sw 0ed76e6ff4 test: 实现重置高压发生器功能的完整E2E测试方案 4 dienas atpakaļ
..
handlers 0ed76e6ff4 test: 实现重置高压发生器功能的完整E2E测试方案 4 dienas atpakaļ
utils 4c7b8bac5d refactor(cypress): reorganize cypress code for intercepting and mocking requests and responses 4 nedēļas atpakaļ
README.md 1b5de54d1b feat: add comprehensive Cypress mock handlers for all DR API endpoints 1 nedēļu atpakaļ
index.ts 1b5de54d1b feat: add comprehensive Cypress mock handlers for all DR API endpoints 1 nedēļu atpakaļ

README.md

Cypress Mock Handlers 使用文档

本目录包含所有 Cypress 测试的 API mock handlers,用于模拟后端接口响应。

目录结构

cypress/support/mock/
├── handlers/           # Mock handler 文件
│   ├── system.ts      # 系统信息相关
│   ├── i18n.ts        # 国际化相关
│   ├── user.ts        # 用户相关
│   ├── auth.ts        # 认证相关
│   ├── resource.ts    # 资源配置相关
│   ├── protocol.ts    # 协议相关
│   ├── study.ts       # 检查信息管理
│   ├── image.ts       # 图像相关
│   ├── report.ts      # 报告相关
│   ├── device.ts      # 设备相关
│   ├── exam.ts        # 检查执行相关
│   └── quota.ts       # 配额相关
├── index.ts           # 统一导出
└── README.md          # 本文档

快速开始

1. 导入 Mock Handlers

在测试文件中导入需要的 mock handlers:

import {
  mockLoginSuccess,
  mockGetSoftwareInfoSuccess,
  mockI18nSuccess,
} from '../support/mock';

2. 在测试中使用

describe('登录功能测试', () => {
  beforeEach(() => {
    // 设置 mock
    mockLoginSuccess();
    mockGetSoftwareInfoSuccess();
  });

  it('应该成功登录', () => {
    cy.visit('/login');
    cy.get('[data-testid="username"]').type('admin');
    cy.get('[data-testid="password"]').type('123456');
    cy.get('[data-testid="login-btn"]').click();

    // 等待并验证 mock 响应
    cy.wait('@loginSuccess');
    cy.url().should('include', '/dashboard');
  });
});

模块说明

System - 系统信息

import { mockGetSoftwareInfoSuccess } from '../support/mock';

// 使用
mockGetSoftwareInfoSuccess();
cy.wait('@getSoftwareInfoSuccess');

可用函数:

  • mockGetSoftwareInfoSuccess() - 获取软件信息成功
  • mockGetSoftwareInfoFail() - 获取软件信息失败

I18n - 国际化

import { mockGetLanguageListSuccess, mockI18nSuccess } from '../support/mock';

// 获取语言列表
mockGetLanguageListSuccess();

// 获取翻译文件
mockI18nSuccess('zh'); // 或 'en'

可用函数:

  • mockGetLanguageListSuccess() - 获取语言列表成功
  • mockGetLanguageListEmpty() - 获取空语言列表
  • mockI18nSuccess(locale) - 获取翻译文件成功
  • mockI18nError(locale) - 获取翻译文件失败(404)
  • mockI18nServerError(locale) - 服务器错误(500)
  • mockI18nTimeout(locale) - 请求超时
  • mockI18nInvalidFormat(locale) - 返回无效格式
  • mockI18nEmptyData(locale) - 返回空数据
  • mockI18nNetworkError(locale) - 网络错误

User - 用户

import { mockLoginSuccess, mockGetUsersSuccess } from '../support/mock';

// 登录
mockLoginSuccess();

// 获取用户列表
mockGetUsersSuccess();

可用函数:

  • mockLoginSuccess() - 登录成功
  • mockLoginFail() - 登录失败(用户名或密码错误)
  • mockGetUsersSuccess() - 获取用户列表成功
  • mockGetUsersEmpty() - 获取空用户列表

Auth - 认证

import { mockChangePasswordSuccess } from '../support/mock';

mockChangePasswordSuccess();
cy.wait('@changePasswordSuccess');

可用函数:

  • mockChangePasswordSuccess() - 修改密码成功
  • mockChangePasswordWrongOldPassword() - 旧密码错误
  • mockChangePasswordNotMatch() - 新密码不匹配

Resource - 资源配置

import { mockGetOptionsSexFull, mockGetImageSuccess } from '../support/mock';

// 获取性别选项
mockGetOptionsSexFull();

// 获取示意图
mockGetImageSuccess();

可用函数:

  • mockGetOptionsSexFull() - 获取性别选项
  • mockGetOptionsPatientSize() - 获取患者体型选项
  • mockGetConfigSimulatorGEN() - 获取发生器仿真配置
  • mockGetConfigSimulatorFPD() - 获取探测器仿真配置
  • mockGetImageSuccess() - 获取示意图成功
  • mockGetImageNotFound() - 示意图不存在(404)

Protocol - 协议

import {
  mockGetPatientTypeHuman,
  mockGetBodyPartHuman,
  mockGetProcedureListSuccess,
} from '../support/mock';

// 获取患者类型
mockGetPatientTypeHuman();

// 获取身体部位
mockGetBodyPartHuman();

// 获取协议列表
mockGetProcedureListSuccess();

可用函数:

  • mockGetPatientTypeHuman() - 获取人医患者类型
  • mockGetPatientTypeAll() - 获取所有患者类型
  • mockGetBodyPartHuman() - 获取人医身体部位
  • mockGetProcedureListSuccess() - 获取协议列表
  • mockGetViewListSuccess() - 获取体位列表
  • mockGetViewDetailSuccess() - 获取体位详情
  • mockGetAprByViewSuccess() - 获取APR详情(通过view_id)
  • mockGetAprDeviceSuccess() - 获取APR设备信息
  • mockGetAprTechParamsSuccess() - 获取APR默认曝光参数

Study - 检查信息管理

import {
  mockRegisterStudySuccess,
  mockGetStudyArrived,
  mockUpdateStudySuccess,
} from '../support/mock';

// 登记检查
mockRegisterStudySuccess();

// 获取检查信息
mockGetStudyArrived();

// 更新检查信息
mockUpdateStudySuccess();

可用函数:

  • mockRegisterStudySuccess() - 登记检查成功
  • mockGetStudyArrived() - 获取检查信息(Arrived状态)
  • mockGetStudyStatSuccess() - 获取检查统计信息
  • mockUpdateStudySuccess() - 更新检查信息成功
  • mockDeleteStudyBatchSuccess() - 批量删除检查成功
  • mockStorePortraitSuccess() - 存储急诊患者影像成功
  • mockLeaveStudyInProgress() - 挂起检查
  • mockLeaveStudyCompleted() - 完成检查

Image - 图像

import {
  mockAppendImagesSuccess,
  mockDeleteImageSuccess,
} from '../support/mock';

// 添加体位
mockAppendImagesSuccess();

// 删除体位
mockDeleteImageSuccess();

可用函数:

  • mockAppendImagesSuccess() - 批量添加体位成功
  • mockCopyImageSuccess() - 复制体位成功
  • mockSortImagesSuccess() - 体位重新排序成功
  • mockDeleteImageSuccess() - 删除体位成功
  • mockStorePostProcSuccess() - 存储后处理DCM成功
  • mockGetDcmFileSuccess() - 获取DCM文件成功
  • mockGetThumbnailSuccess() - 获取缩略图成功

Report - 报告

import {
  mockReportPreviewSuccess,
  mockSaveReportSuccess,
} from '../support/mock';

// 预览报告
mockReportPreviewSuccess();

// 保存报告
mockSaveReportSuccess();

可用函数:

  • mockReportPreviewSuccess() - 报告预览成功
  • mockSaveReportSuccess() - 保存报告成功
  • mockGetReportSuccess() - 获取报告成功
  • mockGetReportNotFound() - 报告不存在(404)

Device - 设备

import {
  mockOpenDeviceSuccess,
  mockDeviceGetSuccess,
  mockDeviceActionSuccess,
} from '../support/mock';

// 打开设备
mockOpenDeviceSuccess();

// 获取设备状态
mockDeviceGetSuccess();

// 执行设备动作
mockDeviceActionSuccess();

可用函数:

  • mockOpenDeviceSuccess() - 打开设备成功
  • mockDeviceGetSuccess() - 执行Get操作成功
  • mockDeviceActionSuccess() - 执行Action操作成功

Exam - 检查执行

import {
  mockStartInspectionSuccess,
  mockGetGlobalStatusAllReady,
  mockTriggerInspectionSuccess,
} from '../support/mock';

// 开始检查
mockStartInspectionSuccess();

// 获取全局状态
mockGetGlobalStatusAllReady();

// 触发曝光
mockTriggerInspectionSuccess();

可用函数:

  • mockStartInspectionSuccess() - 开始检查成功
  • mockGetGlobalStatusAllReady() - 获取全局状态(全部就绪)
  • mockGetGlobalStatusNotReady() - 获取全局状态(未就绪)
  • mockTriggerInspectionSuccess() - 软曝光成功
  • mockJudgeImageAccept() - 接受图像
  • mockJudgeImageReject() - 拒绝图像

Quota - 配额

import { mockQuotaSufficient, mockQuotaInsufficient } from '../support/mock';

// 配额充足
mockQuotaSufficient();

// 配额不足
mockQuotaInsufficient();

完整示例

示例1:登录流程测试

import {
  mockLoginSuccess,
  mockGetSoftwareInfoSuccess,
  mockI18nSuccess,
  mockGetLanguageListSuccess,
} from '../support/mock';

describe('登录流程', () => {
  beforeEach(() => {
    // 设置所有必要的 mocks
    mockGetSoftwareInfoSuccess();
    mockGetLanguageListSuccess();
    mockI18nSuccess('zh');
    mockLoginSuccess();
  });

  it('应该成功登录并跳转到主页', () => {
    cy.visit('/login');

    // 填写登录表单
    cy.get('[data-testid="username"]').type('admin');
    cy.get('[data-testid="password"]').type('123456');
    cy.get('[data-testid="login-btn"]').click();

    // 验证请求
    cy.wait('@loginSuccess').its('response.statusCode').should('eq', 200);

    // 验证跳转
    cy.url().should('include', '/dashboard');
  });
});

示例2:患者登记测试

import {
  mockGetPatientTypeHuman,
  mockGetBodyPartHuman,
  mockGetProcedureListSuccess,
  mockRegisterStudySuccess,
} from '../support/mock';

describe('患者登记', () => {
  beforeEach(() => {
    mockGetPatientTypeHuman();
    mockGetBodyPartHuman();
    mockGetProcedureListSuccess();
    mockRegisterStudySuccess();
  });

  it('应该成功登记患者', () => {
    cy.visit('/patient/register');

    // 填写患者信息
    cy.get('[name="patient_name"]').type('测试患者');
    cy.get('[name="patient_id"]').type('P001');

    // 选择协议
    cy.get('[data-testid="select-protocol"]').click();
    cy.wait('@getProcedureListSuccess');

    // 提交
    cy.get('[data-testid="submit-btn"]').click();
    cy.wait('@registerStudySuccess');

    // 验证成功提示
    cy.contains('登记成功').should('be.visible');
  });
});

示例3:曝光流程测试

import {
  mockStartInspectionSuccess,
  mockGetGlobalStatusAllReady,
  mockTriggerInspectionSuccess,
  mockJudgeImageAccept,
} from '../support/mock';

describe('曝光流程', () => {
  beforeEach(() => {
    mockStartInspectionSuccess();
    mockGetGlobalStatusAllReady();
    mockTriggerInspectionSuccess();
    mockJudgeImageAccept();
  });

  it('应该成功完成曝光', () => {
    cy.visit('/exam/exposure');

    // 等待设备就绪
    cy.wait('@getGlobalStatusAllReady');
    cy.get('[data-testid="ready-indicator"]').should('have.class', 'ready');

    // 触发曝光
    cy.get('[data-testid="trigger-btn"]').click();
    cy.wait('@triggerInspectionSuccess');

    // 接受图像
    cy.get('[data-testid="accept-btn"]').click();
    cy.wait('@judgeImageAccept');

    // 验证成功
    cy.contains('图像已保存').should('be.visible');
  });
});

注意事项

  1. Mock 顺序:在 beforeEach 中设置 mock,确保每个测试都有干净的状态

  2. 等待响应:使用 cy.wait('@aliasName') 等待 mock 响应,避免时序问题

  3. 验证响应:可以验证 mock 响应的状态码和数据:

   cy.wait('@loginSuccess').its('response.statusCode').should('eq', 200);
  1. 组合使用:根据测试场景组合使用多个 mock handlers

  2. 清理:Cypress 会在每个测试后自动清理 intercept,无需手动清理

参考文档

贡献

添加新的 mock handler 时,请遵循以下规范:

  1. 使用统一的 JSDoc 注释格式
  2. 包含完整的参数和返回值说明
  3. 提供使用示例
  4. index.ts 中导出
  5. 更新本文档