|
@@ -0,0 +1,636 @@
|
|
|
|
+# 重置高压发生器功能 E2E 测试方案
|
|
|
|
+
|
|
|
|
+## 功能概述
|
|
|
|
+
|
|
|
|
+重置高压发生器功能允许用户通过界面上的RESET按钮重置设备参数,将高压发生器恢复到初始状态。
|
|
|
|
+
|
|
|
|
+## 功能实现分析
|
|
|
|
+
|
|
|
|
+### 数据流
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+UI Button (RESET)
|
|
|
|
+ ↓
|
|
|
|
+handleResetParameters()
|
|
|
|
+ ↓
|
|
|
|
+dispatch(resetDevices()) [Redux Thunk]
|
|
|
|
+ ↓
|
|
|
|
+resetAllDevices() [API]
|
|
|
|
+ ↓
|
|
|
|
+POST /auth/device/action
|
|
|
|
+ ↓
|
|
|
|
+设备重置完成
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### 技术架构
|
|
|
|
+
|
|
|
|
+- **UI层**: ContentAreaLarge.tsx 组件
|
|
|
|
+- **状态管理**: Redux Toolkit (deviceSlice)
|
|
|
|
+- **异步处理**: createAsyncThunk
|
|
|
|
+- **API调用**: axios + interceptor
|
|
|
|
+
|
|
|
|
+### Redux状态管理
|
|
|
|
+
|
|
|
|
+```typescript
|
|
|
|
+interface DeviceState {
|
|
|
|
+ status: 'idle' | 'loading' | 'succeeded' | 'failed';
|
|
|
|
+ error: string | null;
|
|
|
|
+ deviceError: string | null;
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### API请求格式
|
|
|
|
+
|
|
|
|
+```json
|
|
|
|
+POST /auth/device/action
|
|
|
|
+{
|
|
|
|
+ "deviceUri": "DIOS/DEVICE/Generator",
|
|
|
|
+ "reqName": "RESET",
|
|
|
|
+ "reqParam": "",
|
|
|
|
+ "reqTransaction": "",
|
|
|
|
+ "reqClientID": ""
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### API响应格式
|
|
|
|
+
|
|
|
|
+**成功响应**:
|
|
|
|
+```json
|
|
|
|
+{
|
|
|
|
+ "code": "0x000000",
|
|
|
|
+ "description": "Success",
|
|
|
|
+ "data": {}
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+**失败响应**:
|
|
|
|
+```json
|
|
|
|
+{
|
|
|
|
+ "code": "0x010001",
|
|
|
|
+ "description": "设备通信失败",
|
|
|
|
+ "solution": "检查设备连接"
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## 测试套件设计
|
|
|
|
+
|
|
|
|
+### 测试套件:重置高压发生器功能
|
|
|
|
+
|
|
|
|
+**文件路径**: `cypress/e2e/exam/reset-generator.cy.ts`
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+#### TC-RESET-01: 成功重置设备
|
|
|
|
+
|
|
|
|
+**测试目标**: 验证正常重置流程
|
|
|
|
+
|
|
|
|
+**前置条件**:
|
|
|
|
+- 已登录系统
|
|
|
|
+- 已进入检查页面
|
|
|
|
+- Mock所有依赖API(quota、i18n等)
|
|
|
|
+
|
|
|
|
+**测试步骤**:
|
|
|
|
+1. Mock设备重置API成功响应
|
|
|
|
+2. 定位RESET按钮
|
|
|
|
+3. 验证按钮初始状态为可用
|
|
|
|
+4. 点击RESET按钮
|
|
|
|
+5. 验证按钮变为禁用状态(loading)
|
|
|
|
+6. 等待API调用完成
|
|
|
|
+7. 验证按钮恢复为可用状态
|
|
|
|
+8. 验证Redux状态更新为'succeeded'
|
|
|
|
+
|
|
|
|
+**验证点**:
|
|
|
|
+- ✅ 按钮可点击
|
|
|
|
+- ✅ 点击后按钮禁用(disabled=true)
|
|
|
|
+- ✅ API调用成功(code='0x000000')
|
|
|
|
+- ✅ 按钮恢复可用状态
|
|
|
|
+- ✅ Redux状态: status='succeeded'
|
|
|
|
+- ✅ 无错误提示
|
|
|
|
+
|
|
|
|
+**Mock配置**:
|
|
|
|
+```typescript
|
|
|
|
+cy.intercept('POST', '/auth/device/action', (req) => {
|
|
|
|
+ if (req.body.reqName === 'RESET') {
|
|
|
|
+ req.reply({
|
|
|
|
+ statusCode: 200,
|
|
|
|
+ body: {
|
|
|
|
+ code: '0x000000',
|
|
|
|
+ description: 'Success',
|
|
|
|
+ data: {}
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+}).as('resetDevice');
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+#### TC-RESET-02: API失败处理
|
|
|
|
+
|
|
|
|
+**测试目标**: 验证重置失败时的错误处理
|
|
|
|
+
|
|
|
|
+**前置条件**:
|
|
|
|
+- 已登录系统
|
|
|
|
+- 已进入检查页面
|
|
|
|
+
|
|
|
|
+**测试步骤**:
|
|
|
|
+1. Mock设备重置API失败响应
|
|
|
|
+2. 点击RESET按钮
|
|
|
|
+3. 等待API调用完成
|
|
|
|
+4. 验证Redux状态更新为'failed'
|
|
|
|
+5. 验证错误信息存储到state.error
|
|
|
|
+6. 验证按钮恢复可用
|
|
|
|
+7. 验证控制台输出错误日志
|
|
|
|
+
|
|
|
|
+**验证点**:
|
|
|
|
+- ✅ API返回非'0x000000'错误码
|
|
|
|
+- ✅ Redux状态: status='failed'
|
|
|
|
+- ✅ 错误信息存储到state.error
|
|
|
|
+- ✅ 按钮恢复可用
|
|
|
|
+- ✅ 控制台输出错误日志
|
|
|
|
+
|
|
|
|
+**Mock配置**:
|
|
|
|
+```typescript
|
|
|
|
+cy.intercept('POST', '/auth/device/action', {
|
|
|
|
+ statusCode: 200,
|
|
|
|
+ body: {
|
|
|
|
+ code: '0x010001',
|
|
|
|
+ description: '设备通信失败',
|
|
|
|
+ solution: '检查设备连接'
|
|
|
|
+ }
|
|
|
|
+}).as('resetDeviceFail');
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+#### TC-RESET-03: 按钮禁用状态管理
|
|
|
|
+
|
|
|
|
+**测试目标**: 验证loading期间按钮状态管理
|
|
|
|
+
|
|
|
|
+**前置条件**:
|
|
|
|
+- 已登录系统
|
|
|
|
+- 已进入检查页面
|
|
|
|
+
|
|
|
|
+**测试步骤**:
|
|
|
|
+1. Mock设备重置API延迟响应(2秒)
|
|
|
|
+2. 点击RESET按钮
|
|
|
|
+3. 验证按钮立即禁用
|
|
|
|
+4. 验证disabled属性为true
|
|
|
|
+5. 等待1秒,验证按钮仍然禁用
|
|
|
|
+6. 等待API响应完成
|
|
|
|
+7. 验证按钮恢复可用
|
|
|
|
+
|
|
|
|
+**验证点**:
|
|
|
|
+- ✅ 点击后按钮立即禁用
|
|
|
|
+- ✅ disabled属性为true
|
|
|
|
+- ✅ 响应前按钮保持禁用
|
|
|
|
+- ✅ 响应后按钮恢复可用
|
|
|
|
+- ✅ Redux状态正确转换: idle → loading → succeeded
|
|
|
|
+
|
|
|
|
+**Mock配置**:
|
|
|
|
+```typescript
|
|
|
|
+cy.intercept('POST', '/auth/device/action', (req) => {
|
|
|
|
+ req.reply({
|
|
|
|
+ statusCode: 200,
|
|
|
|
+ body: {
|
|
|
|
+ code: '0x000000',
|
|
|
|
+ description: 'Success',
|
|
|
|
+ data: {}
|
|
|
|
+ },
|
|
|
|
+ delay: 2000
|
|
|
|
+ });
|
|
|
|
+}).as('resetDeviceDelay');
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+#### TC-RESET-04: 网络错误处理
|
|
|
|
+
|
|
|
|
+**测试目标**: 验证网络异常场景的错误处理
|
|
|
|
+
|
|
|
|
+**前置条件**:
|
|
|
|
+- 已登录系统
|
|
|
|
+- 已进入检查页面
|
|
|
|
+
|
|
|
|
+**测试步骤**:
|
|
|
|
+1. Mock网络错误
|
|
|
|
+2. 点击RESET按钮
|
|
|
|
+3. 等待错误发生
|
|
|
|
+4. 验证Redux状态更新为'failed'
|
|
|
|
+5. 验证错误信息被捕获
|
|
|
|
+6. 验证按钮恢复可用
|
|
|
|
+7. 验证用户可以重试
|
|
|
|
+
|
|
|
|
+**验证点**:
|
|
|
|
+- ✅ 捕获网络错误
|
|
|
|
+- ✅ Redux状态: status='failed'
|
|
|
|
+- ✅ 错误信息存储
|
|
|
|
+- ✅ 状态恢复正常
|
|
|
|
+- ✅ 用户可重试操作
|
|
|
|
+
|
|
|
|
+**Mock配置**:
|
|
|
|
+```typescript
|
|
|
|
+cy.intercept('POST', '/auth/device/action', {
|
|
|
|
+ forceNetworkError: true
|
|
|
|
+}).as('resetDeviceNetworkError');
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+#### TC-RESET-05: 防止重复点击
|
|
|
|
+
|
|
|
|
+**测试目标**: 验证loading状态下防止重复操作
|
|
|
|
+
|
|
|
|
+**前置条件**:
|
|
|
|
+- 已登录系统
|
|
|
|
+- 已进入检查页面
|
|
|
|
+
|
|
|
|
+**测试步骤**:
|
|
|
|
+1. Mock设备重置API延迟响应(3秒)
|
|
|
|
+2. 点击RESET按钮
|
|
|
|
+3. 立即再次尝试点击按钮
|
|
|
|
+4. 验证第二次点击无效
|
|
|
|
+5. 验证只发送了一次API请求
|
|
|
|
+6. 等待第一次请求完成
|
|
|
|
+7. 验证可以再次点击
|
|
|
|
+
|
|
|
|
+**验证点**:
|
|
|
|
+- ✅ loading时按钮禁用
|
|
|
|
+- ✅ 再次点击无效
|
|
|
|
+- ✅ 只发送一次API请求
|
|
|
|
+- ✅ 完成后才能再次点击
|
|
|
|
+- ✅ 防抖机制有效
|
|
|
|
+
|
|
|
|
+**Mock配置**:
|
|
|
|
+```typescript
|
|
|
|
+let requestCount = 0;
|
|
|
|
+cy.intercept('POST', '/auth/device/action', (req) => {
|
|
|
|
+ requestCount++;
|
|
|
|
+ req.reply({
|
|
|
|
+ statusCode: 200,
|
|
|
|
+ body: {
|
|
|
|
+ code: '0x000000',
|
|
|
|
+ description: 'Success',
|
|
|
|
+ data: {}
|
|
|
|
+ },
|
|
|
|
+ delay: 3000
|
|
|
|
+ });
|
|
|
|
+}).as('resetDeviceMultiple');
|
|
|
|
+
|
|
|
|
+// 验证requestCount === 1
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## Page Object Model 设计
|
|
|
|
+
|
|
|
|
+### ExamPage 扩展
|
|
|
|
+
|
|
|
|
+**文件**: `cypress/support/pageObjects/ExamPage.ts`
|
|
|
|
+
|
|
|
|
+```typescript
|
|
|
|
+class ExamPage {
|
|
|
|
+ // ... 现有方法
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取重置高压发生器按钮
|
|
|
|
+ */
|
|
|
|
+ getResetGeneratorButton() {
|
|
|
|
+ return cy.get('[data-testid="reset-generator-btn"]');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 点击重置按钮
|
|
|
|
+ */
|
|
|
|
+ clickResetGenerator() {
|
|
|
|
+ this.getResetGeneratorButton().click();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 验证重置按钮为启用状态
|
|
|
|
+ */
|
|
|
|
+ verifyResetButtonEnabled() {
|
|
|
|
+ this.getResetGeneratorButton()
|
|
|
|
+ .should('be.visible')
|
|
|
|
+ .should('not.be.disabled');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 验证重置按钮为禁用状态
|
|
|
|
+ */
|
|
|
|
+ verifyResetButtonDisabled() {
|
|
|
|
+ this.getResetGeneratorButton()
|
|
|
|
+ .should('be.visible')
|
|
|
|
+ .should('be.disabled');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 等待重置操作完成
|
|
|
|
+ */
|
|
|
|
+ waitForResetComplete() {
|
|
|
|
+ cy.wait('@resetDevice');
|
|
|
|
+ this.verifyResetButtonEnabled();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 验证Redux设备状态
|
|
|
|
+ * @param expectedStatus - 期望的状态: 'idle' | 'loading' | 'succeeded' | 'failed'
|
|
|
|
+ */
|
|
|
|
+ verifyDeviceStatus(expectedStatus: string) {
|
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
|
+ .its('device').its('status')
|
|
|
|
+ .should('eq', expectedStatus);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 验证设备错误信息
|
|
|
|
+ * @param expectedError - 期望的错误信息,null表示无错误
|
|
|
|
+ */
|
|
|
|
+ verifyDeviceError(expectedError: string | null) {
|
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
|
+ .its('device').its('error')
|
|
|
|
+ .should('eq', expectedError);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## Mock Handlers 设计
|
|
|
|
+
|
|
|
|
+### 文件结构
|
|
|
|
+
|
|
|
|
+**文件**: `cypress/support/mock/handlers/deviceActions.ts`
|
|
|
|
+
|
|
|
|
+```typescript
|
|
|
|
+/**
|
|
|
|
+ * Mock设备重置成功响应
|
|
|
|
+ */
|
|
|
|
+export const mockResetDeviceSuccess = () => {
|
|
|
|
+ cy.intercept('POST', '/auth/device/action', (req) => {
|
|
|
|
+ if (req.body.reqName === 'RESET') {
|
|
|
|
+ req.reply({
|
|
|
|
+ statusCode: 200,
|
|
|
|
+ body: {
|
|
|
|
+ code: '0x000000',
|
|
|
|
+ description: 'Success',
|
|
|
|
+ data: {}
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }).as('resetDevice');
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Mock设备重置失败响应
|
|
|
|
+ * @param errorCode - 错误码,默认为'0x010001'
|
|
|
|
+ * @param description - 错误描述
|
|
|
|
+ */
|
|
|
|
+export const mockResetDeviceFail = (
|
|
|
|
+ errorCode: string = '0x010001',
|
|
|
|
+ description: string = '设备通信失败'
|
|
|
|
+) => {
|
|
|
|
+ cy.intercept('POST', '/auth/device/action', {
|
|
|
|
+ statusCode: 200,
|
|
|
|
+ body: {
|
|
|
|
+ code: errorCode,
|
|
|
|
+ description: description,
|
|
|
|
+ solution: '检查设备连接'
|
|
|
|
+ }
|
|
|
|
+ }).as('resetDeviceFail');
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Mock网络错误
|
|
|
|
+ */
|
|
|
|
+export const mockResetDeviceNetworkError = () => {
|
|
|
|
+ cy.intercept('POST', '/auth/device/action', (req) => {
|
|
|
|
+ if (req.body.reqName === 'RESET') {
|
|
|
|
+ req.reply({ forceNetworkError: true });
|
|
|
|
+ }
|
|
|
|
+ }).as('resetDeviceNetworkError');
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Mock设备重置延迟响应
|
|
|
|
+ * @param delayMs - 延迟毫秒数
|
|
|
|
+ */
|
|
|
|
+export const mockResetDeviceDelay = (delayMs: number) => {
|
|
|
|
+ cy.intercept('POST', '/auth/device/action', (req) => {
|
|
|
|
+ if (req.body.reqName === 'RESET') {
|
|
|
|
+ req.reply({
|
|
|
|
+ statusCode: 200,
|
|
|
|
+ body: {
|
|
|
|
+ code: '0x000000',
|
|
|
|
+ description: 'Success',
|
|
|
|
+ data: {}
|
|
|
|
+ },
|
|
|
|
+ delay: delayMs
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }).as('resetDeviceDelay');
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Mock所有设备操作(用于其他测试场景)
|
|
|
|
+ */
|
|
|
|
+export const mockAllDeviceActions = () => {
|
|
|
|
+ cy.intercept('POST', '/auth/device/action', (req) => {
|
|
|
|
+ req.reply({
|
|
|
|
+ statusCode: 200,
|
|
|
|
+ body: {
|
|
|
|
+ code: '0x000000',
|
|
|
|
+ description: 'Success',
|
|
|
|
+ data: {}
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }).as('deviceAction');
|
|
|
|
+};
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## UI组件修改
|
|
|
|
+
|
|
|
|
+### ContentAreaLarge.tsx 修改点
|
|
|
|
+
|
|
|
|
+在RESET按钮添加测试标识:
|
|
|
|
+
|
|
|
|
+```tsx
|
|
|
|
+<Button
|
|
|
|
+ data-testid="reset-generator-btn" // 新增测试标识
|
|
|
|
+ style={{ width: '1.5rem', height: '1.5rem' }}
|
|
|
|
+ icon={
|
|
|
|
+ <Icon
|
|
|
|
+ module="module-exam"
|
|
|
|
+ name="btn_ResetGenerator"
|
|
|
|
+ userId="base"
|
|
|
|
+ theme="default"
|
|
|
|
+ size="2x"
|
|
|
|
+ state="normal"
|
|
|
|
+ />
|
|
|
|
+ }
|
|
|
|
+ title="重置参数"
|
|
|
|
+ onClick={handleResetParameters}
|
|
|
|
+ disabled={isResetting}
|
|
|
|
+/>
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## 测试数据准备
|
|
|
|
+
|
|
|
|
+### 前置条件Mock
|
|
|
|
+
|
|
|
|
+每个测试用例都需要以下Mock:
|
|
|
|
+
|
|
|
|
+1. **多语言资源(必需)**
|
|
|
|
+ ```typescript
|
|
|
|
+ mockI18nSuccess('zh_CN'); // 获取中文翻译资源
|
|
|
|
+ mockGetLanguageListSuccess(); // 获取语言列表
|
|
|
|
+ mockAllRequiredAPIs('zh_CN'); // Mock软件信息和日志API
|
|
|
|
+ ```
|
|
|
|
+
|
|
|
|
+2. **登录相关**
|
|
|
|
+ - 用户认证 - LoginPage已处理
|
|
|
|
+ - 权限检查 - LoginPage已处理
|
|
|
|
+
|
|
|
|
+3. **配额检查**
|
|
|
|
+ - Quota API Mock - LoginPage已处理
|
|
|
|
+
|
|
|
|
+4. **检查页面数据**
|
|
|
|
+ - 患者信息 - WorklistPage已处理
|
|
|
|
+ - 体位列表 - 进入检查页面后自动加载
|
|
|
|
+ - APR配置 - 进入检查页面后自动加载
|
|
|
|
+
|
|
|
|
+### Redux State初始化
|
|
|
|
+
|
|
|
|
+```typescript
|
|
|
|
+// 测试前重置Redux状态
|
|
|
|
+beforeEach(() => {
|
|
|
|
+ cy.window().its('store').invoke('dispatch', {
|
|
|
|
+ type: 'device/resetState'
|
|
|
|
+ });
|
|
|
|
+});
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## 测试执行计划
|
|
|
|
+
|
|
|
|
+### 第一阶段:核心功能测试(优先级高)
|
|
|
|
+
|
|
|
|
+- ✅ TC-RESET-01: 成功重置设备
|
|
|
|
+- ✅ TC-RESET-02: API失败处理
|
|
|
|
+- ✅ TC-RESET-03: 按钮禁用状态管理
|
|
|
|
+
|
|
|
|
+### 第二阶段:异常处理测试(优先级中)
|
|
|
|
+
|
|
|
|
+- ✅ TC-RESET-04: 网络错误处理
|
|
|
|
+- ✅ TC-RESET-05: 防止重复点击
|
|
|
|
+
|
|
|
|
+### 第三阶段:集成测试(优先级低)
|
|
|
|
+
|
|
|
|
+- 与其他功能的集成测试
|
|
|
|
+- 性能测试
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## 测试覆盖率目标
|
|
|
|
+
|
|
|
|
+- **功能覆盖**: 100% - 所有重置相关功能
|
|
|
|
+- **代码覆盖**: 90%+ - 核心业务逻辑代码
|
|
|
|
+- **边界测试**: 包含成功、失败、网络异常等场景
|
|
|
|
+- **状态测试**: 验证所有Redux状态转换
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## 验收标准
|
|
|
|
+
|
|
|
|
+### 功能验收
|
|
|
|
+
|
|
|
|
+- ✅ 所有5个测试用例通过
|
|
|
|
+- ✅ 成功和失败场景都能正确处理
|
|
|
|
+- ✅ UI状态与Redux状态同步
|
|
|
|
+- ✅ 错误处理机制完善
|
|
|
|
+- ✅ 按钮状态管理正确
|
|
|
|
+
|
|
|
|
+### 性能验收
|
|
|
|
+
|
|
|
|
+- ✅ 按钮响应及时(<100ms)
|
|
|
|
+- ✅ API调用正确(请求体符合规范)
|
|
|
|
+- ✅ loading状态管理准确
|
|
|
|
+- ✅ 无内存泄漏
|
|
|
|
+
|
|
|
|
+### 用户体验验收
|
|
|
|
+
|
|
|
|
+- ✅ 按钮禁用时有视觉反馈
|
|
|
|
+- ✅ 操作结果有明确提示
|
|
|
|
+- ✅ 错误时可重试
|
|
|
|
+- ✅ 防止误操作
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## 常见错误场景
|
|
|
|
+
|
|
|
|
+### 错误码对照表
|
|
|
|
+
|
|
|
|
+| 错误码 | 描述 | 解决方案 |
|
|
|
|
+|--------|------|----------|
|
|
|
|
+| 0x000000 | 成功 | - |
|
|
|
|
+| 0x010001 | 设备通信失败 | 检查设备连接 |
|
|
|
|
+| 0x010002 | 设备忙碌 | 等待设备空闲后重试 |
|
|
|
|
+| 0x010003 | 参数错误 | 检查请求参数 |
|
|
|
|
+| 0x010004 | 超时 | 检查网络连接 |
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## 附录
|
|
|
|
+
|
|
|
|
+### 相关文件清单
|
|
|
|
+
|
|
|
|
+**新建文件**:
|
|
|
|
+1. `docs/测试/重置高压发生器功能测试方案.md` - 本文档
|
|
|
|
+2. `cypress/e2e/exam/reset-generator.cy.ts` - 测试用例
|
|
|
|
+3. `cypress/support/mock/handlers/deviceActions.ts` - Mock处理器
|
|
|
|
+
|
|
|
|
+**修改文件**:
|
|
|
|
+1. `cypress/support/pageObjects/ExamPage.ts` - 扩展POM
|
|
|
|
+2. `src/pages/exam/ContentAreaLarge.tsx` - 添加data-testid
|
|
|
|
+
|
|
|
|
+### API接口文档
|
|
|
|
+
|
|
|
|
+**接口**: POST /auth/device/action
|
|
|
|
+
|
|
|
|
+**请求参数**:
|
|
|
|
+```typescript
|
|
|
|
+interface DeviceActionMessage {
|
|
|
|
+ deviceUri: string; // 设备URI
|
|
|
|
+ reqName: string; // 请求名称
|
|
|
|
+ reqParam: string; // 请求参数
|
|
|
|
+ reqTransaction: string; // 事务ID
|
|
|
|
+ reqClientID: string; // 客户端ID
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+**响应格式**:
|
|
|
|
+```typescript
|
|
|
|
+interface DeviceActionResponse {
|
|
|
|
+ code: string; // 状态码
|
|
|
|
+ description: string; // 描述信息
|
|
|
|
+ solution?: string; // 解决方案(可选)
|
|
|
|
+ data?: any; // 响应数据(可选)
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+## 文档版本
|
|
|
|
+
|
|
|
|
+- **版本**: 1.0.0
|
|
|
|
+- **创建日期**: 2025-10-10
|
|
|
|
+- **最后更新**: 2025-10-10
|
|
|
|
+- **作者**: Cline AI Assistant
|
|
|
|
+- **审核**: 待审核
|