import { test, expect } from '@playwright/test' function ok(data: unknown) { return { status: 200, contentType: 'application/json', body: JSON.stringify({ code: 0, message: 'success', data }), headers: { 'X-Device-Key': 'e2e-device' }, } } test('star / rhythm / cards pages render with mocked API', async ({ page }) => { await page.route('**/api/v1/**', async (route) => { const url = route.request().url() const method = route.request().method() if (url.includes('/auth/me')) { await route.fulfill(ok({ id: 'u1', phone: '13800000000' })) return } if (url.includes('/profiles') && method === 'GET') { await route.fulfill(ok({ items: [] })) return } if (url.includes('/profiles') && method === 'POST') { await route.fulfill(ok({ id: 'prof-e2e', user_id: 'u1', relation: 'self', display_name: '我', birth_date: '1983-06-06', created_at: new Date().toISOString(), })) return } if (url.includes('/reports/star') && method === 'POST') { await route.fulfill(ok({ id: 'rep-star', type: 'star', has_deep_access: false, summary: { headline: 'E2E星象', one_liner: '星象摘要', keywords: ['灵活'], planets: [ { key: 'sun', title: '太阳', sign: '双子', degree: '10°', house: 1, lon: 70 }, ], chart: { note: '热带黄道', asc_lon: 70, houses: [{ num: 1, sign: '双子' }] }, aspects_preview: [], outlook: { daily: { title: '今日运势', label: '顺畅', score: 80, tip: 'e2e tip', focus: '行动', boost: '水', caution: '缓', dims: { love: 3, career: 4, money: 3, mood: 4 }, }, weekly: { title: '本周', label: '稳', score: 70, tip: 'w', focus: 'f', boost: 'b', caution: 'c' }, monthly: { title: '本月', label: '稳', score: 70, tip: 'm', focus: 'f', boost: 'b', caution: 'c' }, yearly: { title: '今年', label: '稳', score: 70, tip: 'y', focus: 'f', boost: 'b', caution: 'c' }, lifetime: { title: '一生运势摘要', label: '稳', score: 70, tip: 'l', focus: 'f', boost: 'b', caution: 'c' }, }, transits: [{ key: 't1', title: '行运提示', aspect: '合相', tip: '推进' }], }, detail: null, created_at: new Date().toISOString(), })) return } if (url.includes('/reports/rhythm') && method === 'POST') { await route.fulfill(ok({ id: 'rep-rhythm', type: 'rhythm', has_deep_access: false, summary: { headline: 'E2E节律', one_liner: '节律摘要' }, detail: null, created_at: new Date().toISOString(), })) return } if (url.includes('/image-cards/scenes')) { await route.fulfill(ok({ items: [{ key: '情绪整理', label: '情绪整理' }] })) return } if (url.includes('/image-cards/quota')) { await route.fulfill(ok({ remaining: 3, daily_free: 3, unlimited: false })) return } if (url.includes('/image-cards/draw') && method === 'POST') { await route.fulfill(ok({ scene: '情绪整理', quota_left: 2, cards: [{ id: 'c01', title: 'E2E卡片', imagery: '意象', prompt: '反思?', tip: '一小步', }], report: { id: 'rep-card', type: 'image_card', has_deep_access: false, summary: { headline: '意象探索' }, detail: null, }, })) return } if (url.includes('/solar-terms/today')) { await route.fulfill(ok({ name: '立秋', tip: '收敛节奏', date: '2026-08-02' })) return } if (url.includes('/moods/today')) { await route.fulfill(ok({ mood: null })) return } await route.fulfill(ok({})) }) await page.goto('/psy/star?y=1983&m=6&d=6') await expect(page.getByText('E2E星象')).toBeVisible() await expect(page.getByRole('button', { name: /解锁完整分析/ })).toBeVisible() await page.getByRole('button', { name: '运势' }).click() await expect(page.getByText('今日运势')).toBeVisible() await expect(page.getByText('焦点:行动')).toBeVisible() await page.goto('/psy/rhythm?y=1992&m=6&d=8') await expect(page.getByText('身心节律').first()).toBeVisible() await expect(page.getByText('E2E节律')).toBeVisible() await page.goto('/psy/cards') await expect(page.getByRole('heading', { name: '意象卡片' })).toBeVisible() await expect(page.getByText('投射整理 · 自我反思')).toBeVisible() await page.getByRole('button', { name: '关联生日' }).click() await page.locator('input[type="number"]').nth(0).fill('1990') await page.locator('input[type="number"]').nth(1).fill('5') await page.locator('input[type="number"]').nth(2).fill('12') await page.getByRole('button', { name: '抽取卡片' }).click() await expect(page.getByText('E2E卡片')).toBeVisible() await page.goto('/psy/companion') await expect(page.getByText('立秋')).toBeVisible() await expect(page.getByText('今日心情')).toBeVisible() })