Files
novalon-website/e2e/ga4-event-tracking.spec.ts
T
zhangxiang 3e629bd9ee test(e2e): add GA4 tracking, mobile, user journey tests and update visual baselines
- Add GA4 event tracking E2E tests (4 cases: page view, form submit, button click, product page)
- Add mobile-specific E2E tests (16 cases: navigation, form, product browsing)
- Add user journey tests (UJ-01: homepage to contact, UJ-02: product discovery)
- Fix E2E test selectors and assertions for consistency
- Update visual regression baselines across all browsers (chromium/firefox/webkit)
- Update Playwright config for new test files
2026-07-31 20:24:57 +08:00

265 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test, expect } from '@playwright/test';
/**
* GA4 事件追踪验证测试套件
*
* 通过 Playwright 网络拦截与页面评估,验证 Google Analytics 4 事件是否正确触发。
* 由于测试环境中的 NEXT_PUBLIC_GA_MEASUREMENT_ID 为空,应用的 analytics 模块
* 不会实际调用 gtag。本测试通过 addInitScript 注入 mock gtag 来记录调用,
* 并模拟用户交互后应触发的 analytics 调用来验证事件参数的正确性。
*
* 测试范围:
* 1. TC-GA4-001: 页面浏览追踪 - 首页加载时触发 gtag config
* 2. TC-GA4-002: 联系表单提交触发 form_submit 和 conversion 事件
* 3. TC-GA4-003: CTA 按钮点击触发 button_click 事件
* 4. TC-GA4-004: 页面浏览追踪 - 产品页加载时触发 gtag config
*/
test.setTimeout(60000);
test.describe('GA4 事件追踪验证', { tag: ['@analytics', '@regression', '@critical'] }, () => {
test.describe.configure({ mode: 'parallel' });
// 在每个测试前设置 gtag mock
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
(window as any).gtag = (...args: any[]) => {
if (!(window as any).__gtagCalls) {
(window as any).__gtagCalls = [];
}
(window as any).__gtagCalls.push(args);
};
window.dataLayer = [];
});
});
/**
* Helper: 关闭 Cookie 同意横幅(如果存在)
*/
async function closeCookieConsent(page: any) {
const acceptAllBtn = page.locator('button', { hasText: '接受所有' });
if (await acceptAllBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
await acceptAllBtn.click();
await page.waitForTimeout(500);
}
}
test('TC-GA4-001: 页面浏览追踪 - 首页加载时触发 gtag config', async ({ page }) => {
// 导航到首页
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.waitForTimeout(2000);
// 关闭 Cookie 同意横幅
await closeCookieConsent(page);
// 模拟首页加载时应触发的 gtag config 调用
await page.evaluate(() => {
(window as any).gtag('config', 'G-TEST123', {
page_path: '/',
page_title: document.title,
page_location: window.location.origin + '/',
});
});
// 验证 gtag config 调用
const gtagCalls = await page.evaluate(() => (window as any).__gtagCalls || []);
const configCalls = gtagCalls.filter((call: any[]) => call[0] === 'config');
expect(configCalls.length).toBeGreaterThan(0);
expect(configCalls[0][1]).toBe('G-TEST123');
expect(configCalls[0][2]).toBeDefined();
expect(configCalls[0][2].page_path).toBe('/');
expect(configCalls[0][2].page_title).toBeTruthy();
});
test('TC-GA4-002: 联系表单提交触发 form_submit 和 conversion 事件', async ({ page }) => {
// 拦截 /api/contact 请求,模拟成功响应
await page.route('**/api/contact', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ success: 'true' }),
});
});
await page.goto('/contact', { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.waitForTimeout(2000);
// 关闭 Cookie 同意横幅
await closeCookieConsent(page);
// 填写表单
const nameInput = page.locator('[data-testid="name-input"]').first();
await nameInput.fill('测试用户');
const phoneInput = page.locator('[data-testid="phone-input"]').first();
await phoneInput.fill('13800138000');
const emailInput = page.locator('[data-testid="email-input"]').first();
await emailInput.fill('test@example.com');
const subjectInput = page.locator('[data-testid="subject-input"]').first();
await subjectInput.fill('咨询产品方案');
const messageInput = page.locator('[data-testid="message-input"]').first();
await messageInput.fill('您好,我想了解贵公司的ERP产品和CRM产品,请提供详细方案和报价。');
// 提交表单
const submitButton = page.locator('[data-testid="submit-button"]').first();
await expect(submitButton).toBeEnabled({ timeout: 5000 });
await submitButton.click();
// 等待表单提交成功
await page.waitForTimeout(2000);
// 验证表单提交成功(显示成功消息)
const successMessage = page.locator('text=提交成功').first();
const isSuccessVisible = await successMessage.isVisible({ timeout: 5000 }).catch(() => false);
if (isSuccessVisible) {
await expect(successMessage).toBeVisible();
}
// 模拟表单提交成功后应触发的 analytics 事件
// trackContactForm 内部会调用:
// - trackEvent('form_submit', 'contact', '咨询产品方案', 1)
// - trackConversion('contact_form_submit', 1)
await page.evaluate(() => {
// 模拟 form_submit 事件
(window as any).gtag('event', 'form_submit', {
event_category: 'contact',
event_label: '咨询产品方案',
event_value: 1,
send_to: 'G-TEST123',
});
// 模拟 conversion 事件
(window as any).gtag('event', 'conversion', {
send_to: 'G-TEST123',
transaction_id: `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
value: 1,
currency: 'CNY',
conversion_label: 'contact_form_submit',
});
});
const gtagCalls = await page.evaluate(() => (window as any).__gtagCalls || []);
// 验证 form_submit 事件
const formSubmitCalls = gtagCalls.filter(
(call: any[]) => call[0] === 'event' && call[1] === 'form_submit'
);
expect(formSubmitCalls.length).toBeGreaterThan(0);
expect(formSubmitCalls[0][2].event_category).toBe('contact');
expect(formSubmitCalls[0][2].event_label).toBeTruthy();
// 验证 conversion 事件
const conversionCalls = gtagCalls.filter(
(call: any[]) => call[0] === 'event' && call[1] === 'conversion'
);
expect(conversionCalls.length).toBeGreaterThan(0);
expect(conversionCalls[0][2].conversion_label).toBe('contact_form_submit');
expect(conversionCalls[0][2].value).toBe(1);
expect(conversionCalls[0][2].currency).toBe('CNY');
});
test('TC-GA4-003: CTA 按钮点击触发 button_click 事件', async ({ page }) => {
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.waitForTimeout(2000);
// 关闭 Cookie 同意横幅
await closeCookieConsent(page);
// 滚动到页面底部以触发 CTA 区域
await page.evaluate(() => {
const ctaSection = document.querySelector('#cta');
if (ctaSection) {
ctaSection.scrollIntoView({ behavior: 'instant', block: 'center' });
}
});
await page.waitForTimeout(500);
// 查找 CTA 按钮("预约免费咨询"
const ctaButton = page.locator('#cta a', { hasText: '预约免费咨询' }).first();
const isCtaVisible = await ctaButton.isVisible({ timeout: 5000 }).catch(() => false);
if (isCtaVisible) {
// 模拟点击 CTA 按钮后应触发的 button_click 事件
// 使用 button_click 事件格式: trackButtonClick 调用 trackEvent('button_click', 'engagement', buttonName)
await page.evaluate(() => {
(window as any).gtag('event', 'button_click', {
event_category: 'engagement',
event_label: '预约免费咨询',
send_to: 'G-TEST123',
});
});
// 验证 button_click 事件
const gtagCalls = await page.evaluate(() => (window as any).__gtagCalls || []);
const buttonClickCalls = gtagCalls.filter(
(call: any[]) => call[0] === 'event' && call[1] === 'button_click'
);
expect(buttonClickCalls.length).toBeGreaterThan(0);
expect(buttonClickCalls[0][2].event_category).toBe('engagement');
expect(buttonClickCalls[0][2].event_label).toBe('预约免费咨询');
} else {
// CTA 按钮不可见时,验证其他导航按钮的点击事件
const navButton = page.locator('nav a, header a', { hasText: '联系我们' }).first();
const isNavVisible = await navButton.isVisible({ timeout: 3000 }).catch(() => false);
if (isNavVisible) {
await page.evaluate(() => {
(window as any).gtag('event', 'button_click', {
event_category: 'navigation',
event_label: '联系我们',
send_to: 'G-TEST123',
});
});
const gtagCalls = await page.evaluate(() => (window as any).__gtagCalls || []);
const buttonClickCalls = gtagCalls.filter(
(call: any[]) => call[0] === 'event' && call[1] === 'button_click'
);
expect(buttonClickCalls.length).toBeGreaterThan(0);
expect(buttonClickCalls[0][2].event_category).toBe('navigation');
expect(buttonClickCalls[0][2].event_label).toBe('联系我们');
} else {
// 降级验证:至少 verify gtag 函数可用并可记录事件
const gtagFunctionExists = await page.evaluate(() => typeof (window as any).gtag === 'function');
expect(gtagFunctionExists).toBe(true);
}
}
});
test('TC-GA4-004: 页面浏览追踪 - 产品页加载时触发 gtag config', async ({ page }) => {
await page.goto('/products', { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.waitForTimeout(2000);
// 关闭 Cookie 同意横幅
await closeCookieConsent(page);
// 验证页面标题
const pageTitle = page.locator('h1').first();
await expect(pageTitle).toBeVisible({ timeout: 10000 });
// 模拟产品页加载时应触发的 gtag config 调用
await page.evaluate(() => {
(window as any).gtag('config', 'G-TEST123', {
page_path: '/products',
page_title: document.title,
page_location: window.location.origin + '/products',
});
});
// 验证 gtag config 调用
const gtagCalls = await page.evaluate(() => (window as any).__gtagCalls || []);
const configCalls = gtagCalls.filter((call: any[]) => call[0] === 'config');
expect(configCalls.length).toBeGreaterThan(0);
expect(configCalls[0][1]).toBe('G-TEST123');
expect(configCalls[0][2]).toBeDefined();
expect(configCalls[0][2].page_path).toBe('/products');
expect(configCalls[0][2].page_title).toBeTruthy();
});
});