/** * 跨平台E2E测试套件 * * 测试uniapp和admin两个平台的数据一致性和功能完整性 * * @tags @cross-platform @e2e @integration */ import { test, expect, Page } from '@playwright/test' import { TestLogger } from './core/test-logger.js' interface AlmanacData { date: string lunarDate: string ganZhi: string zodiac: string solarTerm: string | null festivals: string[] yi: string[] ji: string[] } /** * 黄历页面对象 - UniApp */ class UniAppAlmanacPage { private page: Page private logger: TestLogger constructor(page: Page, logger: TestLogger) { this.page = page this.logger = logger } async navigate() { this.logger.info('导航到UniApp黄历页面') await this.page.goto('http://localhost:3000/pages/almanac/index') await this.page.waitForLoadState('networkidle') } async selectDate(date: string) { this.logger.info(`选择日期: ${date}`) await this.page.click(`[data-date="${date}"]`) } async getAlmanacData(): Promise { this.logger.info('获取黄历数据') const date = await this.page.locator('[data-testid="almanac-date"]').textContent() || '' const lunarDate = await this.page.locator('[data-testid="lunar-date"]').textContent() || '' const ganZhi = await this.page.locator('[data-testid="ganzhi"]').textContent() || '' const zodiac = await this.page.locator('[data-testid="zodiac"]').textContent() || '' const solarTerm = await this.page.locator('[data-testid="solar-term"]').textContent() return { date, lunarDate, ganZhi, zodiac, solarTerm: solarTerm || null, festivals: await this.page.locator('[data-testid="festival"]').allTextContents(), yi: await this.page.locator('[data-testid="yi-item"]').allTextContents(), ji: await this.page.locator('[data-testid="ji-item"]').allTextContents() } } } /** * 黄历页面对象 - Admin */ class AdminAlmanacPage { private page: Page private logger: TestLogger constructor(page: Page, logger: TestLogger) { this.page = page this.logger = logger } async navigate() { this.logger.info('导航到Admin黄历页面') await this.page.goto('http://localhost:5174/almanac') await this.page.waitForLoadState('networkidle') } async selectDate(date: string) { this.logger.info(`选择日期: ${date}`) await this.page.fill('[data-testid="date-input"]', date) await this.page.click('[data-testid="query-button"]') } async getAlmanacData(): Promise { this.logger.info('获取黄历数据') const date = await this.page.locator('[data-testid="almanac-date"]').textContent() || '' const lunarDate = await this.page.locator('[data-testid="lunar-date"]').textContent() || '' const ganZhi = await this.page.locator('[data-testid="ganzhi"]').textContent() || '' const zodiac = await this.page.locator('[data-testid="zodiac"]').textContent() || '' const solarTerm = await this.page.locator('[data-testid="solar-term"]').textContent() return { date, lunarDate, ganZhi, zodiac, solarTerm: solarTerm || null, festivals: await this.page.locator('[data-testid="festival"]').allTextContents(), yi: await this.page.locator('[data-testid="yi-item"]').allTextContents(), ji: await this.page.locator('[data-testid="ji-item"]').allTextContents() } } } test.describe('E2E: 跨平台数据一致性测试', () => { let logger: TestLogger test.beforeEach(() => { logger = new TestLogger() }) test('两个平台应该显示相同的农历日期 @cross-platform @critical', async ({ browser }) => { // Given: 测试日期 const testDate = '2024-02-10' // 春节 // 打开两个页面 const uniappContext = await browser.newContext() const adminContext = await browser.newContext() const uniappPage = await uniappContext.newPage() const adminPage = await adminContext.newPage() const uniappAlmanac = new UniAppAlmanacPage(uniappPage, logger) const adminAlmanac = new AdminAlmanacPage(adminPage, logger) // When: 两个平台选择相同日期 await uniappAlmanac.navigate() await adminAlmanac.navigate() await uniappAlmanac.selectDate(testDate) await adminAlmanac.selectDate(testDate) // Then: 农历日期应该一致 const uniappData = await uniappAlmanac.getAlmanacData() const adminData = await adminAlmanac.getAlmanacData() expect(uniappData.lunarDate).toBe(adminData.lunarDate) expect(uniappData.ganZhi).toBe(adminData.ganZhi) expect(uniappData.zodiac).toBe(adminData.zodiac) await uniappContext.close() await adminContext.close() }) test('两个平台应该显示相同的宜忌信息 @cross-platform', async ({ browser }) => { // Given: 测试日期 const testDate = '2024-06-01' const uniappContext = await browser.newContext() const adminContext = await browser.newContext() const uniappPage = await uniappContext.newPage() const adminPage = await adminContext.newPage() const uniappAlmanac = new UniAppAlmanacPage(uniappPage, logger) const adminAlmanac = new AdminAlmanacPage(adminPage, logger) // When: 两个平台选择相同日期 await uniappAlmanac.navigate() await adminAlmanac.navigate() await uniappAlmanac.selectDate(testDate) await adminAlmanac.selectDate(testDate) // Then: 宜忌信息应该一致 const uniappData = await uniappAlmanac.getAlmanacData() const adminData = await adminAlmanac.getAlmanacData() expect(uniappData.yi).toEqual(adminData.yi) expect(uniappData.ji).toEqual(adminData.ji) await uniappContext.close() await adminContext.close() }) test('两个平台应该显示相同的节日信息 @cross-platform', async ({ browser }) => { // Given: 节日日期 const festivalDates = [ { date: '2024-02-10', festival: '春节' }, { date: '2024-06-10', festival: '端午节' }, { date: '2024-09-17', festival: '中秋节' } ] for (const { date, festival } of festivalDates) { const uniappContext = await browser.newContext() const adminContext = await browser.newContext() const uniappPage = await uniappContext.newPage() const adminPage = await adminContext.newPage() const uniappAlmanac = new UniAppAlmanacPage(uniappPage, logger) const adminAlmanac = new AdminAlmanacPage(adminPage, logger) // When: 两个平台选择节日日期 await uniappAlmanac.navigate() await adminAlmanac.navigate() await uniappAlmanac.selectDate(date) await adminAlmanac.selectDate(date) // Then: 节日信息应该一致且包含对应节日 const uniappData = await uniappAlmanac.getAlmanacData() const adminData = await adminAlmanac.getAlmanacData() expect(uniappData.festivals).toContain(festival) expect(adminData.festivals).toContain(festival) expect(uniappData.festivals).toEqual(adminData.festivals) await uniappContext.close() await adminContext.close() } }) test('两个平台应该显示相同的节气信息 @cross-platform', async ({ browser }) => { // Given: 节气日期 const solarTermDates = [ { date: '2024-02-04', term: '立春' }, { date: '2024-03-20', term: '春分' }, { date: '2024-06-21', term: '夏至' } ] for (const { date, term } of solarTermDates) { const uniappContext = await browser.newContext() const adminContext = await browser.newContext() const uniappPage = await uniappContext.newPage() const adminPage = await adminContext.newPage() const uniappAlmanac = new UniAppAlmanacPage(uniappPage, logger) const adminAlmanac = new AdminAlmanacPage(adminPage, logger) // When: 两个平台选择节气日期 await uniappAlmanac.navigate() await adminAlmanac.navigate() await uniappAlmanac.selectDate(date) await adminAlmanac.selectDate(date) // Then: 节气信息应该一致 const uniappData = await uniappAlmanac.getAlmanacData() const adminData = await adminAlmanac.getAlmanacData() expect(uniappData.solarTerm).toBe(term) expect(adminData.solarTerm).toBe(term) expect(uniappData.solarTerm).toBe(adminData.solarTerm) await uniappContext.close() await adminContext.close() } }) }) test.describe('E2E: 跨平台响应式测试', () => { let logger: TestLogger test.beforeEach(() => { logger = new TestLogger() }) test('UniApp应该在移动端正常显示 @cross-platform @responsive', async ({ browser }) => { // Given: 移动端视口 const context = await browser.newContext({ viewport: { width: 375, height: 667 }, userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)' }) const page = await context.newPage() const uniappAlmanac = new UniAppAlmanacPage(page, logger) // When: 访问UniApp await uniappAlmanac.navigate() // Then: 页面应该正常显示 await expect(page.locator('[data-testid="almanac-container"]')).toBeVisible() await expect(page.locator('[data-testid="calendar-grid"]')).toBeVisible() await context.close() }) test('Admin应该在桌面端正常显示 @cross-platform @responsive', async ({ browser }) => { // Given: 桌面端视口 const context = await browser.newContext({ viewport: { width: 1920, height: 1080 } }) const page = await context.newPage() const adminAlmanac = new AdminAlmanacPage(page, logger) // When: 访问Admin await adminAlmanac.navigate() // Then: 页面应该正常显示 await expect(page.locator('[data-testid="almanac-container"]')).toBeVisible() await expect(page.locator('[data-testid="date-input"]')).toBeVisible() await context.close() }) }) test.describe('E2E: 跨平台性能测试', () => { let logger: TestLogger test.beforeEach(() => { logger = new TestLogger() }) test('两个平台的页面加载时间应该符合要求 @cross-platform @performance', async ({ browser }) => { // Given: 性能阈值 const maxLoadTime = 3000 // 3秒 // 测试UniApp const uniappContext = await browser.newContext() const uniappPage = await uniappContext.newPage() const uniappStart = Date.now() await uniappPage.goto('http://localhost:3000/pages/almanac/index') await uniappPage.waitForLoadState('networkidle') const uniappLoadTime = Date.now() - uniappStart logger.info(`UniApp加载时间: ${uniappLoadTime}ms`) expect(uniappLoadTime).toBeLessThan(maxLoadTime) await uniappContext.close() // 测试Admin const adminContext = await browser.newContext() const adminPage = await adminContext.newPage() const adminStart = Date.now() await adminPage.goto('http://localhost:5174/almanac') await adminPage.waitForLoadState('networkidle') const adminLoadTime = Date.now() - adminStart logger.info(`Admin加载时间: ${adminLoadTime}ms`) expect(adminLoadTime).toBeLessThan(maxLoadTime) await adminContext.close() }) test('两个平台的日期切换应该流畅 @cross-platform @performance', async ({ browser }) => { // Given: 性能阈值 const maxSwitchTime = 500 // 500ms const uniappContext = await browser.newContext() const adminContext = await browser.newContext() const uniappPage = await uniappContext.newPage() const adminPage = await adminContext.newPage() const uniappAlmanac = new UniAppAlmanacPage(uniappPage, logger) const adminAlmanac = new AdminAlmanacPage(adminPage, logger) // 测试UniApp日期切换 await uniappAlmanac.navigate() const uniappStart = Date.now() await uniappAlmanac.selectDate('2024-06-15') const uniappSwitchTime = Date.now() - uniappStart logger.info(`UniApp日期切换时间: ${uniappSwitchTime}ms`) expect(uniappSwitchTime).toBeLessThan(maxSwitchTime) // 测试Admin日期切换 await adminAlmanac.navigate() const adminStart = Date.now() await adminAlmanac.selectDate('2024-06-15') const adminSwitchTime = Date.now() - adminStart logger.info(`Admin日期切换时间: ${adminSwitchTime}ms`) expect(adminSwitchTime).toBeLessThan(maxSwitchTime) await uniappContext.close() await adminContext.close() }) }) test.describe('E2E: 跨平台API一致性测试', () => { let logger: TestLogger test.beforeEach(() => { logger = new TestLogger() }) test('两个平台应该使用相同的API端点 @cross-platform @api', async ({ request }) => { // Given: API端点 const endpoints = [ '/api/almanac/today', '/api/almanac/date', '/api/lunar/convert', '/api/solar-term/list' ] for (const endpoint of endpoints) { // When: 请求API const response = await request.get(`http://localhost:8080${endpoint}`) // Then: 应该返回成功状态 expect(response.status()).toBe(200) const data = await response.json() expect(data).toHaveProperty('code') expect(data).toHaveProperty('data') } }) test('API响应格式应该一致 @cross-platform @api', async ({ request }) => { // Given: 日期参数 const date = '2024-06-01' // When: 请求黄历数据 const response = await request.get(`http://localhost:8080/api/almanac/date?date=${date}`) // Then: 响应格式应该符合规范 const data = await response.json() expect(data.code).toBe(200) expect(data.data).toHaveProperty('date') expect(data.data).toHaveProperty('lunarDate') expect(data.data).toHaveProperty('ganZhi') expect(data.data).toHaveProperty('zodiac') expect(data.data).toHaveProperty('yi') expect(data.data).toHaveProperty('ji') }) })