/** * 测试文件: 进入检查 - Worklist双击进入检查(未曝光) * 场景: 从Worklist双击未曝光任务,系统应进入检查界面 * * 路径分析: * - POM: LoginPage, MainPage, WorklistPage, ExamPage * - Mock: * - mockLoginSuccess() - 登录成功 * - mockFetchTwoWorks() - 获取工作列表 * - mockGetStudyDetailsUnexposed() - 获取未曝光检查详情 * - 规格: * ✓ 登录成功 * ✓ 导航到工作列表 * ✓ 工作列表显示至少2条记录 * ✓ 双击第一条未曝光记录 * ✓ 系统加载任务详细信息(未曝光状态) * ✓ 进入检查界面(businessFlow: 'exam') * ✓ 验证Redux状态正确 * ✓ 验证界面元素可见 * * @see docs/测试/进入检查功能测试方案.md - 场景1 */ import { mockLoginSuccess } from '../../support/mock/handlers/user'; import { mockFetchTwoWorks } from '../../support/mock/handlers/worklist'; import { mockGetStudyDetailsUnexposed } from '../../support/mock/handlers/study'; import LoginPage from '../../support/pageObjects/LoginPage'; import MainPage from '../../support/pageObjects/MainPage'; import WorklistPage from '../../support/pageObjects/WorklistPage'; import ExamPage from '../../support/pageObjects/ExamPage'; describe('进入检查:Worklist双击进入检查(未曝光)', () => { const loginPage = new LoginPage(); const mainPage = new MainPage(); const worklistPage = new WorklistPage(); const examPage = new ExamPage(); beforeEach(() => { // 设置所有必要的Mock mockLoginSuccess(); mockFetchTwoWorks(); // 使用第一条记录的StudyID mockGetStudyDetailsUnexposed('250929163817805'); }); it('应该通过双击Worklist未曝光条目进入检查界面', () => { /** * Given: 用户已登录 * 步骤1(前置): 打开登录界面,完成登录 */ loginPage.visit(); loginPage.getUsernameInput().should('be.visible'); loginPage.login('admin', '123456'); // 等待登录成功 cy.wait('@loginSuccess'); cy.contains('登录成功').should('be.visible', { timeout: 10000 }); /** * When: 导航到Worklist * 步骤1: 打开 Worklist */ mainPage.clickPatientManagementButton(); mainPage.clickWorklistButton(); /** * Then: 系统加载Worklist任务信息 * 步骤2(前置): 验证工作列表加载 */ cy.wait('@fetchTwoWorks').then((interception) => { expect(interception.response?.statusCode).to.eq(200); }); // 验证工作列表显示(至少2条记录) worklistPage.getTable().should('be.visible'); worklistPage.getTable().find('tr').should('have.length.at.least', 2); /** * When: 用户双击第一条未曝光任务 * 步骤2: 双击任务条目 */ worklistPage.findTableAndDoubleClickFirstRow(); /** * Then: 系统加载任务详细信息(未曝光状态) * 步骤3: 验证API调用和返回数据 */ cy.wait('@getStudyDetailsUnexposed').then((interception) => { expect(interception.response?.statusCode).to.eq(200); // 验证返回的数据包含未曝光的检查信息 const studyData = interception.response?.body.data; expect(studyData).to.have.property('StudyID'); expect(studyData).to.have.property('series'); expect(studyData.series).to.be.an('array'); // 验证所有images的expose_status为'Unexposed' studyData.series.forEach((series: any) => { series.images.forEach((image: any) => { expect(image.expose_status).to.eq('Unexposed'); }); }); }); /** * Then: 验证Redux状态 - examWorksCache * 步骤4: 验证任务数据已缓存 */ cy.window() .its('store') .invoke('getState') .its('examWorksCache') .its('works') .should('have.length', 1) .its(0) .should('have.property', 'StudyID', '250929163817805'); /** * Then: 验证Redux状态 - businessFlow * 步骤5: 验证进入检查流程(exam模式) */ cy.window() .its('store') .invoke('getState') .its('businessFlow') .its('currentFlow') .should('eq', 'exam'); /** * Then: 验证检查界面元素可见 * 步骤6: 验证目标界面加载 */ examPage.verifyExamPageLoaded(); examPage.getToolbar().should('be.visible'); examPage.getContentArea().should('be.visible'); }); it('应该在Redux中正确保存任务的Views数据', () => { /** * 这个测试用例专注于验证数据转换的正确性 */ loginPage.visit(); loginPage.login('admin', '123456'); cy.wait('@loginSuccess'); mainPage.clickPatientManagementButton(); mainPage.clickWorklistButton(); cy.wait('@fetchTwoWorks'); worklistPage.findTableAndDoubleClickFirstRow(); cy.wait('@getStudyDetailsUnexposed'); /** * 验证Views数组被正确构建 */ cy.window() .its('store') .invoke('getState') .its('examWorksCache') .its('works') .its(0) .its('Views') .should('be.an', 'array') .should('have.length.greaterThan', 0) .then((views: any[]) => { // 验证每个View包含必要的属性 views.forEach((view) => { expect(view).to.have.property('view_id'); expect(view).to.have.property('view_description'); expect(view).to.have.property('expose_status', 'Unexposed'); expect(view).to.have.property('study_id'); expect(view).to.have.property('series_instance_uid'); }); }); }); });