506 lines
16 KiB
JavaScript
506 lines
16 KiB
JavaScript
|
|
/// <reference types="cypress" />
|
|||
|
|
|
|||
|
|
describe('蚊子项目 - 用户操作端到端测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
// 清理存储和缓存
|
|||
|
|
cy.clearLocalStorage();
|
|||
|
|
cy.clearCookies();
|
|||
|
|
|
|||
|
|
// 设置viewport
|
|||
|
|
cy.viewport(375, 812); // 移动端尺寸
|
|||
|
|
|
|||
|
|
// Mock API响应
|
|||
|
|
cy.intercept('GET', '/api/auth/profile', { fixture: 'user-profile.json' }).as('getUserProfile');
|
|||
|
|
cy.intercept('GET', '/api/coupons/available', { fixture: 'coupons.json' }).as('getCoupons');
|
|||
|
|
cy.intercept('POST', '/api/coupons/*/claim', { fixture: 'coupon-claim-success.json' }).as('claimCoupon');
|
|||
|
|
cy.intercept('GET', '/api/stats/personal', { fixture: 'personal-stats.json' }).as('getPersonalStats');
|
|||
|
|
cy.intercept('GET', '/api/stats/team', { fixture: 'team-stats.json' }).as('getTeamStats');
|
|||
|
|
cy.intercept('GET', '/api/reward/invite-code', { fixture: 'invite-code.json' }).as('getInviteCode');
|
|||
|
|
cy.intercept('POST', '/api/short-links/generate', { fixture: 'short-link.json' }).as('generateShortLink');
|
|||
|
|
cy.intercept('POST', '/api/auth/login', { fixture: 'login-success.json' }).as('login');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('用户注册和登录流程', () => {
|
|||
|
|
it('应该能够完成用户注册流程', () => {
|
|||
|
|
cy.visit('/');
|
|||
|
|
|
|||
|
|
// 点击注册按钮
|
|||
|
|
cy.get('[data-testid="register-button"]').click();
|
|||
|
|
|
|||
|
|
// 填写手机号
|
|||
|
|
cy.get('[data-testid="phone-input"]').type('13800138001');
|
|||
|
|
|
|||
|
|
// 点击获取验证码
|
|||
|
|
cy.get('[data-testid="get-sms-code"]').click();
|
|||
|
|
|
|||
|
|
// 等待验证码(模拟)
|
|||
|
|
cy.wait(1000);
|
|||
|
|
|
|||
|
|
// 填写验证码
|
|||
|
|
cy.get('[data-testid="sms-code-input"]').type('123456');
|
|||
|
|
|
|||
|
|
// 设置密码
|
|||
|
|
cy.get('[data-testid="password-input"]').type('Test123456');
|
|||
|
|
|
|||
|
|
// 填写邀请码(可选)
|
|||
|
|
cy.get('[data-testid="invite-code-input"]').type('INVITE123');
|
|||
|
|
|
|||
|
|
// 提交注册
|
|||
|
|
cy.get('[data-testid="submit-register"]').click();
|
|||
|
|
|
|||
|
|
// 验证注册成功
|
|||
|
|
cy.url().should('include', '/dashboard');
|
|||
|
|
cy.get('[data-testid="welcome-message"]').should('contain', '欢迎');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该能够完成用户登录流程', () => {
|
|||
|
|
cy.visit('/login');
|
|||
|
|
|
|||
|
|
// 填写登录信息
|
|||
|
|
cy.get('[data-testid="phone-input"]').type('13800138001');
|
|||
|
|
cy.get('[data-testid="password-input"]').type('Test123456');
|
|||
|
|
|
|||
|
|
// 提交登录
|
|||
|
|
cy.get('[data-testid="submit-login"]').click();
|
|||
|
|
|
|||
|
|
// 验证登录成功
|
|||
|
|
cy.wait('@login');
|
|||
|
|
cy.url().should('include', '/dashboard');
|
|||
|
|
cy.get('[data-testid="user-avatar"]').should('be.visible');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该能够处理登录错误', () => {
|
|||
|
|
cy.intercept('POST', '/api/auth/login', {
|
|||
|
|
statusCode: 401,
|
|||
|
|
body: { success: false, message: '手机号或密码错误' }
|
|||
|
|
}).as('loginError');
|
|||
|
|
|
|||
|
|
cy.visit('/login');
|
|||
|
|
|
|||
|
|
// 填写错误信息
|
|||
|
|
cy.get('[data-testid="phone-input"]').type('13800138001');
|
|||
|
|
cy.get('[data-testid="password-input"]').type('wrongpassword');
|
|||
|
|
|
|||
|
|
// 提交登录
|
|||
|
|
cy.get('[data-testid="submit-login"]').click();
|
|||
|
|
|
|||
|
|
// 验证错误提示
|
|||
|
|
cy.wait('@loginError');
|
|||
|
|
cy.get('[data-testid="error-message"]').should('contain', '手机号或密码错误');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('优惠券功能测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
// 设置登录状态
|
|||
|
|
cy.window().then((win) => {
|
|||
|
|
win.localStorage.setItem('token', 'mock-jwt-token');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该显示可用优惠券列表', () => {
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
|
|||
|
|
// 等待优惠券加载
|
|||
|
|
cy.wait('@getCoupons');
|
|||
|
|
|
|||
|
|
// 验证优惠券显示
|
|||
|
|
cy.get('[data-testid="coupon-card"]').should('have.length', 2);
|
|||
|
|
cy.get('[data-testid="coupon-1"]').should('contain', '新用户专享优惠券');
|
|||
|
|
cy.get('[data-testid="coupon-2"]').should('contain', '限时特惠券');
|
|||
|
|
|
|||
|
|
// 验证优惠券信息
|
|||
|
|
cy.get('[data-testid="coupon-1"]').should('contain', '满100减10元');
|
|||
|
|
cy.get('[data-testid="coupon-2"]').should('contain', '满50减5元');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该能够领取优惠券', () => {
|
|||
|
|
cy.visit('/coupons');
|
|||
|
|
|
|||
|
|
cy.wait('@getCoupons');
|
|||
|
|
|
|||
|
|
// 点击领取第一个优惠券
|
|||
|
|
cy.get('[data-testid="coupon-1"]').within(() => {
|
|||
|
|
cy.get('[data-testid="claim-button"]').click();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 等待领取响应
|
|||
|
|
cy.wait('@claimCoupon');
|
|||
|
|
|
|||
|
|
// 验证成功提示
|
|||
|
|
cy.get('[data-testid="success-toast"]').should('contain', '优惠券领取成功');
|
|||
|
|
|
|||
|
|
// 验证按钮状态变化
|
|||
|
|
cy.get('[data-testid="coupon-1"]').within(() => {
|
|||
|
|
cy.get('[data-testid="claim-button"]').should('contain', '已领取');
|
|||
|
|
cy.get('[data-testid="claim-button"]').should('be.disabled');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该显示已领取的优惠券', () => {
|
|||
|
|
cy.intercept('GET', '/api/coupons/my', { fixture: 'my-coupons.json' }).as('getMyCoupons');
|
|||
|
|
|
|||
|
|
cy.visit('/coupons/my');
|
|||
|
|
|
|||
|
|
cy.wait('@getMyCoupons');
|
|||
|
|
|
|||
|
|
// 验证我的优惠券列表
|
|||
|
|
cy.get('[data-testid="my-coupon-list"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="my-coupon-1"]').should('contain', '新用户专享优惠券');
|
|||
|
|
cy.get('[data-testid="my-coupon-1"]').should('contain', '已使用:0张');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该能够分享优惠券', () => {
|
|||
|
|
cy.visit('/coupons');
|
|||
|
|
|
|||
|
|
cy.wait('@getCoupons');
|
|||
|
|
|
|||
|
|
// 点击分享按钮
|
|||
|
|
cy.get('[data-testid="coupon-1"]').within(() => {
|
|||
|
|
cy.get('[data-testid="share-button"]').click();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 验证分享弹窗
|
|||
|
|
cy.get('[data-testid="share-modal"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="share-link"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="copy-link-button"]').should('be.visible');
|
|||
|
|
|
|||
|
|
// 测试复制链接
|
|||
|
|
cy.get('[data-testid="copy-link-button"]').click();
|
|||
|
|
cy.get('[data-testid="copy-success"]').should('contain', '链接已复制');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('数据统计功能测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
cy.window().then((win) => {
|
|||
|
|
win.localStorage.setItem('token', 'mock-jwt-token');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该显示个人统计数据', () => {
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
|
|||
|
|
cy.wait('@getPersonalStats');
|
|||
|
|
|
|||
|
|
// 验证统计卡片
|
|||
|
|
cy.get('[data-testid="stats-card-total-clicks"]').should('contain', '1,250');
|
|||
|
|
cy.get('[data-testid="stats-card-conversions"]').should('contain', '89');
|
|||
|
|
cy.get('[data-testid="stats-card-earnings"]').should('contain', '¥1,256.78');
|
|||
|
|
cy.get('[data-testid="stats-card-today-earnings"]').should('contain', '¥45.50');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该显示团队统计数据', () => {
|
|||
|
|
cy.visit('/team');
|
|||
|
|
|
|||
|
|
cy.wait('@getTeamStats');
|
|||
|
|
|
|||
|
|
// 验证团队统计
|
|||
|
|
cy.get('[data-testid="team-stats-level1"]').should('contain', '8');
|
|||
|
|
cy.get('[data-testid="team-stats-level2"]').should('contain', '12');
|
|||
|
|
cy.get('[data-testid="team-stats-level3"]').should('contain', '6');
|
|||
|
|
cy.get('[data-testid="team-stats-total-earnings"]').should('contain', '¥3,456.78');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该显示趋势图表', () => {
|
|||
|
|
cy.intercept('GET', '/api/stats/trends', { fixture: 'trends.json' }).as('getTrends');
|
|||
|
|
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
|
|||
|
|
cy.wait('@getTrends');
|
|||
|
|
|
|||
|
|
// 验证图表显示
|
|||
|
|
cy.get('[data-testid="trend-chart"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="chart-canvas"]').should('be.visible');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该能够切换时间范围', () => {
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
|
|||
|
|
// 点击时间范围选择器
|
|||
|
|
cy.get('[data-testid="time-range-selector"]').click();
|
|||
|
|
|
|||
|
|
// 选择本周
|
|||
|
|
cy.get('[data-testid="range-week"]').click();
|
|||
|
|
|
|||
|
|
// 验证数据更新
|
|||
|
|
cy.get('[data-testid="time-range-display"]').should('contain', '本周');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('邀请功能测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
cy.window().then((win) => {
|
|||
|
|
win.localStorage.setItem('token', 'mock-jwt-token');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该生成邀请码和邀请链接', () => {
|
|||
|
|
cy.visit('/invite');
|
|||
|
|
|
|||
|
|
cy.wait('@getInviteCode');
|
|||
|
|
|
|||
|
|
// 验证邀请信息显示
|
|||
|
|
cy.get('[data-testid="invite-code"]').should('contain', 'INVITE123');
|
|||
|
|
cy.get('[data-testid="invite-link"]').should('contain', 'https://mosquito.com/invite/INVITE123');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该能够复制邀请链接', () => {
|
|||
|
|
cy.visit('/invite');
|
|||
|
|
|
|||
|
|
cy.wait('@getInviteCode');
|
|||
|
|
|
|||
|
|
// 点击复制按钮
|
|||
|
|
cy.get('[data-testid="copy-invite-link"]').click();
|
|||
|
|
|
|||
|
|
// 验证复制成功提示
|
|||
|
|
cy.get('[data-testid="copy-success"]').should('contain', '邀请链接已复制');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该显示邀请记录', () => {
|
|||
|
|
cy.intercept('GET', '/api/reward/invite-records', { fixture: 'invite-records.json' }).as('getInviteRecords');
|
|||
|
|
|
|||
|
|
cy.visit('/invite');
|
|||
|
|
|
|||
|
|
cy.wait('@getInviteRecords');
|
|||
|
|
|
|||
|
|
// 验证邀请记录列表
|
|||
|
|
cy.get('[data-testid="invite-records"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="invite-record-1"]').should('contain', '138****8001');
|
|||
|
|
cy.get('[data-testid="invite-record-1"]').should('contain', '¥10.00');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('短链功能测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
cy.window().then((win) => {
|
|||
|
|
win.localStorage.setItem('token', 'mock-jwt-token');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该能够生成短链', () => {
|
|||
|
|
cy.visit('/short-links');
|
|||
|
|
|
|||
|
|
// 填写目标URL
|
|||
|
|
cy.get('[data-testid="original-url-input"]').type('https://example.com/landing-page');
|
|||
|
|
|
|||
|
|
// 填写活动名称
|
|||
|
|
cy.get('[data-testid="campaign-input"]').type('test-campaign');
|
|||
|
|
|
|||
|
|
// 点击生成按钮
|
|||
|
|
cy.get('[data-testid="generate-button"]').click();
|
|||
|
|
|
|||
|
|
// 等待生成响应
|
|||
|
|
cy.wait('@generateShortLink');
|
|||
|
|
|
|||
|
|
// 验证短链生成
|
|||
|
|
cy.get('[data-testid="short-code"]').should('contain', 'abc123');
|
|||
|
|
cy.get('[data-testid="short-url"]').should('contain', 'https://mosquito.com/s/abc123');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该显示短链统计', () => {
|
|||
|
|
cy.intercept('GET', '/api/short-links', { fixture: 'short-links.json' }).as('getShortLinks');
|
|||
|
|
|
|||
|
|
cy.visit('/short-links');
|
|||
|
|
|
|||
|
|
cy.wait('@getShortLinks');
|
|||
|
|
|
|||
|
|
// 验证短链列表
|
|||
|
|
cy.get('[data-testid="short-link-list"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="short-link-1"]').should('contain', 'abc123');
|
|||
|
|
cy.get('[data-testid="short-link-1"]').should('contain', '125');
|
|||
|
|
cy.get('[data-testid="short-link-1"]').should('contain', '7.2%');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该能够测试短链跳转', () => {
|
|||
|
|
cy.visit('/short-links');
|
|||
|
|
|
|||
|
|
cy.wait('@getShortLinks');
|
|||
|
|
|
|||
|
|
// 点击测试跳转按钮
|
|||
|
|
cy.get('[data-testid="test-redirect-button"]').click();
|
|||
|
|
|
|||
|
|
// 验证新窗口打开(需要处理弹出窗口)
|
|||
|
|
cy.get('@testRedirect').should('be.called');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('响应式设计测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
cy.window().then((win) => {
|
|||
|
|
win.localStorage.setItem('token', 'mock-jwt-token');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('在移动端应该正确显示', () => {
|
|||
|
|
cy.viewport(375, 812); // iPhone X
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
|
|||
|
|
cy.wait('@getPersonalStats');
|
|||
|
|
|
|||
|
|
// 验证移动端布局
|
|||
|
|
cy.get('[data-testid="mobile-layout"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="stats-grid"]').should('have.css', 'grid-template-columns', '1fr');
|
|||
|
|
|
|||
|
|
// 验证底部导航
|
|||
|
|
cy.get('[data-testid="bottom-navigation"]').should('be.visible');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('在平板端应该正确显示', () => {
|
|||
|
|
cy.viewport(768, 1024); // iPad
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
|
|||
|
|
cy.wait('@getPersonalStats');
|
|||
|
|
|
|||
|
|
// 验证平板端布局
|
|||
|
|
cy.get('[data-testid="tablet-layout"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="stats-grid"]').should('have.css', 'grid-template-columns', 'repeat(2, 1fr)');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('在桌面端应该正确显示', () => {
|
|||
|
|
cy.viewport(1200, 800); // Desktop
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
|
|||
|
|
cy.wait('@getPersonalStats');
|
|||
|
|
|
|||
|
|
// 验证桌面端布局
|
|||
|
|
cy.get('[data-testid="desktop-layout"]').should('be.visible');
|
|||
|
|
cy.get('[data-testid="stats-grid"]').should('have.css', 'grid-template-columns', 'repeat(4, 1fr)');
|
|||
|
|
|
|||
|
|
// 验证侧边栏
|
|||
|
|
cy.get('[data-testid="sidebar"]').should('be.visible');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('性能测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
cy.window().then((win) => {
|
|||
|
|
win.localStorage.setItem('token', 'mock-jwt-token');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('页面加载时间应该在合理范围内', () => {
|
|||
|
|
const startTime = Date.now();
|
|||
|
|
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
cy.wait('@getPersonalStats');
|
|||
|
|
|
|||
|
|
cy.get('[data-testid="stats-container"]').should('be.visible');
|
|||
|
|
|
|||
|
|
const loadTime = Date.now() - startTime;
|
|||
|
|
expect(loadTime).to.be.lessThan(3000); // 3秒内加载完成
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('大量数据渲染不应该影响性能', () => {
|
|||
|
|
// Mock大量优惠券数据
|
|||
|
|
const largeCoupons = Array.from({ length: 1000 }, (_, i) => ({
|
|||
|
|
id: i.toString(),
|
|||
|
|
name: `优惠券 ${i + 1}`,
|
|||
|
|
description: `满${(i + 1) * 10}减${i + 1}元`,
|
|||
|
|
discount: i + 1,
|
|||
|
|
minAmount: (i + 1) * 10,
|
|||
|
|
claimed: false
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
cy.intercept('GET', '/api/coupons/available', {
|
|||
|
|
body: { success: true, data: largeCoupons }
|
|||
|
|
}).as('getLargeCoupons');
|
|||
|
|
|
|||
|
|
const startTime = Date.now();
|
|||
|
|
|
|||
|
|
cy.visit('/coupons');
|
|||
|
|
cy.wait('@getLargeCoupons');
|
|||
|
|
|
|||
|
|
cy.get('[data-testid="coupon-list"]').should('be.visible');
|
|||
|
|
|
|||
|
|
const renderTime = Date.now() - startTime;
|
|||
|
|
expect(renderTime).to.be.lessThan(2000); // 2秒内渲染完成
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('错误处理测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
cy.window().then((win) => {
|
|||
|
|
win.localStorage.setItem('token', 'mock-jwt-token');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该处理网络错误', () => {
|
|||
|
|
cy.intercept('GET', '/api/stats/personal', {
|
|||
|
|
statusCode: 0,
|
|||
|
|
body: {}
|
|||
|
|
}).as('networkError');
|
|||
|
|
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
cy.wait('@networkError');
|
|||
|
|
|
|||
|
|
// 验证错误提示
|
|||
|
|
cy.get('[data-testid="error-toast"]').should('contain', '网络连接失败');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该处理服务器错误', () => {
|
|||
|
|
cy.intercept('GET', '/api/stats/personal', {
|
|||
|
|
statusCode: 500,
|
|||
|
|
body: { success: false, message: '服务器内部错误' }
|
|||
|
|
}).as('serverError');
|
|||
|
|
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
cy.wait('@serverError');
|
|||
|
|
|
|||
|
|
// 验证错误提示
|
|||
|
|
cy.get('[data-testid="error-toast"]').should('contain', '服务器内部错误');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该处理认证错误', () => {
|
|||
|
|
cy.intercept('GET', '/api/stats/personal', {
|
|||
|
|
statusCode: 401,
|
|||
|
|
body: { success: false, message: '未授权访问' }
|
|||
|
|
}).as('authError');
|
|||
|
|
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
cy.wait('@authError');
|
|||
|
|
|
|||
|
|
// 验证跳转到登录页
|
|||
|
|
cy.url().should('include', '/login');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('可访问性测试', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
cy.window().then((win) => {
|
|||
|
|
win.localStorage.setItem('token', 'mock-jwt-token');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该支持键盘导航', () => {
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
cy.wait('@getPersonalStats');
|
|||
|
|
|
|||
|
|
// 测试Tab键导航
|
|||
|
|
cy.get('body').tab();
|
|||
|
|
cy.focused().should('have.attr', 'data-testid', 'skip-to-content');
|
|||
|
|
|
|||
|
|
// 继续Tab导航
|
|||
|
|
cy.focused().tab();
|
|||
|
|
cy.focused().should('have.attr', 'data-testid', 'mobile-menu-button');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该有正确的ARIA标签', () => {
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
cy.wait('@getPersonalStats');
|
|||
|
|
|
|||
|
|
// 验证重要元素的ARIA标签
|
|||
|
|
cy.get('[data-testid="stats-container"]').should('have.attr', 'aria-label', '用户统计数据');
|
|||
|
|
cy.get('[data-testid="total-clicks"]').should('have.attr', 'aria-label', '总点击次数');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('应该支持屏幕阅读器', () => {
|
|||
|
|
cy.visit('/dashboard');
|
|||
|
|
cy.wait('@getPersonalStats');
|
|||
|
|
|
|||
|
|
// 验证重要内容有文本描述
|
|||
|
|
cy.get('[data-testid="stats-card-total-clicks"]').should('contain', '1,250');
|
|||
|
|
cy.get('[data-testid="stats-card-total-clicks"]').should('have.attr', 'aria-describedby');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|