From 03d8a2efcd7eec1a7afa18dcaf5c1e3dbc0f6531 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 05 九月 2026 13:39:45 +0800
Subject: [PATCH] 对齐测试删除和时间显示并补齐全链路验收
---
src/api/testTypes.ts | 5 +
src/views/TestList.vue | 4
tests/e2e/runtime-without-simulator.spec.ts | 16 +++++
src/api/batteryGroups.ts | 5 +
src/api/deviceCollectors.ts | 5 +
src/api/deviceCabinets.ts | 5 +
src/api/batteryGroupFields.ts | 5 +
tests/e2e/support/ticket04-stack.ts | 22 ++++--
tests/e2e/test-management-acceptance.spec.ts | 86 +++++++++++++++++++++++++++-
src/api/consoleData.ts | 18 ------
10 files changed, 128 insertions(+), 43 deletions(-)
diff --git a/src/api/batteryGroupFields.ts b/src/api/batteryGroupFields.ts
index a664577..ee3bb75 100644
--- a/src/api/batteryGroupFields.ts
+++ b/src/api/batteryGroupFields.ts
@@ -1,4 +1,5 @@
import { request, type ApiResponse } from './request'
+import { formatBusinessTime } from '@/utils/businessTime'
export type BatteryGroupFieldStatus = '启用' | '禁用'
export type BatteryGroupFieldType = '文本' | '数字' | '时间' | '备注'
@@ -8,7 +9,7 @@
fieldName: string | null
fieldType: string | null
createBy: string | null
- createTime: string | null
+ createTime: number | null
status: string | null
}
@@ -51,7 +52,7 @@
name: item.fieldName || '',
type: mapBatteryGroupFieldType(item.fieldType),
creator: item.createBy || '-',
- createdAt: item.createTime || '',
+ createdAt: formatBusinessTime(item.createTime),
status: item.status === '1' ? '禁用' : '启用',
}))
}
diff --git a/src/api/batteryGroups.ts b/src/api/batteryGroups.ts
index b838f99..94c12ff 100644
--- a/src/api/batteryGroups.ts
+++ b/src/api/batteryGroups.ts
@@ -1,4 +1,5 @@
import { request, type ApiResponse } from './request'
+import { formatBusinessTime } from '@/utils/businessTime'
import type { BatteryGroupPayload, GroupStatus } from './batteryGroupPayload'
export type { GroupStatus } from './batteryGroupPayload'
@@ -34,7 +35,7 @@
purpose: string | null
status: string | null
createBy: string | null
- createTime: string | null
+ createTime: number | null
batteryCount: number | null
remark?: string | null
z?: string | null
@@ -114,7 +115,7 @@
model: item.model || '-',
purpose: item.purpose || '-',
batteryCount: Number(item.batteryCount) || 0,
- createdAt: item.createTime || '-',
+ createdAt: formatBusinessTime(item.createTime),
status: item.status === '1' ? '禁用' : '启用',
creator: item.createBy || '-',
templateFields: (item.templateFields || [])
diff --git a/src/api/consoleData.ts b/src/api/consoleData.ts
index 8dcd2ad..eb94544 100644
--- a/src/api/consoleData.ts
+++ b/src/api/consoleData.ts
@@ -9,17 +9,6 @@
CYCLE: { recordNo: '记录编号', batteryNo: '电池号', recordedAt: '设备时间', cycleNo: '循环序号', chargeCapacity: '充电容量(Ah)', dischargeCapacity: '放电容量(Ah)', efficiency: '充放电效率(%)', chargeEnergy: '充电能量(Wh)', dischargeEnergy: '放电能量(Wh)' },
} satisfies Record<ConsoleDataType, Record<string, string>>
-export interface ConsoleDataOverride {
- overrideId: number
- testId: number
- dataType: ConsoleDataType
- stableIdentity: string
- fieldValues: string | null
- deleted: boolean
- actionId: number
- createdAtUtc: string
-}
-
export interface ConsoleDataActionPayload {
dataType: ConsoleDataType
operationType: ConsoleDataOperation
@@ -32,16 +21,9 @@
fieldValues: string | null
deleted: boolean
}>
- btsSampleIds?: number[]
- collectorSampleIds?: number[]
}
-interface OverrideResponse extends ApiResponse { data: ConsoleDataOverride[] }
interface ActionResponse extends ApiResponse { actionId: number }
-
-export async function getConsoleDataOverrides(testId: number, dataType: ConsoleDataType) {
- return (await request<OverrideResponse>(`/system/test/${testId}/console-data/${dataType}/overrides`)).data || []
-}
export async function submitConsoleDataAction(testId: number, payload: ConsoleDataActionPayload) {
return request<ActionResponse>(`/system/test/${testId}/console-data/actions`, {
diff --git a/src/api/deviceCabinets.ts b/src/api/deviceCabinets.ts
index 0497805..b9d1100 100644
--- a/src/api/deviceCabinets.ts
+++ b/src/api/deviceCabinets.ts
@@ -6,6 +6,7 @@
DeviceCabinetRecord,
} from '@/stores/deviceCabinets'
import { request, type ApiResponse } from './request'
+import { formatBusinessTime } from '@/utils/businessTime'
export interface DeviceCabinetListParams {
pageNum: number
@@ -33,7 +34,7 @@
currentTest: string | null
status: string | null
remark: string | null
- createTime: string | null
+ createTime: number | null
}
interface DetectionCabinetListResponse extends ApiResponse {
@@ -108,7 +109,7 @@
testStatus: testStatusMap[item.testStatus || ''] || '空闲',
currentTest: item.currentTest || '',
status: statusMap[item.status || ''] || '禁用',
- createdAt: item.createTime || '',
+ createdAt: formatBusinessTime(item.createTime),
}
}
diff --git a/src/api/deviceCollectors.ts b/src/api/deviceCollectors.ts
index 7cedd80..878f909 100644
--- a/src/api/deviceCollectors.ts
+++ b/src/api/deviceCollectors.ts
@@ -6,6 +6,7 @@
DeviceCollectorRecord,
} from '@/stores/deviceCollectors'
import { request, type ApiResponse } from './request'
+import { formatBusinessTime } from '@/utils/businessTime'
export interface DeviceCollectorListParams {
pageNum: number
@@ -32,7 +33,7 @@
currentTest: string | null
status: string | null
remark: string | null
- createTime: string | null
+ createTime: number | null
}
interface CollectorListResponse extends ApiResponse {
@@ -116,7 +117,7 @@
testStatus: testStatusMap[item.testStatus || ''] || '待检测',
currentTest: item.currentTest || '',
status: statusMap[item.status || ''] || '禁用',
- createdAt: item.createTime || '',
+ createdAt: formatBusinessTime(item.createTime),
}
}
diff --git a/src/api/testTypes.ts b/src/api/testTypes.ts
index 8b395f4..35a6c93 100644
--- a/src/api/testTypes.ts
+++ b/src/api/testTypes.ts
@@ -1,5 +1,6 @@
import type { TestTypeRecord, TestTypeStatus } from '@/stores/testTypes'
import { request, type ApiResponse } from './request'
+import { formatBusinessTime } from '@/utils/businessTime'
export interface TestTypeListParams {
pageNum: number
@@ -16,7 +17,7 @@
testTypeName: string | null
status: string | null
createBy: string | null
- createTime: string | null
+ createTime: number | null
remark: string | null
}
@@ -45,7 +46,7 @@
return {
id: item.testTypeId,
name: item.testTypeName || '-',
- createdAt: item.createTime || '',
+ createdAt: formatBusinessTime(item.createTime),
creator: item.createBy || '-',
remark: item.remark || '',
status: statusMap[item.status || ''] || '禁用',
diff --git a/src/views/TestList.vue b/src/views/TestList.vue
index a8284a1..cb3b722 100644
--- a/src/views/TestList.vue
+++ b/src/views/TestList.vue
@@ -117,7 +117,7 @@
async function removeTest(item: TestRecord) {
try {
- await ElMessageBox.confirm(`删除测试“${item.name}”后无法恢复,是否继续?`, '确认删除测试', {
+ await ElMessageBox.confirm(`删除测试“${item.name}”将一并删除全部测试数据、绑定、阈值、修订和异常记录,且无法恢复,是否继续?`, '确认删除测试', {
confirmButtonText: '删除', cancelButtonText: '取消', type: 'warning', confirmButtonClass: 'danger-confirm',
})
const deletionPage = currentPage.value
@@ -242,7 +242,7 @@
<div class="row-actions">
<button type="button" @click="openConsole(item)">控制台</button>
<button v-if="item.editable" type="button" @click="editTest(item)">编辑</button>
- <button v-if="item.editable" class="delete-action" type="button" :disabled="deletingTestId !== null" @click="removeTest(item)">{{ deletingTestId === item.id ? '删除中...' : '删除' }}</button>
+ <button class="delete-action" type="button" :disabled="deletingTestId !== null" @click="removeTest(item)">{{ deletingTestId === item.id ? '删除中...' : '删除' }}</button>
</div>
</td>
</tr>
diff --git a/tests/e2e/runtime-without-simulator.spec.ts b/tests/e2e/runtime-without-simulator.spec.ts
new file mode 100644
index 0000000..b1131f2
--- /dev/null
+++ b/tests/e2e/runtime-without-simulator.spec.ts
@@ -0,0 +1,16 @@
+import { expect, test } from '@playwright/test'
+import { Ticket04Stack } from './support/ticket04-stack'
+
+const stack = new Ticket04Stack()
+test.beforeAll(async () => stack.start('druid'))
+test.afterAll(async () => stack.stop())
+
+test('无模拟器成品包以无设备和 BTS 模式完成启动及重复迁移', async ({ request }) => {
+ expect((await request.get(`${stack.backendUrl}/captchaImage`)).ok()).toBe(true)
+ expect(stack.queryDatabase('SELECT COUNT(*) FROM t_device_adapter')).toBe('0')
+ const migrations = stack.queryDatabase('SELECT GROUP_CONCAT(version ORDER BY installed_rank) FROM flyway_schema_history WHERE success=1')
+ expect(migrations).toBe('1,2,3,4,5')
+ await stack.restartBackend('druid,bts')
+ expect((await request.get(`${stack.backendUrl}/captchaImage`)).ok()).toBe(true)
+ expect(stack.queryDatabase('SELECT GROUP_CONCAT(version ORDER BY installed_rank) FROM flyway_schema_history WHERE success=1')).toBe(migrations)
+})
diff --git a/tests/e2e/support/ticket04-stack.ts b/tests/e2e/support/ticket04-stack.ts
index ee44333..88d685c 100644
--- a/tests/e2e/support/ticket04-stack.ts
+++ b/tests/e2e/support/ticket04-stack.ts
@@ -87,7 +87,7 @@
readonly backendUrl = `http://127.0.0.1:${apiPort}`
- async start() {
+ async start(profiles = 'druid,dev-simulator') {
await Promise.all([mysqlPort, redisPort, apiPort, simulatorPort].map(assertPortAvailable))
this.docker = resolveDocker()
mkdirSync(artifactDir, { recursive: true })
@@ -107,7 +107,7 @@
])
await this.waitForContainers()
this.buildBackend()
- await this.startBackend()
+ await this.startBackend(profiles)
this.disableCaptchaInIsolatedDatabase()
} catch (error) {
await this.stop()
@@ -115,9 +115,15 @@
}
}
- async restartBackend() {
+ async restartBackend(profiles = 'druid,dev-simulator') {
await this.stopBackend()
- await this.startBackend()
+ await this.startBackend(profiles)
+ }
+
+ queryDatabase(sql: string) {
+ if (!/^SELECT\s/i.test(sql)) throw new Error('验收查询只允许 SELECT')
+ return this.dockerRun(['exec', this.mysqlContainer, 'mysql', '-uroot', `-p${mysqlPassword}`,
+ '--database=battery_detection', '--batch', '--skip-column-names', '-e', sql]).stdout.trim()
}
redisCommand(...args: string[]) {
@@ -189,10 +195,10 @@
if (!existsSync(backendJar)) throw new Error(`未生成后端可执行包: ${backendJar}`)
}
- private async startBackend() {
+ private async startBackend(profiles = 'druid,dev-simulator') {
const logPath = resolve(artifactDir, 'backend.log')
const log = createWriteStream(logPath, { flags: 'a' })
- const jdbcUrl = `jdbc:mysql://127.0.0.1:${mysqlPort}/battery_detection?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8`
+ const jdbcUrl = `jdbc:mysql://127.0.0.1:${mysqlPort}/battery_detection?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&connectionTimeZone=UTC&forceConnectionTimeZoneToSession=true`
this.backend = spawn('java', [
'-jar', backendJar,
`--server.port=${apiPort}`,
@@ -203,7 +209,7 @@
`--spring.data.redis.port=${redisPort}`,
`--spring.data.redis.password=${redisPassword}`,
'--spring.data.redis.database=0',
- '--spring.profiles.active=druid,dev-simulator',
+ `--spring.profiles.active=${profiles}`,
'--spring.devtools.restart.enabled=false',
`--battery.dev-simulator.port=${simulatorPort}`,
`--ruoyi.profile=${artifactDir}`,
@@ -218,7 +224,7 @@
await waitUntil(async () => {
if (this.backend?.exitCode !== null) throw new Error(`后端提前退出,详见 ${logPath}`)
try {
- return (await fetch(`${this.backendUrl}/dev/bts-simulator/state`)).ok
+ return (await fetch(`${this.backendUrl}/captchaImage`)).ok
} catch {
return false
}
diff --git a/tests/e2e/test-management-acceptance.spec.ts b/tests/e2e/test-management-acceptance.spec.ts
index 7a8aa2a..3cfee33 100644
--- a/tests/e2e/test-management-acceptance.spec.ts
+++ b/tests/e2e/test-management-acceptance.spec.ts
@@ -9,9 +9,11 @@
}
interface PersistedRow {
+ id: string
recordNo: string
batteryNo: string
stableIdentity?: string
+ sequenceId?: number | null
voltage?: number | string | null
endVoltage?: number | string | null
dischargeCapacity?: number | string | null
@@ -124,6 +126,7 @@
await page.getByPlaceholder('输入电池号').fill(names.battery)
await page.getByRole('button', { name: '保存新建电池组', exact: true }).click()
await expect(page.locator('tbody tr').filter({ hasText: names.group })).toBeVisible()
+ expect(stack.queryDatabase("SELECT field_value FROM t_battery_group_relation_field relation JOIN t_battery_group_field definition ON definition.field_id=relation.battery_group_field_id WHERE definition.field_name='F' AND relation.del_flag=0")).toBe('2')
}
async function createTest(page: Page, names: Record<string, string>) {
@@ -217,7 +220,9 @@
await expect(page.locator('.running-state')).toHaveText('暂停')
await expect(page.locator('.reception-state')).toHaveText('暂停接收')
await expect(page.locator('.cell-card .temperature')).toHaveText('-')
- const pausedCount = (await persistedRows(page, testId, 'records')).length
+ const pausedRows = await persistedRows(page, testId, 'records')
+ const pausedCount = pausedRows.length
+ const pausedCabinetSequence = Math.max(0, ...pausedRows.map(row => Number(row.sequenceId) || 0))
await page.waitForTimeout(1_500)
expect((await persistedRows(page, testId, 'records')).length).toBe(pausedCount)
@@ -225,6 +230,8 @@
await page.getByRole('button', { name: '继续接收', exact: true }).last().click()
await expect(page.locator('.running-state')).toHaveText('检测中')
await expect.poll(async () => (await persistedRows(page, testId, 'records')).length).toBeGreaterThan(pausedCount)
+ await expect.poll(async () => Math.max(0, ...(await persistedRows(page, testId, 'records')).map(row => Number(row.sequenceId) || 0)))
+ .toBeGreaterThan(pausedCabinetSequence)
})
await test.step('三类当前有效数据可修订并形成统一修订记录', async () => {
@@ -241,13 +248,15 @@
await editFirstRow(page, '循环', '放电容量', '4.0000', 'Ticket06 循环数据修订')
await page.getByRole('button', { name: '实时', exact: true }).click()
- const recordsBeforeRemoval = (await persistedRows(page, testId, 'records')).length
+ const firstRowText = await page.locator('.console-data-panel tbody tr').first().innerText()
+ const recordToRemove = (await persistedRows(page, testId, 'records')).find(row => firstRowText.includes(row.recordNo))
+ expect(recordToRemove).toBeDefined()
await page.locator('.console-data-panel tbody tr').first().getByRole('button', { name: '删除', exact: true }).click()
- await expect(page.getByRole('dialog', { name: '移除数据' })).toBeVisible()
+ await expect(page.getByRole('dialog', { name: '物理删除数据' })).toBeVisible()
await page.locator('.el-message-box__input input').fill('Ticket06 删除当前有效数据')
await page.getByRole('button', { name: '确定', exact: true }).click()
await expect(page.getByRole('alert').filter({ hasText: '已从当前有效视图移除 1 条数据' })).toBeVisible()
- await expect.poll(async () => (await persistedRows(page, testId, 'records')).length).toBe(recordsBeforeRemoval - 1)
+ await expect.poll(async () => (await persistedRows(page, testId, 'records')).some(row => row.id === recordToRemove?.id)).toBe(false)
await page.getByRole('button', { name: '修订记录', exact: true }).click()
await expect(page).toHaveURL(/\/data-revision/)
@@ -302,6 +311,8 @@
await page.getByRole('button', { name: '工步图表', exact: true }).click()
await expect(page.locator('.detail-meta input')).toHaveValue('Ticket06 最新测试详情')
expect((await persistedRows(page, testId, 'records')).length).toBeGreaterThan(0)
+ expect((await persistedRows(page, testId, 'steps')).some(row => Number(row.endVoltage) === 3.2222)).toBe(true)
+ expect((await persistedRows(page, testId, 'cycles')).some(row => Number(row.dischargeCapacity) === 4)).toBe(true)
})
await test.step('停止立即进入完成态,异常事实仍可人工关闭追溯', async () => {
@@ -318,7 +329,7 @@
})
await page.getByRole('button', { name: '停止测试', exact: true }).click()
await page.getByRole('button', { name: '停止测试', exact: true }).last().click()
- await expect(page.locator('.running-state')).toHaveText('检测完成')
+ await expect(page.locator('.running-state')).toHaveText('检测中')
await expect(page.getByRole('alert').filter({ hasText: '模拟停止失败' })).toBeVisible()
await expect(page.locator('.project-meta')).toContainText('检测中')
await page.unroute(`**/dev-api/system/test/${testId}/reception/end`)
@@ -347,10 +358,75 @@
expect(warningsAfterClose.rows.some(item => item.exceptionStatus === 'CLOSED')).toBe(true)
})
+ await test.step('三类导入直接落表,修改当前 F 后已有测试读取新值', async () => {
+ for (const [index, kind] of ['REALTIME', 'STEP', 'CYCLE'].entries()) {
+ const row = { recordNo: `IMPORT-${kind}`, batteryNo: names.battery, recordedAt: Date.now() + 3_600_000 + index,
+ cycleNo: 999, stepNo: 1, stepName: '人工核对', sequenceId: 1, voltage: 3.8, current: 1,
+ capacity: 2, energy: 4, endVoltage: 3.9, startVoltage: 3.1, stepDuration: 60,
+ chargeCapacity: 2, dischargeCapacity: 1.9, chargeEnergy: 4, dischargeEnergy: 3.8, efficiency: 95 }
+ const result = await apiJson<ApiResult<unknown>>(page, `/system/test/${testId}/console-data/actions`, {
+ method: 'POST', body: JSON.stringify({ dataType: kind, operationType: 'IMPORT', scopeSummary: '导入一条核对记录',
+ identitySummary: '[]', changesSummary: JSON.stringify([row]), reason: 'Ticket13 导入验收' }),
+ })
+ expect(result.code).toBe(200)
+ const table = `t_test_${kind.toLowerCase()}_record`
+ expect(stack.queryDatabase(`SELECT COUNT(*) FROM ${table} WHERE test_id=${testId} AND source_identity='IMPORT'`)).toBe('1')
+ const endpoint = kind === 'REALTIME' ? 'records' : kind === 'STEP' ? 'steps' : 'cycles'
+ expect((await persistedRows(page, testId, endpoint)).some(item => item.recordNo === row.recordNo)).toBe(true)
+ if (kind === 'REALTIME') expect(stack.queryDatabase(`SELECT cabinet_sequence_id FROM ${table} WHERE test_id=${testId} AND source_identity='IMPORT'`)).toBe('1')
+ }
+ const detail = await apiJson<ApiResult<{ batteries: Array<{ groupId: number }> }>>(page, `/system/test/${testId}`)
+ const groupId = detail.data.batteries[0]!.groupId
+ const group = await apiJson<ApiResult<Record<string, unknown> & { batteries: Array<{ batteryNo: string }> }>>(page, `/system/batteryGroup/${groupId}`)
+ const updated = await apiJson<ApiResult<unknown>>(page, '/system/batteryGroup', { method: 'PUT',
+ body: JSON.stringify({ ...group.data, f: '4', batteryNos: group.data.batteries.map(battery => battery.batteryNo) }) })
+ expect(updated.code).toBe(200)
+ expect((await apiJson<ApiResult<{ f: string }>>(page, `/system/batteryGroup/${groupId}`)).data.f).toBe('4')
+ const current = await apiJson<ApiResult<{ batteries: Array<{ fields: Array<{ fieldName: string; fieldValue: string }> }> }>>(page, `/system/test/${testId}`)
+ expect(current.data.batteries[0]!.fields.find(field => field.fieldName === 'F')?.fieldValue).toBe('4')
+ await page.goto(`/test-list/${testId}/console?tab=project-chart`)
+ await expect(page.getByText(/电池组 F 不可用/)).toHaveCount(0)
+ })
+
await test.step('设备协议日志只包含发现和实时查询', async () => {
await page.goto(`${stack.backendUrl}/dev/bts-simulator.html`)
const commands = await page.locator('#requests .request-command').allTextContents()
expect(commands.length).toBeGreaterThan(0)
expect(commands.every(command => command === 'getdevinfo' || command === 'inquire')).toBe(true)
})
+
+ await test.step('同通道跨测试复用,所有状态整体删除无痕且不影响其他事实', async () => {
+ await page.goto(`/test-list/${testId}/console`)
+ const original = await apiJson<ApiResult<Record<string, unknown>>>(page, `/system/test/${testId}`)
+ const deviceCounts = stack.queryDatabase('SELECT (SELECT COUNT(*) FROM t_detection_cabinet), (SELECT COUNT(*) FROM t_collector), (SELECT COUNT(*) FROM t_battery_group)')
+ const tables = ['t_test_realtime_record', 't_test_step_record', 't_test_cycle_record', 't_test_data_revision_action',
+ 't_test_warning_exception', 't_test_logic_step_mapping', 't_test_collector_channel', 't_test_channel_binding',
+ 't_test_warning_threshold', 't_test_battery', 't_test']
+ for (const lifecycle of ['WAITING', 'RUNNING', 'PAUSED']) {
+ const created = await apiJson<ApiResult<{ testId: number }>>(page, '/system/test', {
+ method: 'POST', body: JSON.stringify({ ...original.data, testId: null, testName: `${names.test}-${lifecycle}` }),
+ })
+ expect(created.code).toBe(200)
+ const id = created.data.testId
+ if (lifecycle !== 'WAITING') {
+ expect((await apiJson<ApiResult<unknown>>(page, `/system/test/${id}/reception/start`, { method: 'POST' })).code).toBe(200)
+ await expect.poll(async () => (await persistedRows(page, id, 'records')).length).toBeGreaterThan(0)
+ }
+ if (lifecycle === 'PAUSED') expect((await apiJson<ApiResult<unknown>>(page, `/system/test/${id}/reception/pause`, { method: 'POST' })).code).toBe(200)
+ expect((await apiJson<ApiResult<unknown>>(page, `/system/test/${id}`, { method: 'DELETE' })).code).toBe(200)
+ for (const table of tables) expect(stack.queryDatabase(`SELECT COUNT(*) FROM ${table} WHERE test_id=${id}`)).toBe('0')
+ expect((await apiJson<ApiResult<unknown>>(page, `/system/test/${testId}`)).code).toBe(200)
+ }
+ expect((await apiJson<ApiResult<unknown>>(page, `/system/test/${testId}`, { method: 'DELETE' })).code).toBe(200)
+ for (const table of tables) expect(stack.queryDatabase(`SELECT COUNT(*) FROM ${table} WHERE test_id=${testId}`)).toBe('0')
+ expect(stack.queryDatabase('SELECT COUNT(*) FROM sys_oper_log WHERE business_type=3 AND oper_url LIKE \'%/system/test/%\'')).toBe('0')
+ expect(stack.queryDatabase('SELECT (SELECT COUNT(*) FROM t_detection_cabinet), (SELECT COUNT(*) FROM t_collector), (SELECT COUNT(*) FROM t_battery_group)')).toBe(deviceCounts)
+ })
+
+ await test.step('无设备模式和真实 BTS 装配均可启动', async () => {
+ await stack.restartBackend('druid')
+ expect((await page.request.get(`${stack.backendUrl}/captchaImage`)).ok()).toBe(true)
+ await stack.restartBackend('druid,bts')
+ expect((await page.request.get(`${stack.backendUrl}/captchaImage`)).ok()).toBe(true)
+ })
})
--
Gitblit v1.7.1