import { expect, test } from '@playwright/test' import { getDebugState, patchAdminSiteSettings, resetMockState } from './helpers' test.beforeEach(async ({ request }) => { await resetMockState(request) }) test('首页过滤、热门区和文章详情链路可用', async ({ page }) => { await page.goto('/') await expect(page.locator('#home-results-count')).toContainText(/条结果/) await page.locator('[data-home-category-filter="测试体系"]').click() await expect(page.locator('#home-active-category-text')).toHaveText('测试体系') await page.locator('[data-home-tag-filter="Playwright"]').click() await expect(page.locator('#home-active-tag-text')).toHaveText('Playwright') await page.locator('[data-home-popular-range="30d"]').click() await expect(page.locator('#home-stats-window-pill')).toHaveText('30d') await page.locator('a[href="/articles/playwright-regression-workflow"]').first().click() await expect(page).toHaveURL(/\/articles\/playwright-regression-workflow$/) await expect(page.getByRole('heading', { name: 'Playwright 回归工作流设计' })).toBeVisible() await expect(page.locator('.paragraph-comment-marker').first()).toBeVisible() await page.goto('/categories/frontend-engineering') await expect(page.getByRole('heading', { name: '前端工程' })).toBeVisible() await expect(page.getByText('Astro 终端博客信息架构实战')).toBeVisible() await page.goto('/tags/playwright') await expect(page.getByRole('heading', { name: 'Playwright', exact: true })).toBeVisible() await expect(page.getByText('Playwright 回归工作流设计')).toBeVisible() await page.goto('/reviews') await expect(page.getByText('《宇宙探索编辑部》')).toHaveCount(0) await page.goto('/reviews/4') await expect(page.getByRole('heading', { name: '评价不存在' })).toBeVisible() await page.goto('/reviews/1') await page.getByRole('link', { name: '#年度最佳' }).click() await expect(page).toHaveURL(/\/reviews\?tag=%E5%B9%B4%E5%BA%A6%E6%9C%80%E4%BD%B3$/) await expect(page.getByText('《漫长的季节》')).toBeVisible() await page.goto('/reviews/1') await page.getByRole('link', { name: '动画' }).click() await expect(page).toHaveURL(/\/reviews\?type=anime$/) await expect(page.locator('#reviews-subtitle')).toContainText('动画') await expect(page.getByText('《漫长的季节》')).toBeVisible() await page.goto('/reviews/1') await page.getByRole('link', { name: '已完成' }).click() await expect(page).toHaveURL(/\/reviews\?status=completed$/) await expect(page.locator('#reviews-subtitle')).toContainText('已完成') await expect(page.getByText('《漫长的季节》')).toBeVisible() }) test('文章评论、搜索和 AI 问答链路可用', async ({ page, request }) => { await page.goto('/articles/astro-terminal-blog') await page.locator('#toggle-comment-form').click() await page.locator('#comment-form input[name="nickname"]').fill('Playwright Visitor') await page.locator('#comment-form input[name="email"]').fill('visitor@example.com') await page.locator('#comment-form textarea[name="content"]').fill('这是一条来自回归测试的新评论。') await page.locator('#comment-form input[name="captchaAnswer"]').fill('7') await page.getByRole('button', { name: '提交' }).click() await expect(page.locator('#comment-message')).toContainText('提交') const commentState = await getDebugState(request) expect(commentState.comments.some((item: { author: string }) => item.author === 'Playwright Visitor')).toBeTruthy() await page.goto('/search?q=playwright') await expect(page.getByText('Playwright 回归工作流设计')).toBeVisible() await page.goto('/ask') await page.locator('#ai-question').fill('这个博客主要写什么内容?') await page.locator('#ai-submit').click() await expect(page.locator('#ai-answer')).toContainText('Playwright 回归工作流') }) test('友链申请与订阅确认/偏好/退订链路可用', async ({ page, request }) => { await page.goto('/friends') await page.locator('input[name="siteName"]').fill('Playwright Friend') await page.locator('input[name="siteUrl"]').fill('https://playwright-friend.example') await page.locator('textarea[name="description"]').fill('回归测试用的友链申请。') await page.locator('label', { hasText: '[其他]' }).click() await page.locator('#has-reciprocal').check() await page.getByRole('button', { name: '提交申请' }).click() await expect(page.locator('#form-message')).toContainText('提交') const friendState = await getDebugState(request) expect(friendState.friend_links.some((item: { site_name: string }) => item.site_name === 'Playwright Friend')).toBeTruthy() await page.goto('/') await page.locator('[data-subscribe-form] input[name="displayName"]').fill('首页订阅用户') await page.locator('[data-subscribe-form] input[name="email"]').fill('inline-subscriber@example.com') await page.locator('[data-subscribe-form] button[type="submit"]').click() await expect(page.locator('[data-subscribe-status]')).toContainText('订阅') await page.locator('[data-subscription-popup-open]').click() await expect(page.locator('[data-subscription-popup-panel]')).toBeVisible() await page.locator('[data-subscription-popup-form] input[name="displayName"]').fill('弹窗订阅用户') await page.locator('[data-subscription-popup-email]').fill('playwright-subscriber@example.com') await page.locator('[data-subscription-popup-form] button[type="submit"]').click() await expect(page.locator('[data-subscription-popup-status]')).toContainText('订阅') const subscriptionState = await getDebugState(request) const inlineRecord = subscriptionState.subscriptions.find( (item: { target: string; display_name: string }) => item.target === 'inline-subscriber@example.com', ) expect(inlineRecord?.display_name).toBe('首页订阅用户') const latest = subscriptionState.subscriptions.find( (item: { target: string; display_name: string }) => item.target === 'playwright-subscriber@example.com', ) expect(latest).toBeTruthy() expect(latest.display_name).toBe('弹窗订阅用户') await page.goto(`/subscriptions/confirm?token=${encodeURIComponent(latest.confirm_token)}`) await expect(page.getByText('订阅已确认')).toBeVisible() await page.goto(`/subscriptions/manage?token=${encodeURIComponent(latest.manage_token)}`) await page.getByRole('textbox', { name: '称呼' }).fill('回归通知') await page.getByRole('button', { name: '保存偏好' }).click() await expect(page.locator('[data-manage-status]')).toContainText('偏好已保存') await page.goto(`/subscriptions/unsubscribe?token=${encodeURIComponent(latest.manage_token)}`) await page.getByRole('button', { name: '确认退订' }).click() await expect(page.locator('[data-unsubscribe-status]')).toContainText('成功退订') }) test('GEO 分享面板、AI 摘要块与 llms 入口可用', async ({ page, request }) => { await patchAdminSiteSettings(request, { seoWechatShareQrEnabled: true, }) await page.goto('/') await expect(page.locator('head link[rel="alternate"][href$="/llms.txt"]')).toHaveCount(1) await expect(page.locator('head link[rel="alternate"][href$="/llms-full.txt"]')).toHaveCount(1) await expect(page.getByRole('heading', { name: '给 AI 看的站点摘要' })).toBeVisible() await expect(page.getByRole('button', { name: '微信扫码' }).first()).toBeVisible() await page.goto('/about') await expect(page.getByRole('heading', { name: '给 AI 看的身份摘要' })).toBeVisible() await expect(page.getByText('身份主页')).toBeVisible() await page.goto('/articles') await expect(page.getByRole('heading', { name: '给 AI 看的归档摘要' })).toBeVisible() await page.goto('/reviews') await expect(page.getByRole('heading', { name: '给 AI 看的评测摘要' })).toBeVisible() await page.goto('/ask') await expect(page.getByRole('heading', { name: '给 AI 看的问答页摘要' })).toBeVisible() await page.goto('/friends') await expect(page.getByRole('heading', { name: '给 AI 看的友链网络摘要' })).toBeVisible() await page.goto('/articles/playwright-regression-workflow') await page.getByRole('button', { name: '微信扫码' }).first().click() await expect(page.locator('[data-article-wechat-qr-modal]')).toHaveAttribute('aria-hidden', 'false') await expect(page.getByRole('heading', { name: '微信扫码分享' })).toBeVisible() await expect(page.locator('[data-article-qr-download]')).toBeVisible() await page.locator('[data-article-wechat-qr-close]').first().click() await expect(page.locator('[data-article-wechat-qr-modal]')).toHaveAttribute('aria-hidden', 'true') await page.goto('/categories/frontend-engineering') await expect(page.getByRole('button', { name: '复制摘要' })).toBeVisible() await page.goto('/tags/playwright') await expect(page.getByRole('button', { name: '分享摘要' })).toBeVisible() await page.goto('/reviews/1') await expect(page.getByRole('button', { name: '复制摘要' })).toBeVisible() })