| package.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| tests/e2e/collector-sampling.spec.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| tests/e2e/shared-fields-and-battery-groups.spec.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| tests/e2e/support/ticket04-stack.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
package.json
@@ -8,7 +8,8 @@ "build": "vue-tsc -b && vite build", "preview": "vite preview", "test:e2e:ticket04": "playwright test tests/e2e/device-registration.spec.ts", "test:e2e:ticket05": "playwright test tests/e2e/shared-fields-and-battery-groups.spec.ts" "test:e2e:ticket05": "playwright test tests/e2e/shared-fields-and-battery-groups.spec.ts", "test:e2e:ticket06": "playwright test tests/e2e/collector-sampling.spec.ts" }, "dependencies": { "@element-plus/icons-vue": "^2.3.2", tests/e2e/collector-sampling.spec.ts
New file @@ -0,0 +1,67 @@ import { expect, test, type Page } from '@playwright/test' import { Ticket04Stack } from './support/ticket04-stack' const stack = new Ticket04Stack() test.beforeAll(async () => stack.start()) test.afterAll(async () => stack.stop()) async function login(page: Page) { await page.goto('/login') await page.locator('input[autocomplete="username"]').fill('admin') await page.locator('input[autocomplete="current-password"]').fill('admin123') await page.getByRole('button', { name: '登录', exact: true }).click() await expect(page).toHaveURL(/\/dashboard$/) } test('采集器登记后可观察独立实时与分页历史采样', async ({ page }) => { await page.goto(`${stack.backendUrl}/dev/bts-simulator.html`) page.once('dialog', dialog => dialog.accept()) await page.getByRole('button', { name: '重置模拟器' }).click() let collector = page.locator('article.device').filter({ has: page.getByRole('heading', { name: 'dev-sim 采集器 1' }) }) await expect(collector.getByText('S-01', { exact: true })).toBeVisible() await expect(collector.getByText('S-04', { exact: true })).toBeVisible() await collector.locator('label').filter({ hasText: '采样间隔(毫秒)' }).locator('input').fill('200') await collector.getByRole('button', { name: '保存配置' }).click() collector = page.locator('article.device').filter({ has: page.getByRole('heading', { name: 'dev-sim 采集器 1' }) }) await collector.getByLabel('S-01 测量项').fill([ 'temperature=28.6 ℃', 'positive_potential=3.812 V', 'negative_potential=-0.116 V', 'dynamic_pressure=101.3 kPa', ].join('\n')) await collector.getByRole('button', { name: '保存测量值' }).first().click() collector = page.locator('article.device').filter({ has: page.getByRole('heading', { name: 'dev-sim 采集器 1' }) }) await expect(collector.getByText(/原始历史 [1-9]\d* 条/)).toBeVisible() await collector.getByRole('button', { name: '查看实时' }).click() await expect(collector.locator('.collector-output')).toContainText('dev-sim-collector-1') await expect(collector.locator('.collector-output')).toContainText('S-01 dynamic_pressure=101.3 kPa') await expect(collector.locator('.collector-output')).toContainText('设备 2026-') await expect(collector.locator('.collector-output')).toContainText('/ 接收 2026-') await collector.getByRole('button', { name: '下载历史' }).click() await expect(collector.locator('.collector-output')).toContainText(/历史 \d+ 条 \/ 本页 \d+ 条/) await login(page) await page.goto('/device-collector/new') await page.getByRole('button', { name: '选择设备' }).click() const candidate = page.locator('.device-table tbody tr').filter({ hasText: 'dev-sim-collector-1' }) await expect(candidate).toBeVisible() await candidate.getByRole('button', { name: '选择' }).click() await page.locator('label').filter({ hasText: '采集器名称' }).locator('input').fill('Ticket06 验收采集器') await page.getByRole('button', { name: '保存', exact: true }).click() await expect(page.locator('tbody tr').filter({ hasText: 'dev-sim-collector-1' })).toBeVisible() await stack.restartBackend() await page.goto(`${stack.backendUrl}/dev/bts-simulator.html`) collector = page.locator('article.device').filter({ has: page.getByRole('heading', { name: 'dev-sim 采集器 1' }) }) await expect(collector.locator('label').filter({ hasText: '采样间隔(毫秒)' }).locator('input')).toHaveValue('200') await expect(collector.getByLabel('S-01 测量项')).toHaveValue(/dynamic_pressure=101\.3 kPa/) await collector.getByRole('button', { name: '下载历史' }).click() await expect(collector.locator('.collector-output')).toContainText('dev-sim-collector-1') const commands = await page.locator('#requests .request-command').allTextContents() expect(commands.every(command => command === 'getdevinfo' || command === 'inquire')).toBe(true) }) tests/e2e/shared-fields-and-battery-groups.spec.ts
@@ -24,14 +24,14 @@ await page.goto('/battery-group/fields') await page.getByRole('button', { name: '新增字段' }).click() await page.locator('.field-dialog label').filter({ hasText: '字段名称' }).locator('input').fill(fieldName) await page.locator('.field-dialog .el-select').click() await page.locator('.field-dialog label').filter({ hasText: '字段类型' }).locator('.el-select__wrapper').click() await page.getByRole('option', { name: '数字', exact: true }).click() await page.getByRole('button', { name: '保存', exact: true }).last().click() await expect(page.locator('tbody tr').filter({ hasText: fieldName })).toBeVisible() await page.goto('/battery-group/new') await page.getByRole('button', { name: '编辑当前模板' }).click() await page.getByRole('checkbox', { name: fieldName, exact: true }).check() await page.locator('.field-checkbox-grid .el-checkbox').filter({ hasText: fieldName }).click() await page.getByRole('button', { name: '另存模板' }).click() await page.locator('.el-message-box__input input').fill(templateName) await page.getByRole('button', { name: '保存', exact: true }).last().click() @@ -41,15 +41,15 @@ await page.locator('label').filter({ hasText: '型号' }).locator('input').fill('M-TICKET05') await page.locator('label').filter({ hasText: '目的' }).locator('textarea').fill('Ticket05 持久化验收') await page.locator('.battery-row input').first().fill(`BAT-${suffix}`) await page.locator('label').filter({ hasText: fieldName }).locator('input').fill('72') await page.getByPlaceholder(`输入${fieldName}`).fill('72') await page.getByRole('button', { name: '保存新建电池组', exact: true }).click() await expect(page).toHaveURL(/\/battery-group$/) await expect(page.locator('tbody tr').filter({ hasText: groupName })).toBeVisible() await page.locator('tbody tr').filter({ hasText: groupName }).getByRole('button', { name: '编辑' }).click() await expect(page.locator('label').filter({ hasText: fieldName }).locator('input')).toHaveValue('72') await expect(page.getByPlaceholder(`输入${fieldName}`)).toHaveValue('72') await expect(page.locator('.battery-row input').first()).toHaveValue(`BAT-${suffix}`) await page.reload() await expect(page.locator('label').filter({ hasText: fieldName }).locator('input')).toHaveValue('72') await expect(page.getByPlaceholder(`输入${fieldName}`)).toHaveValue('72') await expect(page.locator('.battery-row input').first()).toHaveValue(`BAT-${suffix}`) }) tests/e2e/support/ticket04-stack.ts
@@ -15,6 +15,7 @@ const apiPort = Number(process.env.TICKET04_API_PORT || 18001) const mysqlPort = Number(process.env.TICKET04_MYSQL_PORT || 63306) const redisPort = Number(process.env.TICKET04_REDIS_PORT || 56379) const simulatorPort = Number(process.env.TICKET04_SIMULATOR_PORT || 15021) const mysqlImage = process.env.TICKET04_MYSQL_IMAGE || 'public.ecr.aws/docker/library/mysql:8.0.36' const redisImage = process.env.TICKET04_REDIS_IMAGE || 'public.ecr.aws/docker/library/redis:7.2-alpine' const mysqlPassword = 'ticket04-mysql' @@ -87,7 +88,7 @@ readonly backendUrl = `http://127.0.0.1:${apiPort}` async start() { await Promise.all([mysqlPort, redisPort, apiPort].map(assertPortAvailable)) await Promise.all([mysqlPort, redisPort, apiPort, simulatorPort].map(assertPortAvailable)) this.docker = resolveDocker() mkdirSync(artifactDir, { recursive: true }) try { @@ -166,6 +167,7 @@ `--spring.data.redis.password=${redisPassword}`, '--spring.data.redis.database=0', '--spring.devtools.restart.enabled=false', `--battery.dev-simulator.port=${simulatorPort}`, `--ruoyi.profile=${artifactDir}`, ], { cwd: backendRepo,