123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- /**
- * 测试文件: 患者注册 - 切换患者类型清空已选体位
- * 功能: 验证切换患者类型时自动清空已选择体位列表
- *
- * 测试场景:
- * 1. 切换患者类型时清空已选体位列表
- * 2. 切换协议/体位模式时保持已选体位
- * 3. 切换身体部位时保持已选体位
- *
- * 相关需求文档: docs/实现/注册时体位过滤-需求-实现.md
- */
- import { mockLoginSuccess } from '../../support/mock/handlers/user';
- import {
- mockGetMultiplePatientTypes,
- mockGetBodyPartForHuman,
- mockGetBodyPartForSpecialType,
- mockGetViewsForHumanSkull,
- mockGetProceduresForHumanSkull,
- mockGetViewsByProcedure,
- } from '../../support/mock/handlers/patientRegistration';
- describe('患者注册:切换患者类型清空已选体位列表', () => {
- beforeEach(() => {
- // 设置所有必要的 Mock
- mockLoginSuccess();
- mockGetMultiplePatientTypes();
- mockGetBodyPartForHuman();
- mockGetBodyPartForSpecialType();
- mockGetViewsForHumanSkull();
- mockGetProceduresForHumanSkull();
- mockGetViewsByProcedure();
- // 登录并导航到患者注册页面
- cy.visit('/');
- cy.get('[data-testid="username"]').type('admin');
- cy.get('[data-testid="password"]').type('123456');
- cy.get('[data-testid="login-button"]').click();
- cy.wait('@loginSuccess');
- // 导航到患者管理 -> 注册页面
- cy.get('[data-testid="patient-management"]').click();
- cy.get('[data-testid="register"]').click();
- });
- /**
- * 测试场景 1:切换患者类型时清空已选体位列表
- *
- * Given: 用户已在患者注册页面,已选择患者类型、身体部位并添加了体位
- * When: 用户切换到不同的患者类型
- * Then: 已选择体位列表应该被清空
- */
- it('应该在切换患者类型时清空已选择的体位列表', () => {
- /**
- * Given: 用户在患者注册页面
- * 步骤1: 页面已加载患者类型列表
- */
- cy.wait('@getMultiplePatientTypes');
- /**
- * When: 选择患者类型 "Human"
- * 步骤2: 点击患者类型选择器
- * 步骤3: 选择 "Human" 类型
- */
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-Human"]').click();
- cy.wait('@getBodyPartForHuman');
- /**
- * When: 选择身体部位 "颅骨"
- * 步骤4: 点击身体部位选择器
- * 步骤5: 选择 "颅骨"
- */
- cy.get('[data-testid="body-part-selector"]').click();
- cy.get('[data-testid="body-part-option-Human_SKULL"]').click();
- /**
- * When: 切换到 "体位" 选择模式
- * 步骤6: 点击 "体位" 标签
- */
- cy.get('[data-testid="selection-mode-view"]').click();
- cy.wait('@getViewsForHumanSkull');
- /**
- * When: 添加体位到已选列表
- * 步骤7: 点击第一个体位(颅骨前后位)
- */
- cy.get('[data-testid="view-item-View_DX_H_SKULL_AP"]').click();
- /**
- * Then: 验证已选列表包含 1 个体位
- * 步骤8: 检查已选列表
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 1);
- cy.get('[data-testid="selected-view-count"]')
- .should('contain', '1');
- /**
- * When: 切换患者类型到 "SpecialType"
- * 步骤9: 打开患者类型选择器
- * 步骤10: 选择 "SpecialType"
- */
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-SpecialType"]').click();
- cy.wait('@getBodyPartForSpecialType');
- /**
- * Then: 已选择体位列表应该被清空
- * 步骤11: 验证已选列表为空
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 0);
- cy.get('[data-testid="selected-view-count"]')
- .should('contain', '0');
- /**
- * Then: 验证 Redux store 中的状态
- * 步骤12: 检查 Redux store
- */
- cy.window().its('store').invoke('getState')
- .its('viewSelection')
- .its('selectedViews')
- .should('have.length', 0);
- });
- /**
- * 测试场景 2:切换协议/体位模式时保持已选体位
- *
- * Given: 用户已选择患者类型、身体部位,并在协议模式下添加了协议
- * When: 用户切换到体位选择模式
- * Then: 已选择体位列表应该保持不变
- */
- it('应该在切换协议/体位模式时保持已选择的体位列表', () => {
- /**
- * Given: 选择患者类型和身体部位
- */
- cy.wait('@getMultiplePatientTypes');
-
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-Human"]').click();
- cy.wait('@getBodyPartForHuman');
- cy.get('[data-testid="body-part-selector"]').click();
- cy.get('[data-testid="body-part-option-Human_SKULL"]').click();
- /**
- * When: 在协议模式下添加协议
- * 步骤1: 确保在协议模式(默认)
- * 步骤2: 等待协议列表加载
- */
- cy.get('[data-testid="selection-mode-protocol"]').should('have.class', 'active');
- cy.wait('@getProceduresForHumanSkull');
- /**
- * When: 点击协议添加体位
- * 步骤3: 点击协议
- */
- cy.get('[data-testid="procedure-item-P_SKULL_AP_LAT"]').click();
- cy.wait('@getViewsByProcedure');
- /**
- * Then: 验证已选列表包含体位
- * 步骤4: 检查已选列表(协议包含2个体位)
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 2);
- /**
- * When: 切换到体位模式
- * 步骤5: 点击体位标签
- */
- cy.get('[data-testid="selection-mode-view"]').click();
- cy.wait('@getViewsForHumanSkull');
- /**
- * Then: 已选列表应该保持不变
- * 步骤6: 验证已选列表仍然包含 2 个体位
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 2);
- cy.get('[data-testid="selected-view-count"]')
- .should('contain', '2');
- /**
- * Then: 验证 Redux store 状态
- */
- cy.window().its('store').invoke('getState')
- .its('viewSelection')
- .its('selectedViews')
- .should('have.length', 2);
- });
- /**
- * 测试场景 3:切换身体部位时保持已选体位
- *
- * Given: 用户已选择患者类型、身体部位并添加了体位
- * When: 用户切换到不同的身体部位
- * Then: 已选择体位列表应该保持不变
- */
- it('应该在切换身体部位时保持已选择的体位列表', () => {
- /**
- * Given: 选择患者类型 "Human"
- */
- cy.wait('@getMultiplePatientTypes');
-
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-Human"]').click();
- cy.wait('@getBodyPartForHuman');
- /**
- * Given: 选择身体部位 "颅骨"
- */
- cy.get('[data-testid="body-part-selector"]').click();
- cy.get('[data-testid="body-part-option-Human_SKULL"]').click();
- /**
- * Given: 切换到体位模式并添加体位
- */
- cy.get('[data-testid="selection-mode-view"]').click();
- cy.wait('@getViewsForHumanSkull');
- cy.get('[data-testid="view-item-View_DX_H_SKULL_AP"]').click();
- /**
- * Then: 验证已选列表包含 1 个体位
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 1);
- /**
- * When: 切换身体部位到 "颈部"
- * 步骤1: 打开身体部位选择器
- * 步骤2: 选择 "颈部"
- */
- cy.get('[data-testid="body-part-selector"]').click();
- cy.get('[data-testid="body-part-option-Human_NECK"]').click();
- /**
- * Then: 已选列表应该保持不变
- * 步骤3: 验证已选列表仍然包含 1 个体位
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 1);
- cy.get('[data-testid="selected-view-count"]')
- .should('contain', '1');
- /**
- * Then: 验证 Redux store 状态
- */
- cy.window().its('store').invoke('getState')
- .its('viewSelection')
- .its('selectedViews')
- .should('have.length', 1);
- });
- /**
- * 测试场景 4:边界情况 - 已选列表为空时切换患者类型
- *
- * Given: 用户已选择患者类型但未添加任何体位
- * When: 用户切换到不同的患者类型
- * Then: 不应该产生错误
- */
- it('应该在已选列表为空时安全地切换患者类型', () => {
- /**
- * Given: 选择患者类型但不添加体位
- */
- cy.wait('@getMultiplePatientTypes');
-
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-Human"]').click();
- cy.wait('@getBodyPartForHuman');
- /**
- * Then: 验证已选列表为空
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 0);
- /**
- * When: 切换患者类型
- */
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-SpecialType"]').click();
- cy.wait('@getBodyPartForSpecialType');
- /**
- * Then: 应该没有错误,已选列表仍为空
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 0);
- // 验证没有错误提示
- cy.get('[data-testid="error-message"]').should('not.exist');
- });
- /**
- * 测试场景 5:边界情况 - 已选多个体位时切换患者类型
- *
- * Given: 用户已添加多个体位到已选列表
- * When: 用户切换患者类型
- * Then: 所有体位都应该被清空
- */
- it('应该在切换患者类型时清空所有已选择的体位', () => {
- /**
- * Given: 选择患者类型和身体部位
- */
- cy.wait('@getMultiplePatientTypes');
-
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-Human"]').click();
- cy.wait('@getBodyPartForHuman');
- cy.get('[data-testid="body-part-selector"]').click();
- cy.get('[data-testid="body-part-option-Human_SKULL"]').click();
- /**
- * Given: 切换到体位模式并添加多个体位
- */
- cy.get('[data-testid="selection-mode-view"]').click();
- cy.wait('@getViewsForHumanSkull');
- // 添加第一个体位
- cy.get('[data-testid="view-item-View_DX_H_SKULL_AP"]').click();
- // 添加第二个体位
- cy.get('[data-testid="view-item-View_DX_H_SKULL_LAT"]').click();
- /**
- * Then: 验证已选列表包含 2 个体位
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 2);
- /**
- * When: 切换患者类型
- */
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-SpecialType"]').click();
- cy.wait('@getBodyPartForSpecialType');
- /**
- * Then: 所有体位都应该被清空
- */
- cy.get('[data-testid="selected-views-list"]')
- .find('[data-testid^="selected-view-"]')
- .should('have.length', 0);
- cy.get('[data-testid="selected-view-count"]')
- .should('contain', '0');
- });
- /**
- * 测试场景 6:验证控制台日志输出
- *
- * Given: 用户已添加体位
- * When: 切换患者类型
- * Then: 应该在控制台输出清空体位的日志
- */
- it('应该在切换患者类型时输出正确的控制台日志', () => {
- /**
- * 监听控制台日志
- */
- cy.window().then((win) => {
- cy.spy(win.console, 'log').as('consoleLog');
- });
- /**
- * Given: 添加体位到已选列表
- */
- cy.wait('@getMultiplePatientTypes');
-
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-Human"]').click();
- cy.wait('@getBodyPartForHuman');
- cy.get('[data-testid="body-part-selector"]').click();
- cy.get('[data-testid="body-part-option-Human_SKULL"]').click();
- cy.get('[data-testid="selection-mode-view"]').click();
- cy.wait('@getViewsForHumanSkull');
- cy.get('[data-testid="view-item-View_DX_H_SKULL_AP"]').click();
- /**
- * When: 切换患者类型
- */
- cy.get('[data-testid="patient-type-selector"]').click();
- cy.get('[data-testid="patient-type-option-SpecialType"]').click();
- cy.wait('@getBodyPartForSpecialType');
- /**
- * Then: 验证控制台输出了清空日志
- */
- cy.get('@consoleLog').should('be.calledWith', '患者类型已变更,已选择体位列表已清空');
- });
- });
|