import { test, expect } from '@playwright/test' import { gotoPage, clickButton } from './helpers' /** * 用户旅程 J-ALMANAC(Critical):黄历吉日搜索完整旅程 * * 用户目标:查找适合特定活动(嫁娶、搬家等)的黄道吉日 * * 旅程步骤: * 1. 进入黄历页(模板面板、搜索条件面板、空状态可见) * 2. 使用预置模板一键搜索(嫁娶吉日) * 3. 验证搜索结果卡片(日期、宜/忌、匹配数) * 4. 手动添加搜索条件(宜 → 嫁娶) * 5. 选择搜索天数范围 * 6. 执行搜索并验证结果 * * 错误恢复场景: * E1. 未添加条件直接搜索 → 显示"请添加搜索条件"提示 * E2. 搜索失败后可通过添加条件恢复 */ test.describe('旅程 J-ALMANAC:黄历吉日搜索完整旅程', () => { test.describe.configure({ mode: 'serial' }) test.beforeEach(async ({ page }) => { await gotoPage(page, '/pages/almanac-search/index') }) test('STEP 1: 进入黄历页,今日黄历/模板面板/搜索面板可见', async ({ page }) => { // 今日黄历默认显示(新需求:进入即展示当天宜忌) await expect(page.locator('.today-almanac')).toBeVisible() const todayTitle = await page.locator('.today-title').textContent() expect(todayTitle && todayTitle.length).toBeGreaterThan(0) // 宜/忌信息 await expect(page.locator('.suitable-items')).toBeVisible() await expect(page.locator('.unsuitable-items')).toBeVisible() await expect(page.locator('.template-panel')).toBeVisible() await expect(page.locator('.search-condition-panel')).toBeVisible() await expect(page.locator('.page-title')).toBeVisible() // 初始为未搜索空状态 await expect(page.locator('.search-result-list')).not.toBeVisible() }) test('STEP 2-3: 使用预置模板"嫁娶吉日"一键搜索并验证结果', async ({ page }) => { const template = page.locator('.template-item', { hasText: '嫁娶吉日' }).first() await expect(template).toBeVisible() await template.click() await page.waitForTimeout(1500) // 搜索结果列表出现 await expect(page.locator('.search-result-list')).toBeVisible() const resultCount = await page.locator('.search-result-card').count() expect(resultCount).toBeGreaterThan(0) }) test('STEP 4: 手动添加搜索条件(宜 → 嫁娶)', async ({ page }) => { await clickButton(page, /Add Condition/i) // 条件面板出现活动项选择 const itemTags = page.locator('.item-tag') await expect(itemTags.first()).toBeVisible() // 选择"嫁娶"活动 await page.locator('.item-tag', { hasText: '嫁娶' }).click() await page.waitForTimeout(300) // 验证选中状态 await expect(page.locator('.item-tag', { hasText: '嫁娶' })).toHaveClass(/item-tag-selected/) }) test('STEP 5-6: 选择天数范围并执行搜索', async ({ page }) => { // 先添加条件 await clickButton(page, /Add Condition/i) await page.locator('.item-tag', { hasText: '嫁娶' }).click() // 选择 60 天范围 await page.locator('.day-tag', { hasText: '60' }).click() await page.waitForTimeout(300) await expect(page.locator('.day-tag', { hasText: '60' })).toHaveClass(/day-tag-selected/) // 执行搜索 await clickButton(page, /Search/i) await page.waitForTimeout(1500) // 结果出现 await expect(page.locator('.search-result-list')).toBeVisible() const cards = page.locator('.search-result-card') const count = await cards.count() expect(count).toBeGreaterThan(0) // 验证结果卡片包含宜/匹配信息(i18n 英文环境显示 Suitable / Match) const firstCardText = (await cards.first().textContent()) || '' expect(firstCardText).toContain('Suitable') expect(firstCardText).toMatch(/Match/i) }) test('E1: 未添加条件直接搜索 → 显示提示', async ({ page }) => { await clickButton(page, /Search/i) await page.waitForTimeout(500) // 错误提示可见(error-container),或无搜索结果 const errorVisible = await page.locator('.error-container').isVisible().catch(() => false) const searchResultVisible = await page.locator('.search-result-list').isVisible().catch(() => false) expect(errorVisible || !searchResultVisible).toBe(true) }) test('E2: 搜索失败重试路径(重试按钮)', async ({ page }) => { // 触发一次无条件的搜索产生提示,验证重试路径存在 await clickButton(page, /Search/i) await page.waitForTimeout(500) // 页面仍可用:添加条件后可恢复搜索 await clickButton(page, /Add Condition/i) await page.locator('.item-tag', { hasText: '出行' }).click() await clickButton(page, /Search/i) await page.waitForTimeout(1500) const ok = await page.locator('.search-result-list').isVisible().catch(() => false) expect(ok).toBe(true) }) })