/** * 测试文件: 阶段1-登录与注册 * 路径: 异常1-登录失败 * * 路径分析: * - POM: LoginPage * - Mock: mockLoginFail() * - 规格: * ✓ 输入错误的用户名和密码 * ✓ 系统显示错误提示 "登录失败" * ✓ 停留在登录页面 * - 需要新建: 无 * - 需要添加: 错误提示的data-testid(可选,可用文本查找) * - 已有的data-testid: * - login-username-input - 用户名输入框 * - login-password-input - 密码输入框 * - login-submit-button - 登录按钮 */ import { mockLoginFail } from '../../support/mock/handlers/user'; import LoginPage from '../../support/pageObjects/LoginPage'; describe('阶段1:登录与注册 - 异常1:登录失败', () => { const loginPage = new LoginPage(); beforeEach(() => { // 设置Mock API - 登录失败场景 mockLoginFail(); }); it('应该显示错误提示并停留在登录页面', () => { /** * Given: 用户在登录页面 * 步骤1: 打开登录界面(隐含) */ loginPage.visit(); // 验证登录页面元素可见 loginPage.getUsernameInput().should('be.visible'); loginPage.getPasswordInput().should('be.visible'); loginPage.getSubmitButton().should('be.visible'); /** * When: 用户输入错误的用户名和密码 * 步骤1: 输入错误的用户名/密码 */ loginPage.login('wronguser', 'wrongpassword'); /** * Then: 系统提示错误 * 步骤2: 系统提示错误 */ // 等待登录API响应 cy.wait('@loginFail').then((interception) => { // 验证API返回错误 expect(interception.response?.statusCode).to.eq(200); expect(interception.response?.body.code).to.eq('0x000001'); expect(interception.response?.body.description).to.include('Invalid username or password'); }); /** * Then: 显示登录失败提示,停留在登录页面 * 步骤2-3: 系统提示错误 → 超过限制 → 账号锁定(本测试只验证单次失败) */ // 验证显示登录失败提示 cy.contains('登录失败').should('be.visible', { timeout: 10000 }); /** * Then: 用户停留在登录页面 * 验证仍在登录页面 - 登录按钮仍然可见 */ loginPage.getSubmitButton().should('be.visible'); // 验证用户名输入框仍然可见(确认没有跳转) loginPage.getUsernameInput().should('be.visible'); }); });