diff --git a/e2e/src/tests/visual/visual-regression.spec.ts b/e2e/src/tests/visual/visual-regression.spec.ts new file mode 100644 index 0000000..c5104ab --- /dev/null +++ b/e2e/src/tests/visual/visual-regression.spec.ts @@ -0,0 +1,419 @@ +import { test, expect } from '@playwright/test'; +import { HomePage } from '../../pages/HomePage'; +import { ContactPage } from '../../pages/ContactPage'; + +test.describe('视觉回归测试', () => { + test.describe('首页视觉测试', () => { + let homePage: HomePage; + + test.beforeEach(async ({ page }) => { + homePage = new HomePage(page); + await homePage.goto(); + }); + + test('首页完整页面截图', async () => { + await expect(homePage.page).toHaveScreenshot('homepage-full.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('首页头部截图', async () => { + await expect(homePage.header).toHaveScreenshot('homepage-header.png', { + animations: 'disabled', + }); + }); + + test('首页Hero区域截图', async () => { + await expect(homePage.heroSection).toHaveScreenshot('homepage-hero.png', { + animations: 'disabled', + }); + }); + + test('首页导航截图', async () => { + await expect(homePage.navigation).toHaveScreenshot('homepage-navigation.png', { + animations: 'disabled', + }); + }); + + test('首页页脚截图', async () => { + await expect(homePage.footer).toHaveScreenshot('homepage-footer.png', { + animations: 'disabled', + }); + }); + + test('首页服务区域截图', async () => { + await homePage.scrollToSection('services'); + await homePage.waitForTimeout(500); + + const servicesSection = homePage.page.locator('#services'); + await expect(servicesSection).toHaveScreenshot('homepage-services.png', { + animations: 'disabled', + }); + }); + + test('首页产品区域截图', async () => { + await homePage.scrollToSection('products'); + await homePage.waitForTimeout(500); + + const productsSection = homePage.page.locator('#products'); + await expect(productsSection).toHaveScreenshot('homepage-products.png', { + animations: 'disabled', + }); + }); + + test('首页案例区域截图', async () => { + await homePage.scrollToSection('cases'); + await homePage.waitForTimeout(500); + + const casesSection = homePage.page.locator('#cases'); + await expect(casesSection).toHaveScreenshot('homepage-cases.png', { + animations: 'disabled', + }); + }); + + test('首页新闻区域截图', async () => { + await homePage.scrollToSection('news'); + await homePage.waitForTimeout(500); + + const newsSection = homePage.page.locator('#news'); + await expect(newsSection).toHaveScreenshot('homepage-news.png', { + animations: 'disabled', + }); + }); + + test('首页联系区域截图', async () => { + await homePage.scrollToSection('contact'); + await homePage.waitForTimeout(500); + + const contactSection = homePage.page.locator('#contact'); + await expect(contactSection).toHaveScreenshot('homepage-contact.png', { + animations: 'disabled', + }); + }); + }); + + test.describe('联系页面视觉测试', () => { + let contactPage: ContactPage; + + test.beforeEach(async ({ page }) => { + contactPage = new ContactPage(page); + await contactPage.goto(); + }); + + test('联系页面完整页面截图', async () => { + await expect(contactPage.page).toHaveScreenshot('contact-page-full.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('联系页面表单截图', async () => { + await expect(contactPage.contactForm).toHaveScreenshot('contact-form.png', { + animations: 'disabled', + }); + }); + + test('联系页面表单填写后截图', async () => { + await contactPage.fillContactForm({ + name: '张三', + email: 'zhangsan@example.com', + phone: '13800138000', + subject: '产品咨询', + message: '您好,我对贵公司的产品很感兴趣。', + }); + + await expect(contactPage.contactForm).toHaveScreenshot('contact-form-filled.png', { + animations: 'disabled', + }); + }); + + test('联系页面表单错误状态截图', async () => { + await contactPage.fillContactForm({ + name: '', + email: 'invalid-email', + phone: '123', + message: '', + }); + await contactPage.submitForm(); + await contactPage.waitForTimeout(1000); + + await expect(contactPage.contactForm).toHaveScreenshot('contact-form-errors.png', { + animations: 'disabled', + }); + }); + }); + + test.describe('响应式视觉测试', () => { + test('移动端首页截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.page.setViewportSize({ width: 375, height: 667 }); + await homePage.goto(); + + await expect(homePage.page).toHaveScreenshot('homepage-mobile.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('移动端联系页面截图', async ({ page }) => { + const contactPage = new ContactPage(page); + await contactPage.page.setViewportSize({ width: 375, height: 667 }); + await contactPage.goto(); + + await expect(contactPage.page).toHaveScreenshot('contact-page-mobile.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('平板端首页截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.page.setViewportSize({ width: 768, height: 1024 }); + await homePage.goto(); + + await expect(homePage.page).toHaveScreenshot('homepage-tablet.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('平板端联系页面截图', async ({ page }) => { + const contactPage = new ContactPage(page); + await contactPage.page.setViewportSize({ width: 768, height: 1024 }); + await contactPage.goto(); + + await expect(contactPage.page).toHaveScreenshot('contact-page-tablet.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('桌面端首页截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.page.setViewportSize({ width: 1280, height: 720 }); + await homePage.goto(); + + await expect(homePage.page).toHaveScreenshot('homepage-desktop.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('桌面端联系页面截图', async ({ page }) => { + const contactPage = new ContactPage(page); + await contactPage.page.setViewportSize({ width: 1280, height: 720 }); + await contactPage.goto(); + + await expect(contactPage.page).toHaveScreenshot('contact-page-desktop.png', { + fullPage: true, + animations: 'disabled', + }); + }); + }); + + test.describe('交互状态视觉测试', () => { + test('链接hover状态截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.goto(); + + const firstLink = homePage.page.locator('nav a').first(); + await firstLink.hover(); + + await expect(homePage.navigation).toHaveScreenshot('navigation-hover.png', { + animations: 'disabled', + }); + }); + + test('按钮hover状态截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.goto(); + + const contactButton = homePage.page.locator('a:has-text("立即咨询")'); + await contactButton.hover(); + + await expect(contactButton).toHaveScreenshot('button-hover.png', { + animations: 'disabled', + }); + }); + + test('按钮focus状态截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.goto(); + + const contactButton = homePage.page.locator('a:has-text("立即咨询")'); + await contactButton.focus(); + + await expect(contactButton).toHaveScreenshot('button-focus.png', { + animations: 'disabled', + }); + }); + + test('输入框focus状态截图', async ({ page }) => { + const contactPage = new ContactPage(page); + await contactPage.goto(); + + await contactPage.nameInput.focus(); + + await expect(contactPage.nameInput).toHaveScreenshot('input-focus.png', { + animations: 'disabled', + }); + }); + + test('移动端菜单打开状态截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.page.setViewportSize({ width: 375, height: 667 }); + await homePage.goto(); + + await homePage.openMobileMenu(); + + await expect(homePage.page).toHaveScreenshot('mobile-menu-open.png', { + animations: 'disabled', + }); + }); + }); + + test.describe('滚动状态视觉测试', () => { + test('首页滚动到顶部截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.goto(); + await homePage.scrollToTop(); + + await expect(homePage.page).toHaveScreenshot('homepage-scroll-top.png', { + animations: 'disabled', + }); + }); + + test('首页滚动到中部截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.goto(); + await homePage.scrollToSection('services'); + + await expect(homePage.page).toHaveScreenshot('homepage-scroll-middle.png', { + animations: 'disabled', + }); + }); + + test('首页滚动到底部截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.goto(); + await homePage.scrollToBottom(); + + await expect(homePage.page).toHaveScreenshot('homepage-scroll-bottom.png', { + animations: 'disabled', + }); + }); + }); + + test.describe('表单验证视觉测试', () => { + test('表单验证成功状态截图', async ({ page }) => { + const contactPage = new ContactPage(page); + await contactPage.goto(); + + await contactPage.fillContactForm({ + name: '张三', + email: 'zhangsan@example.com', + phone: '13800138000', + subject: '产品咨询', + message: '您好,我对贵公司的产品很感兴趣。', + }); + await contactPage.submitForm(); + await contactPage.waitForTimeout(2000); + + await expect(contactPage.page).toHaveScreenshot('contact-form-success.png', { + animations: 'disabled', + }); + }); + + test('表单验证失败状态截图', async ({ page }) => { + const contactPage = new ContactPage(page); + await contactPage.goto(); + + await contactPage.fillContactForm({ + name: '', + email: 'invalid-email', + phone: '123', + message: '', + }); + await contactPage.submitForm(); + await contactPage.waitForTimeout(1000); + + await expect(contactPage.contactForm).toHaveScreenshot('contact-form-validation-failed.png', { + animations: 'disabled', + }); + }); + }); + + test.describe('加载状态视觉测试', () => { + test('页面加载前截图', async ({ page }) => { + const homePage = new HomePage(page); + + await homePage.goto(); + await homePage.page.waitForLoadState('domcontentloaded'); + + await expect(homePage.page).toHaveScreenshot('page-loading.png', { + animations: 'disabled', + }); + }); + + test('页面加载完成截图', async ({ page }) => { + const homePage = new HomePage(page); + + await homePage.goto(); + await homePage.waitForPageLoad(); + + await expect(homePage.page).toHaveScreenshot('page-loaded.png', { + fullPage: true, + animations: 'disabled', + }); + }); + }); + + test.describe('错误状态视觉测试', () => { + test('404页面截图', async ({ page }) => { + await page.goto('/non-existent-page'); + await page.waitForLoadState('networkidle'); + + await expect(page).toHaveScreenshot('404-page.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('500错误页面截图', async ({ page }) => { + await page.goto('/error'); + await page.waitForLoadState('networkidle'); + + await expect(page).toHaveScreenshot('500-page.png', { + fullPage: true, + animations: 'disabled', + }); + }); + }); + + test.describe('主题切换视觉测试', () => { + test('亮色主题截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.goto(); + + await expect(homePage.page).toHaveScreenshot('theme-light.png', { + fullPage: true, + animations: 'disabled', + }); + }); + + test('暗色主题截图', async ({ page }) => { + const homePage = new HomePage(page); + await homePage.goto(); + + await homePage.page.evaluate(() => { + document.documentElement.setAttribute('data-theme', 'dark'); + }); + + await expect(homePage.page).toHaveScreenshot('theme-dark.png', { + fullPage: true, + animations: 'disabled', + }); + }); + }); +});