Files
wenzi/frontend/h5/cypress/e2e/userOperations.cy.js
Your Name 91a0b77f7a test(cache): 修复CacheConfigTest边界值测试
- 修改 shouldVerifyCacheManager_withMaximumIntegerTtl 为 shouldVerifyCacheManager_withMaximumAllowedTtl
- 使用正确的最大TTL值(10080分钟,7天)而不是 Integer.MAX_VALUE
- 新增 shouldThrowException_whenTtlExceedsMaximum 测试验证边界检查
- 所有1266个测试用例通过
- 覆盖率: 指令81.89%, 行88.48%, 分支51.55%

docs: 添加项目状态报告
- 生成 PROJECT_STATUS_REPORT.md 详细记录项目当前状态
- 包含质量指标、已完成功能、待办事项和技术债务
2026-03-02 13:31:54 +08:00

506 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// <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');
});
});
});