156 lines
9.0 KiB
TypeScript
156 lines
9.0 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test('目标账号下拉仅编辑当前账号,保留草稿并定位未选中账号的错误', async ({ page }) => {
|
|
await page.goto('/');
|
|
const session = await (await page.request.get('/api/v1/session')).json();
|
|
const headers = { 'X-CSRF-Token': session.csrfToken };
|
|
const response = await page.request.post('/api/v1/targets', { headers, data: {
|
|
name: '目标账号下拉编辑', type: 'mysql', targetHost: 'fixture.invalid', targetPort: 3306,
|
|
accounts: [
|
|
{ id: 'reader', remark: '读取账号', username: 'reader', password: 'fixture-reader' },
|
|
{ id: 'writer', remark: '写入账号', username: 'writer', password: 'fixture-writer' },
|
|
],
|
|
} });
|
|
expect(response.ok()).toBeTruthy();
|
|
const id = (await response.json()).config.id;
|
|
try {
|
|
await page.reload();
|
|
await page.getByRole('navigation').getByRole('button', { name: /目标服务/ }).click();
|
|
const drawer = page.getByRole('dialog', { name: '编辑目标服务', exact: true });
|
|
const open = async () => {
|
|
await page.locator('.target-card').filter({ hasText: '目标账号下拉编辑' }).getByRole('button', { name: '配置目标', exact: true }).click();
|
|
await drawer.getByRole('tab', { name: '账号', exact: true }).click();
|
|
};
|
|
const editor = drawer.locator('.target-accounts');
|
|
const remark = editor.getByRole('textbox', { name: '账号备注', exact: true });
|
|
const username = editor.getByRole('textbox', { name: '登录用户名', exact: true });
|
|
const password = editor.getByLabel('账号密码', { exact: true });
|
|
const add = editor.getByRole('button', { name: '添加账号', exact: true });
|
|
const remove = editor.getByRole('button', { name: '删除账号', exact: true });
|
|
const select = async (label: string) => {
|
|
await editor.locator('.el-select').filter({ has: page.getByRole('combobox', { name: '编辑目标账号', exact: true }) }).click();
|
|
await page.getByRole('option', { name: label, exact: true }).click();
|
|
};
|
|
await open();
|
|
await expect(editor.locator('.account-fields')).toHaveCount(1);
|
|
await expect(username).toHaveValue('reader');
|
|
await select('2. 写入账号 · writer');
|
|
await remark.fill('修改写入账号');
|
|
await username.fill('updated-writer');
|
|
await password.fill('updated-fixture-writer');
|
|
await add.click();
|
|
await expect(remark).toBeFocused();
|
|
await expect(remark).toHaveValue('');
|
|
await expect(editor.locator('.account-fields')).toHaveCount(1);
|
|
await remark.fill('新增账号');
|
|
await username.fill('new-user');
|
|
await password.fill('fixture-new');
|
|
await select('1. 读取账号 · reader');
|
|
await username.fill('');
|
|
await select('2. 修改写入账号 · updated-writer');
|
|
await expect(password).toHaveValue('updated-fixture-writer');
|
|
await select('3. 新增账号 · new-user');
|
|
await expect(password).toHaveValue('fixture-new');
|
|
await drawer.getByRole('button', { name: '保存配置', exact: true }).click();
|
|
await expect(username).toBeFocused();
|
|
await expect(remark).toHaveValue('读取账号');
|
|
await expect(username).toHaveValue('');
|
|
await username.fill('reader');
|
|
await drawer.getByRole('button', { name: '保存配置', exact: true }).click();
|
|
await expect(drawer).not.toBeVisible();
|
|
const saved = await (await page.request.get(`/api/v1/targets/${id}`)).json();
|
|
expect(saved.config.accounts).toHaveLength(3);
|
|
expect(saved.config.accounts[1]).toMatchObject({ id: 'writer', remark: '修改写入账号', username: 'updated-writer' });
|
|
expect(saved.config.accounts[2]).toMatchObject({ remark: '新增账号', username: 'new-user' });
|
|
for (const account of saved.config.accounts) expect(saved.secretStatus[`account:${account.id}:password`]).toBe(true);
|
|
|
|
await open();
|
|
for (const viewport of [{ width: 1440, height: 900 }, { width: 375, height: 812 }, { width: 320, height: 568 }]) {
|
|
await page.setViewportSize(viewport);
|
|
await expect(add).toBeInViewport();
|
|
await expect(remove).toBeInViewport();
|
|
await expect.poll(() => drawer.evaluate(el => el.scrollWidth <= el.clientWidth + 1)).toBe(true);
|
|
}
|
|
await select('2. 修改写入账号 · updated-writer');
|
|
await remove.click();
|
|
await expect(remark).toHaveValue('新增账号');
|
|
await remove.click();
|
|
await expect(remark).toHaveValue('读取账号');
|
|
await remove.click();
|
|
await expect(editor.locator('.account-fields')).toHaveCount(0);
|
|
await expect(editor.getByRole('combobox', { name: '编辑目标账号', exact: true })).toBeDisabled();
|
|
await expect(remove).toBeDisabled();
|
|
await expect(editor.getByText('点击「添加账号」开始配置。', { exact: true })).toBeVisible();
|
|
await add.click();
|
|
await expect(remark).toBeFocused();
|
|
await expect(remark).toHaveValue('');
|
|
await expect(editor.locator('.account-fields')).toHaveCount(1);
|
|
await remark.fill('重建账号');
|
|
await username.fill('replacement');
|
|
await password.fill('fixture-replacement');
|
|
await drawer.getByRole('button', { name: '保存配置', exact: true }).click();
|
|
await expect(drawer).not.toBeVisible();
|
|
const replaced = await (await page.request.get(`/api/v1/targets/${id}`)).json();
|
|
expect(replaced.config.accounts).toHaveLength(1);
|
|
expect(replaced.config.accounts[0]).toMatchObject({ remark: '重建账号', username: 'replacement' });
|
|
} finally { await page.request.delete(`/api/v1/targets/${id}`, { headers }).catch(() => {}); }
|
|
});
|
|
|
|
test('多账号可在工作区页面添加切换,小屏分组编辑和跨账号错误定位', async ({ page }) => {
|
|
await page.goto('/');
|
|
const session = await (await page.request.get('/api/v1/session')).json();
|
|
const headers = {'X-CSRF-Token':session.csrfToken};
|
|
const response = await page.request.post('/api/v1/proxies', {headers,data:{
|
|
name:'页面账号编辑',type:'mysql',listenHost:'127.0.0.1',listenPort:24923,
|
|
gatewayAccounts:Array.from({length:12},(_,i)=>({id:`account-${i}`,username:`client-${i}`,password:`fixture-${i}`,accessMode:'readonly'})),
|
|
}});
|
|
expect(response.ok()).toBeTruthy();
|
|
const id = (await response.json()).config.id;
|
|
try {
|
|
await page.reload();
|
|
await page.getByRole('row').filter({hasText:'页面账号编辑'}).getByRole('button',{name:'配置',exact:true}).click();
|
|
const workspacePage = page.getByRole('dialog',{name:'编辑网关服务',exact:true});
|
|
await workspacePage.getByRole('tab',{name:'账号',exact:true}).click();
|
|
const editor = workspacePage.locator('.gateway-accounts');
|
|
const body = workspacePage.locator('.workspace-page__body');
|
|
const footer = workspacePage.locator('.workspace-page__footer');
|
|
const select = async (label:string) => {
|
|
await editor.locator('.el-select').filter({has:page.getByRole('combobox',{name:'编辑网关账号',exact:true})}).click();
|
|
await page.getByRole('option',{name:label,exact:true}).click();
|
|
};
|
|
for (const viewport of [{width:1440,height:900},{width:375,height:812},{width:320,height:568}]) {
|
|
await page.setViewportSize(viewport);
|
|
for (const tab of ['登录','目标','权限','更多']) {
|
|
await editor.getByRole('tab',{name:tab,exact:true}).click();
|
|
expect(await workspacePage.evaluate(el=>el.scrollWidth<=el.clientWidth+1)).toBe(true);
|
|
expect(await body.evaluate(el=>el.scrollWidth<=el.clientWidth+1)).toBe(true);
|
|
await editor.getByRole('button',{name:'添加账号',exact:true}).scrollIntoViewIfNeeded();
|
|
await expect(editor.getByRole('button',{name:'添加账号',exact:true})).toBeInViewport();
|
|
await footer.scrollIntoViewIfNeeded();
|
|
await expect(footer).toBeInViewport();
|
|
}
|
|
}
|
|
await editor.getByRole('button',{name:'添加账号',exact:true}).click();
|
|
const username = editor.getByRole('textbox',{name:'用户名',exact:true});
|
|
await expect(username).toBeFocused();
|
|
await expect(username).toBeInViewport();
|
|
await username.fill('new-client');
|
|
await editor.getByRole('textbox',{name:'密码',exact:true}).fill('fixture-new');
|
|
await select('1. client-0');
|
|
await username.fill('');
|
|
await select('13. new-client');
|
|
await expect(username).toHaveValue('new-client');
|
|
await workspacePage.getByRole('button',{name:'保存配置',exact:true}).click();
|
|
await expect(username).toBeFocused();
|
|
await expect(username).toHaveValue('');
|
|
await username.fill('client-0');
|
|
await workspacePage.getByRole('button',{name:'保存配置',exact:true}).click();
|
|
await expect(workspacePage).not.toBeVisible();
|
|
const saved = await (await page.request.get(`/api/v1/proxies/${id}`)).json();
|
|
expect(saved.config.gatewayAccounts).toHaveLength(13);
|
|
expect(saved.config.gatewayAccounts[11]).toMatchObject({username:'client-11',accessMode:'readonly'});
|
|
expect(saved.config.gatewayAccounts[12].username).toBe('new-client');
|
|
for (const account of saved.config.gatewayAccounts) expect(saved.secretStatus[`gatewayAccount:${account.id}:password`]).toBe(true);
|
|
} finally { await page.request.delete(`/api/v1/proxies/${id}`,{headers}).catch(()=>{}); }
|
|
});
|