|
|
@@ -0,0 +1,697 @@
|
|
|
+/**
|
|
|
+ * 测试文件: 检查页面 - 退出检查逻辑
|
|
|
+ * 功能: 验证从检查页面退出时的各种场景和逻辑处理
|
|
|
+ *
|
|
|
+ * 测试场景:
|
|
|
+ * 1. 未曝光状态直接退出
|
|
|
+ * 2. 半曝光状态 - 继续检查
|
|
|
+ * 3. 半曝光状态 - 保存并完成
|
|
|
+ * 4. 半曝光状态 - 直接中止
|
|
|
+ * 5. 全曝光状态退出
|
|
|
+ * 6. 发生器采集中阻止退出到process
|
|
|
+ * 7. 从检查正常退出到process(非采集)
|
|
|
+ * 8. 边界场景:快速连续点击退出
|
|
|
+ *
|
|
|
+ * 相关需求文档: docs/实现/退出检查的逻辑.md
|
|
|
+ */
|
|
|
+
|
|
|
+import LoginPage from '../../support/pageObjects/LoginPage';
|
|
|
+import MainPage from '../../support/pageObjects/MainPage';
|
|
|
+import WorklistPage from '../../support/pageObjects/WorklistPage';
|
|
|
+
|
|
|
+describe('检查页面:退出检查逻辑', () => {
|
|
|
+ const loginPage = new LoginPage();
|
|
|
+ const mainPage = new MainPage();
|
|
|
+ const worklistPage = new WorklistPage();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通用的登录和进入检查页面的前置步骤
|
|
|
+ */
|
|
|
+ beforeEach(() => {
|
|
|
+ // 登录系统
|
|
|
+ loginPage.visit();
|
|
|
+ loginPage.login('admin', '123456');
|
|
|
+ cy.contains('登录成功').should('be.visible', { timeout: 10000 });
|
|
|
+
|
|
|
+ // 导航到工作列表
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+
|
|
|
+ // 双击第一行进入检查页面
|
|
|
+ worklistPage.findTableAndDoubleClickFirstRow();
|
|
|
+ cy.wait(1000);
|
|
|
+
|
|
|
+ // 验证已进入检查页面
|
|
|
+ cy.get('[data-testid="exam-page"]').should('exist');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 1:未曝光状态直接退出
|
|
|
+ *
|
|
|
+ * Given: 用户已登录系统并从工作列表进入检查页面
|
|
|
+ * 未进行任何曝光操作
|
|
|
+ * When: 用户点击导航按钮切换到工作列表
|
|
|
+ * Then: 应该直接退出检查页面,不显示退出反馈弹窗
|
|
|
+ */
|
|
|
+ it('场景1:未曝光状态应该直接退出检查', () => {
|
|
|
+ /**
|
|
|
+ * Given: 验证当前在检查页面
|
|
|
+ */
|
|
|
+ cy.get('[data-testid="exam-page"]').should('exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 验证曝光状态为 "Not Exposed"
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('bodyPositionList')
|
|
|
+ .its('exposureStatus')
|
|
|
+ .should('equal', 'Not Exposed');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击导航按钮切换到工作列表
|
|
|
+ */
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证成功退出到工作列表页面
|
|
|
+ */
|
|
|
+ cy.url().should('include', '/worklist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证未显示退出反馈弹窗
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('not.exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证Redux store中业务流程已切换
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('BusinessFlow')
|
|
|
+ .its('currentKey')
|
|
|
+ .should('equal', 'worklist');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 2:半曝光状态 - 继续检查
|
|
|
+ *
|
|
|
+ * Given: 用户已登录系统并进入检查页面
|
|
|
+ * 已完成部分体位的曝光
|
|
|
+ * When: 用户点击退出,显示反馈弹窗
|
|
|
+ * 用户点击"继续检查"按钮
|
|
|
+ * Then: 弹窗关闭,停留在检查页面
|
|
|
+ */
|
|
|
+ it('场景2:半曝光状态点击"继续检查"应该停留在检查页面', () => {
|
|
|
+ /**
|
|
|
+ * Given: 模拟半曝光状态
|
|
|
+ * 通过Redux store直接设置状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'bodyPositionList/setExposureStatus',
|
|
|
+ payload: 'Half Exposed'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 验证曝光状态为 "Half Exposed"
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('bodyPositionList')
|
|
|
+ .its('exposureStatus')
|
|
|
+ .should('equal', 'Half Exposed');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击导航按钮尝试退出
|
|
|
+ */
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证显示退出反馈弹窗
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('be.visible');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗标题
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('contain', '检查未完成');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗提示信息
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('contain', '当前检查的曝光步骤尚未完成');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证Redux store中弹窗状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('largeScreen')
|
|
|
+ .its('isFeedbackOpen')
|
|
|
+ .should('be.true');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击"继续检查"按钮
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').contains('button', '继续检查').click();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗关闭
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('not.exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证仍停留在检查页面
|
|
|
+ */
|
|
|
+ cy.get('[data-testid="exam-page"]').should('exist');
|
|
|
+ cy.url().should('include', '/exam');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证Redux store中弹窗已关闭
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('largeScreen')
|
|
|
+ .its('isFeedbackOpen')
|
|
|
+ .should('be.false');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证业务流程仍为exam
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('BusinessFlow')
|
|
|
+ .its('currentKey')
|
|
|
+ .should('equal', 'exam');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 3:半曝光状态 - 保存并完成
|
|
|
+ *
|
|
|
+ * Given: 用户已登录系统并进入检查页面
|
|
|
+ * 已完成部分体位的曝光
|
|
|
+ * When: 用户点击退出,显示反馈弹窗
|
|
|
+ * 用户点击"保存并完成"按钮
|
|
|
+ * Then: 调用API通知后端(study_status='Completed')
|
|
|
+ * 成功跳转到工作列表页面
|
|
|
+ */
|
|
|
+ it('场景3:半曝光状态点击"保存并完成"应该调用API并退出', () => {
|
|
|
+ /**
|
|
|
+ * Given: Mock API接口
|
|
|
+ */
|
|
|
+ cy.intercept('POST', '/auth/task/inspection/leave', {
|
|
|
+ statusCode: 200,
|
|
|
+ body: {
|
|
|
+ code: '0x000000',
|
|
|
+ description: 'Success',
|
|
|
+ solution: '',
|
|
|
+ data: {}
|
|
|
+ }
|
|
|
+ }).as('suspendOrCompleteStudy');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 模拟半曝光状态并设置StudyID
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ const state = store.getState();
|
|
|
+
|
|
|
+ // 设置曝光状态
|
|
|
+ store.dispatch({
|
|
|
+ type: 'bodyPositionList/setExposureStatus',
|
|
|
+ payload: 'Half Exposed'
|
|
|
+ });
|
|
|
+
|
|
|
+ // 确保有StudyID
|
|
|
+ if (state.bodyPositionList.selectedBodyPosition?.work?.StudyID) {
|
|
|
+ cy.wrap(state.bodyPositionList.selectedBodyPosition.work.StudyID).as('currentStudyId');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击导航按钮尝试退出
|
|
|
+ */
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证显示退出反馈弹窗
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('be.visible');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击"保存并完成"按钮
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').contains('button', '保存并完成').click();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证调用了API
|
|
|
+ */
|
|
|
+ cy.wait('@suspendOrCompleteStudy').then((interception) => {
|
|
|
+ // 验证请求参数
|
|
|
+ expect(interception.request.body).to.have.property('study_status', 'Completed');
|
|
|
+ expect(interception.request.body).to.have.property('study_id');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗关闭
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('not.exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证成功跳转到工作列表页面
|
|
|
+ */
|
|
|
+ cy.url().should('include', '/worklist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证业务流程已切换
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('BusinessFlow')
|
|
|
+ .its('currentKey')
|
|
|
+ .should('equal', 'worklist');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 4:半曝光状态 - 直接中止
|
|
|
+ *
|
|
|
+ * Given: 用户已登录系统并进入检查页面
|
|
|
+ * 已完成部分体位的曝光
|
|
|
+ * When: 用户点击退出,显示反馈弹窗
|
|
|
+ * 用户点击"直接中止"按钮(危险按钮)
|
|
|
+ * Then: 调用API通知后端(study_status='InProgress')
|
|
|
+ * 成功跳转到工作列表页面
|
|
|
+ */
|
|
|
+ it('场景4:半曝光状态点击"直接中止"应该调用API并退出', () => {
|
|
|
+ /**
|
|
|
+ * Given: Mock API接口
|
|
|
+ */
|
|
|
+ cy.intercept('POST', '/auth/task/inspection/leave', {
|
|
|
+ statusCode: 200,
|
|
|
+ body: {
|
|
|
+ code: '0x000000',
|
|
|
+ description: 'Success',
|
|
|
+ solution: '',
|
|
|
+ data: {}
|
|
|
+ }
|
|
|
+ }).as('suspendOrCompleteStudy');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 模拟半曝光状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'bodyPositionList/setExposureStatus',
|
|
|
+ payload: 'Half Exposed'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击导航按钮尝试退出
|
|
|
+ */
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证显示退出反馈弹窗
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('be.visible');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证"直接中止"按钮为危险样式
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]')
|
|
|
+ .contains('button', '直接中止')
|
|
|
+ .should('have.class', 'ant-btn-dangerous');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击"直接中止"按钮
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').contains('button', '直接中止').click();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证调用了API
|
|
|
+ */
|
|
|
+ cy.wait('@suspendOrCompleteStudy').then((interception) => {
|
|
|
+ // 验证请求参数
|
|
|
+ expect(interception.request.body).to.have.property('study_status', 'InProgress');
|
|
|
+ expect(interception.request.body).to.have.property('study_id');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗关闭
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('not.exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证成功跳转到工作列表页面
|
|
|
+ */
|
|
|
+ cy.url().should('include', '/worklist');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 5:全曝光状态退出
|
|
|
+ *
|
|
|
+ * Given: 用户已登录系统并进入检查页面
|
|
|
+ * 已完成所有体位的曝光
|
|
|
+ * When: 用户点击导航按钮切换到工作列表
|
|
|
+ * Then: 应该直接退出,不显示退出反馈弹窗
|
|
|
+ */
|
|
|
+ it('场景5:全曝光状态应该直接退出检查', () => {
|
|
|
+ /**
|
|
|
+ * Given: 模拟全曝光状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'bodyPositionList/setExposureStatus',
|
|
|
+ payload: 'Fully Exposed'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 验证曝光状态为 "Fully Exposed"
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('bodyPositionList')
|
|
|
+ .its('exposureStatus')
|
|
|
+ .should('equal', 'Fully Exposed');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击导航按钮切换到工作列表
|
|
|
+ */
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证未显示退出反馈弹窗
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('not.exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证成功退出到工作列表页面
|
|
|
+ */
|
|
|
+ cy.url().should('include', '/worklist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证业务流程已切换
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('BusinessFlow')
|
|
|
+ .its('currentKey')
|
|
|
+ .should('equal', 'worklist');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 6:发生器采集中阻止退出到process
|
|
|
+ *
|
|
|
+ * Given: 用户在检查页面
|
|
|
+ * 发生器正在采集(acquisitionState = 1)
|
|
|
+ * When: 用户尝试跳转到图像处理页面(process)
|
|
|
+ * Then: 跳转被阻止,停留在检查页面
|
|
|
+ */
|
|
|
+ it('场景6:发生器采集中应该阻止退出到图像处理', () => {
|
|
|
+ /**
|
|
|
+ * Given: 模拟发生器正在采集
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'generatorMonitor/setAcquisitionState',
|
|
|
+ payload: 1
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 验证发生器状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('generatorMonitor')
|
|
|
+ .its('acquisitionState')
|
|
|
+ .should('equal', 1);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 尝试跳转到图像处理页面
|
|
|
+ * 注意:这里需要根据实际的导航方式调整
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'BusinessFlow/setBusinessFlow',
|
|
|
+ payload: 'process'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证仍停留在检查页面
|
|
|
+ */
|
|
|
+ cy.wait(500); // 等待可能的状态变化
|
|
|
+ cy.get('[data-testid="exam-page"]').should('exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证业务流程仍为exam
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('BusinessFlow')
|
|
|
+ .its('currentKey')
|
|
|
+ .should('equal', 'exam');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 7:从检查正常退出到process(非采集)
|
|
|
+ *
|
|
|
+ * Given: 用户在检查页面
|
|
|
+ * 发生器空闲(acquisitionState != 1)
|
|
|
+ * 有已曝光的图像
|
|
|
+ * When: 用户点击进入图像处理页面
|
|
|
+ * Then: 成功跳转到process页面
|
|
|
+ * 执行了清理操作(unprepare)
|
|
|
+ */
|
|
|
+ it('场景7:发生器空闲时应该能正常退出到图像处理', () => {
|
|
|
+ /**
|
|
|
+ * Given: 确保发生器不在采集状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'generatorMonitor/setAcquisitionState',
|
|
|
+ payload: 0
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 验证发生器状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('generatorMonitor')
|
|
|
+ .its('acquisitionState')
|
|
|
+ .should('not.equal', 1);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 监听控制台日志(验证unprepare调用)
|
|
|
+ */
|
|
|
+ cy.window().then((win) => {
|
|
|
+ cy.spy(win.console, 'log').as('consoleLog');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 点击进入图像处理页面
|
|
|
+ * 注意:这里需要根据实际的导航方式调整
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'BusinessFlow/setBusinessFlow',
|
|
|
+ payload: 'process'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证成功跳转到process页面
|
|
|
+ */
|
|
|
+ cy.wait(1000);
|
|
|
+ cy.url().should('include', '/process');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证业务流程已切换
|
|
|
+ */
|
|
|
+ cy.window().its('store').invoke('getState')
|
|
|
+ .its('BusinessFlow')
|
|
|
+ .its('currentKey')
|
|
|
+ .should('equal', 'process');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证控制台输出了相应日志
|
|
|
+ */
|
|
|
+ cy.get('@consoleLog').should('be.calledWith', '从检查退出到处理');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 8:边界场景 - 快速连续点击退出
|
|
|
+ *
|
|
|
+ * Given: 用户在检查页面(半曝光状态)
|
|
|
+ * When: 快速连续点击退出按钮(3次)
|
|
|
+ * Then: 只显示一个退出反馈弹窗
|
|
|
+ * 弹窗功能正常
|
|
|
+ */
|
|
|
+ it('场景8:快速连续点击退出应该只显示一个弹窗', () => {
|
|
|
+ /**
|
|
|
+ * Given: 模拟半曝光状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'bodyPositionList/setExposureStatus',
|
|
|
+ payload: 'Half Exposed'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 快速连续点击退出按钮3次
|
|
|
+ */
|
|
|
+ for (let i = 0; i < 3; i++) {
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+ cy.wait(50); // 很短的等待时间,模拟快速点击
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证只显示一个弹窗
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('have.length', 1);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗可见
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('be.visible');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗功能正常(点击"继续检查")
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').contains('button', '继续检查').click();
|
|
|
+ cy.get('[role="dialog"]').should('not.exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证仍在检查页面
|
|
|
+ */
|
|
|
+ cy.get('[data-testid="exam-page"]').should('exist');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 9:边界场景 - StudyID为空的错误处理
|
|
|
+ *
|
|
|
+ * Given: 用户在检查页面但StudyID为空
|
|
|
+ * When: 用户尝试退出并选择保存
|
|
|
+ * Then: 应该有适当的错误处理
|
|
|
+ */
|
|
|
+ it('场景9:StudyID为空时应该有错误处理', () => {
|
|
|
+ /**
|
|
|
+ * Given: 清空StudyID
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'bodyPositionList/setExposureStatus',
|
|
|
+ payload: 'Half Exposed'
|
|
|
+ });
|
|
|
+
|
|
|
+ // 模拟StudyID为空的情况
|
|
|
+ store.dispatch({
|
|
|
+ type: 'bodyPositionList/clearSelectedBodyPosition'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Given: 监听控制台错误日志
|
|
|
+ */
|
|
|
+ cy.window().then((win) => {
|
|
|
+ cy.spy(win.console, 'error').as('consoleError');
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 尝试退出
|
|
|
+ */
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 可能显示弹窗或直接显示错误
|
|
|
+ * 根据实际实现调整验证逻辑
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').then(($dialog) => {
|
|
|
+ if ($dialog.length > 0) {
|
|
|
+ // 如果显示了弹窗,尝试点击保存
|
|
|
+ cy.get('[role="dialog"]').contains('button', '保存并完成').click();
|
|
|
+
|
|
|
+ // 验证控制台输出了错误日志
|
|
|
+ cy.get('@consoleError').should('be.called');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试场景 10:验证退出反馈弹窗UI元素
|
|
|
+ *
|
|
|
+ * Given: 用户在检查页面(半曝光状态)
|
|
|
+ * When: 触发退出反馈弹窗
|
|
|
+ * Then: 验证弹窗包含所有必要的UI元素
|
|
|
+ */
|
|
|
+ it('场景10:退出反馈弹窗应该包含所有必要的UI元素', () => {
|
|
|
+ /**
|
|
|
+ * Given: 模拟半曝光状态
|
|
|
+ */
|
|
|
+ cy.window().its('store').then((store) => {
|
|
|
+ store.dispatch({
|
|
|
+ type: 'bodyPositionList/setExposureStatus',
|
|
|
+ payload: 'Half Exposed'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When: 触发退出
|
|
|
+ */
|
|
|
+ mainPage.clickPatientManagementButton();
|
|
|
+ mainPage.clickWorklistButton();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗存在
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('be.visible');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证弹窗标题
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('contain', '检查未完成');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证警告图标
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').find('.anticon-exclamation-circle').should('exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证提示消息
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').should('contain', '当前检查的曝光步骤尚未完成');
|
|
|
+ cy.get('[role="dialog"]').should('contain', '中止后,本次检查的进度将不会保存');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证包含三个按钮
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').find('button').should('have.length', 3);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证"继续检查"按钮
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').contains('button', '继续检查').should('exist');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证"保存并完成"按钮(主按钮)
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]')
|
|
|
+ .contains('button', '保存并完成')
|
|
|
+ .should('have.class', 'ant-btn-primary');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Then: 验证"直接中止"按钮(危险按钮)
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]')
|
|
|
+ .contains('button', '直接中止')
|
|
|
+ .should('have.class', 'ant-btn-primary')
|
|
|
+ .should('have.class', 'ant-btn-dangerous');
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清理:关闭弹窗
|
|
|
+ */
|
|
|
+ cy.get('[role="dialog"]').contains('button', '继续检查').click();
|
|
|
+ });
|
|
|
+});
|