diff --git a/e2e/journeys/visitor-browse-journey.spec.ts b/e2e/journeys/visitor-browse-journey.spec.ts index 1621d27..0a72c38 100644 --- a/e2e/journeys/visitor-browse-journey.spec.ts +++ b/e2e/journeys/visitor-browse-journey.spec.ts @@ -1,95 +1,91 @@ import { test, expect } from '@playwright/test'; +import { + FrontendHomePage, + FrontendNewsPage, + FrontendProductPage, + FrontendContactPage +} from '../pages/frontend'; +import { TestDataFactory } from '../fixtures/test-data-factory'; test.describe('访客浏览旅程 @journey @visitor', () => { - test('访客浏览首页并了解公司信息', async ({ page }) => { + let homePage: FrontendHomePage; + let newsPage: FrontendNewsPage; + let productPage: FrontendProductPage; + let contactPage: FrontendContactPage; + + test.beforeEach(async ({ page }) => { + homePage = new FrontendHomePage(page); + newsPage = new FrontendNewsPage(page); + productPage = new FrontendProductPage(page); + contactPage = new FrontendContactPage(page); + }); + + test('访客浏览首页并了解公司信息', async () => { await test.step('步骤1: 访问首页', async () => { - await page.goto('/'); - await expect(page).toHaveTitle(/四川睿新致远科技有限公司/); + await homePage.goto(); + await expect(homePage.page).toHaveTitle(/四川睿新致远科技有限公司/); }); await test.step('步骤2: 查看Hero区域', async () => { - await expect(page.locator('h1')).toBeVisible(); - await expect(page.locator('text=专业')).toBeVisible(); + await homePage.expectHeroVisible(); }); await test.step('步骤3: 滚动查看服务介绍', async () => { - await page.locator('#services').scrollIntoViewIfNeeded(); - await expect(page.locator('#services')).toBeVisible(); + await homePage.scrollToSection('services'); }); await test.step('步骤4: 查看产品展示', async () => { - await page.locator('#products').scrollIntoViewIfNeeded(); - await expect(page.locator('#products')).toBeVisible(); + await homePage.scrollToSection('products'); }); await test.step('步骤5: 查看最新资讯', async () => { - await page.locator('#news').scrollIntoViewIfNeeded(); - await expect(page.locator('#news')).toBeVisible(); + await homePage.scrollToSection('news'); }); }); - test('访客浏览新闻列表并查看详情', async ({ page }) => { + test('访客浏览新闻列表并查看详情', async () => { await test.step('步骤1: 访问新闻列表页', async () => { - await page.goto('/news'); - await expect(page).toHaveURL(/\/news/); + await newsPage.goto(); }); await test.step('步骤2: 查看新闻列表', async () => { - const newsCards = page.locator('article, [data-testid="news-card"]'); - const count = await newsCards.count(); - expect(count).toBeGreaterThan(0); + await newsPage.expectNewsListVisible(); }); await test.step('步骤3: 点击第一条新闻', async () => { - const firstNews = page.locator('article a, [data-testid="news-card"] a').first(); - if (await firstNews.count() > 0) { - await firstNews.click(); - await page.waitForLoadState('networkidle'); - await expect(page.locator('h1')).toBeVisible(); - } + await newsPage.clickFirstNews(); + await newsPage.expectNewsDetailVisible(); }); }); - test('访客浏览产品并了解详情', async ({ page }) => { + test('访客浏览产品并了解详情', async () => { await test.step('步骤1: 访问产品列表页', async () => { - await page.goto('/products'); - await expect(page).toHaveURL(/\/products/); + await productPage.goto(); }); await test.step('步骤2: 查看产品列表', async () => { - const productCards = page.locator('article, [data-testid="product-card"]'); - const count = await productCards.count(); - expect(count).toBeGreaterThan(0); + await productPage.expectProductListVisible(); }); await test.step('步骤3: 点击第一个产品', async () => { - const firstProduct = page.locator('article a, [data-testid="product-card"] a').first(); - if (await firstProduct.count() > 0) { - await firstProduct.click(); - await page.waitForLoadState('networkidle'); - await expect(page.locator('h1')).toBeVisible(); - } + await productPage.clickFirstProduct(); + await productPage.expectProductDetailVisible(); }); }); - test('访客查看联系信息并提交表单', async ({ page }) => { + test('访客查看联系信息并提交表单', async () => { + const contactData = TestDataFactory.createContactForm(); + await test.step('步骤1: 访问联系页面', async () => { - await page.goto('/contact'); - await expect(page).toHaveURL(/\/contact/); + await contactPage.goto(); }); await test.step('步骤2: 查看联系信息', async () => { - await expect(page.locator('text=电话')).toBeVisible(); - await expect(page.locator('text=邮箱')).toBeVisible(); + await contactPage.expectContactInfoVisible(); }); await test.step('步骤3: 填写联系表单', async () => { - const form = page.locator('form'); - if (await form.count() > 0) { - await page.fill('input[name="name"]', '测试用户'); - await page.fill('input[name="email"]', 'test@example.com'); - await page.fill('textarea[name="message"]', '这是一条测试留言'); - } + await contactPage.fillForm(contactData); }); }); }); diff --git a/e2e/pages/FrontendNewsPage.ts b/e2e/pages/FrontendNewsPage.ts index c55c4fc..5632b5c 100644 --- a/e2e/pages/FrontendNewsPage.ts +++ b/e2e/pages/FrontendNewsPage.ts @@ -1,29 +1,53 @@ import { Page, expect } from '@playwright/test'; export class FrontendNewsPage { - constructor(private page: Page) {} + readonly page: Page; + + constructor(page: Page) { + this.page = page; + } async goto() { await this.page.goto('/news'); - await this.page.waitForLoadState('networkidle'); + await this.page.waitForLoadState('domcontentloaded'); + } + + async expectNewsListVisible() { + const newsCards = this.page.locator('article, [data-testid="news-card"]'); + await expect(newsCards.first()).toBeVisible({ timeout: 10000 }); + const count = await newsCards.count(); + expect(count).toBeGreaterThan(0); + } + + async clickFirstNews() { + const firstNews = this.page.locator('article a, [data-testid="news-card"] a').first(); + if (await firstNews.count() > 0) { + await firstNews.click(); + await this.page.waitForLoadState('domcontentloaded'); + } + } + + async expectNewsDetailVisible(expectedContent?: string) { + await expect(this.page.locator('h1')).toBeVisible(); + if (expectedContent) { + await expect(this.page.locator(`text=${expectedContent}`)).toBeVisible(); + } } async expectNewsVisible(title: string) { - const newsCard = this.page.locator(`text="${title}"`); + await this.goto(); + const newsCard = this.page.locator(`article:has-text("${title}"), [data-testid="news-card"]:has-text("${title}")`); await expect(newsCard).toBeVisible(); } async expectNewsNotVisible(title: string) { - const newsCard = this.page.locator(`text="${title}"`); + await this.goto(); + const newsCard = this.page.locator(`article:has-text("${title}"), [data-testid="news-card"]:has-text("${title}")`); await expect(newsCard).not.toBeVisible(); } async clickNews(title: string) { await this.page.locator(`text="${title}"`).click(); - await this.page.waitForLoadState('networkidle'); - } - - async expectNewsDetailVisible(content: string) { - await expect(this.page.locator(`text=${content}`)).toBeVisible(); + await this.page.waitForLoadState('domcontentloaded'); } } diff --git a/e2e/pages/FrontendProductPage.ts b/e2e/pages/FrontendProductPage.ts index eebf66c..16d74c2 100644 --- a/e2e/pages/FrontendProductPage.ts +++ b/e2e/pages/FrontendProductPage.ts @@ -1,20 +1,55 @@ import { Page, expect } from '@playwright/test'; export class FrontendProductPage { - constructor(private page: Page) {} + readonly page: Page; + + constructor(page: Page) { + this.page = page; + } async goto() { await this.page.goto('/products'); - await this.page.waitForLoadState('networkidle'); + await this.page.waitForLoadState('domcontentloaded'); + } + + async expectProductListVisible() { + const productCards = this.page.locator('article, [data-testid="product-card"]'); + await expect(productCards.first()).toBeVisible({ timeout: 10000 }); + const count = await productCards.count(); + expect(count).toBeGreaterThan(0); + } + + async clickFirstProduct() { + const firstProduct = this.page.locator('article a, [data-testid="product-card"] a').first(); + if (await firstProduct.count() > 0) { + await firstProduct.click(); + await this.page.waitForLoadState('domcontentloaded'); + } + } + + async expectProductDetailVisible() { + await expect(this.page.locator('h1')).toBeVisible(); + } + + async expectProductDetailsVisible() { + await expect(this.page.locator('h1')).toBeVisible(); + await expect(this.page.locator('article, .product-details')).toBeVisible(); } async expectProductVisible(title: string) { - const productCard = this.page.locator(`text="${title}"`); + await this.goto(); + const productCard = this.page.locator(`article:has-text("${title}"), [data-testid="product-card"]:has-text("${title}")`); await expect(productCard).toBeVisible(); } + async expectProductNotVisible(title: string) { + await this.goto(); + const productCard = this.page.locator(`article:has-text("${title}"), [data-testid="product-card"]:has-text("${title}")`); + await expect(productCard).not.toBeVisible(); + } + async clickProduct(title: string) { await this.page.locator(`text="${title}"`).click(); - await this.page.waitForLoadState('networkidle'); + await this.page.waitForLoadState('domcontentloaded'); } }