| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /**
- * ================================================================
- * 场景:文章管理全流程 E2E 测试
- * ================================================================
- * 用户故事:
- * - 管理员:创建/发布/编辑/删除/精选文章
- * - 用户:浏览文章列表,查看文章详情,获取每日贴士
- *
- * 流程步骤:
- * 1. 管理员创建文章并发布
- * 2. 管理员管理文章分类
- * 3. 管理员设置精选文章
- * 4. 用户浏览文章列表
- * 5. 用户查看文章详情
- *
- * 关键里程碑:
- * - [Milestone-1] 文章发布成功
- * - [Milestone-2] 文章精选设置成功
- * - [Milestone-3] 用户成功浏览文章
- * ================================================================
- *
- * 运行:npx playwright test tests/e2e/article-management.spec.js
- */
- const { test, expect } = require('@playwright/test');
- test.describe('【场景流程】文章管理全流程', () => {
- // ===== 场景1:管理员创建并发布文章 =====
- test('[场景1] 管理员创建并发布文章 - 期望发布成功', async ({ page }) => {
- // ========== Given:管理员进入文章管理页面 ==========
- await page.goto('/#/pages/admin/article-list');
- await page.waitForLoadState('networkidle');
- // ========== When:创建并发布文章 ==========
- const createBtn = page.locator('.create-btn, .add-article-btn');
- if (await createBtn.isVisible()) {
- await createBtn.click();
- } else {
- await page.goto('/#/pages/admin/article-create');
- await page.waitForLoadState('networkidle');
- }
- await page.waitForSelector('.article-form, .create-form', { timeout: 5000 });
- // 填写标题
- const titleInput = page.locator('input[name="title"], .title-input');
- if (await titleInput.isVisible()) {
- await titleInput.fill('测试文章_' + Date.now());
- }
- // 填写摘要
- const summaryInput = page.locator('textarea[name="summary"], .summary-input');
- if (await summaryInput.isVisible()) {
- await summaryInput.fill('这是文章摘要内容,描述文章的核心要点。');
- }
- // 填写内容
- const contentInput = page.locator('textarea[name="content"], .content-input');
- if (await contentInput.isVisible()) {
- await contentInput.fill('这是文章的正文内容,包含详细的信息和说明。');
- }
- // 选择分类
- const categorySelect = page.locator('.category-picker, select[name="category"]');
- if (await categorySelect.isVisible()) {
- await categorySelect.click();
- await page.waitForSelector('.option-item', { timeout: 3000 });
- await page.locator('.option-item').first().click();
- }
- // 发布文章
- await page.click('.publish-btn, .submit-btn');
- // ========== Then:Milestone-1 - 发布成功 ========
- await page.waitForSelector('.success-tip, .publish-success, .toast-success', { timeout: 10000 });
- const successTip = page.locator('.success-tip, .publish-success');
- expect(await successTip.isVisible()).toBeTruthy();
- });
- // ===== 场景2:管理员管理文章分类 =====
- test('[场景2] 管理员管理文章分类 - 期望分类创建成功', async ({ page }) => {
- // ========== Given:管理员进入分类管理页面 ==========
- await page.goto('/#/pages/admin/category-list');
- await page.waitForLoadState('networkidle');
- // ========== When:创建新分类 ==========
- const addBtn = page.locator('.add-btn, .create-category-btn');
- if (await addBtn.isVisible()) {
- await addBtn.click();
- }
- await page.waitForSelector('.category-form, .create-form', { timeout: 5000 });
- const nameInput = page.locator('input[name="name"], .category-name-input');
- if (await nameInput.isVisible()) {
- await nameInput.fill('测试分类_' + Date.now());
- }
- await page.click('.submit-btn, .save-btn');
- // ========== Then:分类创建成功 ========
- await page.waitForSelector('.success-tip, .create-success', { timeout: 10000 });
- const successTip = page.locator('.success-tip, .create-success');
- expect(await successTip.isVisible()).toBeTruthy();
- });
- // ===== 场景3:管理员设置精选文章 =====
- test('[场景3] 管理员设置精选文章 - 期望精选状态切换成功', async ({ page }) => {
- // ========== Given:管理员进入文章列表 ==========
- await page.goto('/#/pages/admin/article-list');
- await page.waitForLoadState('networkidle');
- // ========== When:设置精选 ==========
- await page.waitForSelector('.article-item', { timeout: 10000 });
- const firstArticle = page.locator('.article-item').first();
- const featuredBtn = firstArticle.locator('.featured-btn, .toggle-featured');
- if (await featuredBtn.isVisible()) {
- await featuredBtn.click();
- }
- // ========== Then:Milestone-2 - 精选设置成功 ========
- await page.waitForTimeout(500);
- // 验证精选标识变化
- const featuredTag = firstArticle.locator('.featured-tag, .is-featured');
- const isFeatured = await featuredTag.isVisible();
- expect(isFeatured).toBeTruthy();
- });
- // ===== 场景4:用户浏览文章列表 =====
- test('[场景4] 用户浏览文章列表 - 期望返回已发布文章', async ({ page }) => {
- // ========== Given:用户进入文章列表页 ==========
- await page.goto('/#/pages/mind/articles');
- await page.waitForLoadState('networkidle');
- // ========== When:浏览文章列表 ==========
- await page.waitForSelector('.article-list, .article-item', { timeout: 10000 });
- // ========== Then:Milestone-3 - 返回文章列表 ========
- const articleItems = page.locator('.article-item, .article-card');
- const count = await articleItems.count();
- expect(count).toBeGreaterThan(0);
- // 验证文章包含标题
- const firstArticle = articleItems.first();
- const title = firstArticle.locator('.article-title, .title');
- if (await title.isVisible()) {
- const titleText = await title.textContent();
- expect(titleText.length).toBeGreaterThan(0);
- }
- });
- // ===== 场景5:用户查看文章详情 =====
- test('[场景5] 用户查看文章详情 - 期望返回完整文章内容', async ({ page }) => {
- // ========== Given:用户进入文章详情页 ==========
- await page.goto('/#/pages/mind/articles');
- await page.waitForLoadState('networkidle');
- // ========== When:点击文章查看详情 ==========
- await page.waitForSelector('.article-item', { timeout: 10000 });
- await page.locator('.article-item').first().click();
- // ========== Then:返回完整文章详情 ========
- await page.waitForSelector('.article-detail, .detail-content, .article-content', { timeout: 10000 });
- const detailContent = page.locator('.article-detail, .detail-content');
- expect(await detailContent.isVisible()).toBeTruthy();
- // 验证包含正文内容
- const articleBody = page.locator('.article-body, .content');
- if (await articleBody.isVisible()) {
- const bodyText = await articleBody.textContent();
- expect(bodyText.length).toBeGreaterThan(0);
- }
- });
- });
|