Skip to main content
Ask AI

E2E Testing (Browser)

End-to-end browser testing with TestRelic captures comprehensive analytics about page navigation, network activity, and user interactions. The SDK automatically tracks navigation timelines and network statistics.

What does E2E mode track?

E2E tests use the page fixture from TestRelic to enable automatic tracking of:

  • Navigation Timeline — Page load timing, DOM content loaded, network idle detection
  • Network Statistics — Request counts, byte transfers, response times per navigation
  • Navigation Types — goto, link clicks, back/forward, SPA route changes, hash changes

How do I set up E2E testing with TestRelic?

How do I set up E2E testing using an AI assistant?

Copy one of the prompts below and paste it into your AI coding assistant.


Full setup (one prompt, does everything)

AI Prompt — E2E full setup
Set up @testrelic/playwright-analytics for E2E browser testing in this project:

1. Run: npm install @testrelic/playwright-analytics
2. Install the browser: npx playwright install chromium
3. Open playwright.config.ts and add the TestRelic reporter to the reporter array:
['@testrelic/playwright-analytics', {
outputPath: './test-results/analytics-timeline.json',
includeStackTrace: true,
includeCodeSnippets: true,
includeNetworkStats: true,
}]
4. In all test files that currently import from '@playwright/test', change the import
to '@testrelic/playwright-analytics/fixture' so navigation is tracked automatically.

Keep the existing 'list' reporter if it is already there. Do not change any test logic.

Step-by-step prompts (one at a time)

Step 1 — Install the packages:

AI Prompt — Step 1: Install
Run the following in my project terminal:
npm install @testrelic/playwright-analytics
npx playwright install chromium

Step 2 — Configure the reporter:

AI Prompt — Step 2: Configure reporter
Open playwright.config.ts and add @testrelic/playwright-analytics to the reporter array.
Use this configuration:

['@testrelic/playwright-analytics', {
outputPath: './test-results/analytics-timeline.json',
includeStackTrace: true,
includeCodeSnippets: true,
includeNetworkStats: true,
}]

Keep any existing reporters (like 'list'). Show me the updated file.

Step 3 — Switch the test fixture:

AI Prompt — Step 3: Switch fixture
In my test files, replace:
import { test, expect } from '@playwright/test';
with:
import { test, expect } from '@testrelic/playwright-analytics/fixture';

This enables automatic navigation tracking. Do not change any test logic.

Step 4 — Run the tests:

AI Prompt — Step 4: Run tests
Run my Playwright tests with:
npx playwright test

Then tell me where the analytics report was written.

How do I write E2E tests with TestRelic?

What does a basic test look like?

tests/homepage.spec.ts
import { test, expect } from '@testrelic/playwright-analytics/fixture';

test('homepage loads successfully', { tag: ['@e2e'] }, async ({ page }) => {
// Navigate to homepage
await page.goto('https://example.com');

// Verify page loaded
await expect(page).toHaveTitle(/Example Domain/);
await expect(page.locator('h1')).toBeVisible();
});
Test Tags

Use the { tag: ['@e2e'] } syntax to categorize your tests. This helps filter and organize test runs.

How does navigation tracking work?

TestRelic automatically detects and tracks different types of navigation:

tests/navigation.spec.ts
import { test, expect } from '@testrelic/playwright-analytics/fixture';

test.describe('Navigation Tracking', () => {
test('tracks initial page load', async ({ page }) => {
// Initial navigation - tracked as "navigate"
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example/);
});

test('tracks link clicks', async ({ page }) => {
await page.goto('https://example.com');

// Click navigation - tracked as "click"
await page.click('a[href="/about"]');
await expect(page).toHaveURL(/about/);
});

test('tracks form submissions', async ({ page }) => {
await page.goto('https://example.com/search');

// Form submission - tracked as "submit"
await page.fill('input[name="query"]', 'test');
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/query=test/);
});

test('tracks browser navigation', async ({ page }) => {
await page.goto('https://example.com');
await page.click('a[href="/about"]');

// Back button - tracked as "back"
await page.goBack();
await expect(page).toHaveURL('https://example.com');

// Forward button - tracked as "forward"
await page.goForward();
await expect(page).toHaveURL(/about/);
});
});

How do I track multi-page user flows?

tests/user-journey.spec.ts
import { test, expect } from '@testrelic/playwright-analytics/fixture';

test('complete user journey', { tag: ['@e2e', '@flow'] }, async ({ page }) => {
// Step 1: Homepage
await page.goto('https://example.com');
await expect(page.locator('h1')).toContainText('Welcome');

// Step 2: Navigate to products
await page.click('a[href="/products"]');
await expect(page).toHaveURL(/products/);

// Step 3: Search for product
await page.fill('input[name="search"]', 'laptop');
await page.click('button[type="submit"]');
await expect(page.locator('.product-item')).toHaveCount(10);

// Step 4: View product details
await page.click('.product-item:first-child');
await expect(page.locator('.product-title')).toBeVisible();

// Step 5: Add to cart
await page.click('button:has-text("Add to Cart")');
await expect(page.locator('.cart-badge')).toContainText('1');
});

What do real-world E2E examples look like?

How do I test Wikipedia search and navigation?

examples/wikipedia/tests/wikipedia.spec.ts
import { test, expect } from '@testrelic/playwright-analytics/fixture';

test.describe('Wikipedia', () => {
test('homepage loads', { tag: ['@e2e', '@wikipedia'] }, async ({ page }) => {
await page.goto('https://en.wikipedia.org');
await expect(page).toHaveTitle(/Wikipedia/);
await expect(page.locator('#searchInput')).toBeVisible();
});

test('search and navigate', { tag: ['@e2e', '@wikipedia'] }, async ({ page }) => {
await page.goto('https://en.wikipedia.org');

// Search for JavaScript
await page.fill('#searchInput', 'JavaScript');
await page.click('button[type="submit"]');

// Verify article loaded
await expect(page).toHaveURL(/JavaScript/);
await expect(page.locator('#firstHeading')).toContainText('JavaScript');

// Click on a related link
await page.click('a[href="/wiki/ECMAScript"]');
await expect(page).toHaveURL(/ECMAScript/);
});

test('tracks media-heavy pages', { tag: ['@e2e', '@wikipedia'] }, async ({ page }) => {
// Navigate to an article with many images
await page.goto('https://en.wikipedia.org/wiki/Solar_System');

// Wait for images to load
await page.waitForLoadState('networkidle');

// Verify content loaded
await expect(page.locator('.mw-parser-output')).toBeVisible();
});
});

How do I test an e-commerce site?

examples/flipkart/tests/ecommerce.spec.ts
import { test, expect } from '@testrelic/playwright-analytics/fixture';

test.describe('Flipkart E-commerce', () => {
test('homepage loads', { tag: ['@e2e', '@ecommerce'] }, async ({ page }) => {
await page.goto('https://www.flipkart.com');

// Close login popup if present
await page.click('button:has-text("✕")').catch(() => {});

await expect(page.locator('._1XjE3T')).toBeVisible();
});

test('product search', { tag: ['@e2e', '@ecommerce'] }, async ({ page }) => {
await page.goto('https://www.flipkart.com');
await page.click('button:has-text("✕")').catch(() => {});

// Search for laptops
await page.fill('input[name="q"]', 'laptop');
await page.press('input[name="q"]', 'Enter');

// Wait for results
await page.waitForSelector('._1AtVbE');
await expect(page.locator('._1AtVbE')).toHaveCountGreaterThan(0);
});

test('product page navigation', { tag: ['@e2e', '@ecommerce'] }, async ({ page }) => {
await page.goto('https://www.flipkart.com');
await page.click('button:has-text("✕")').catch(() => {});

// Navigate to category
await page.click('text=Electronics');
await expect(page).toHaveURL(/electronics/);

// Browse products
await page.waitForSelector('._1AtVbE');

// Click on first product
const firstProduct = page.locator('._1AtVbE').first();
await firstProduct.click();

// Verify product page
await expect(page.locator('.B_NuCI')).toBeVisible();
});
});
examples/google/tests/search.spec.ts
import { test, expect } from '@testrelic/playwright-analytics/fixture';

test.describe('Google Search', () => {
test('homepage loads', { tag: ['@e2e', '@search'] }, async ({ page }) => {
await page.goto('https://www.google.com');
await expect(page.locator('input[name="q"]')).toBeVisible();
});

test('search query', { tag: ['@e2e', '@search'] }, async ({ page }) => {
await page.goto('https://www.google.com');

// Perform search
await page.fill('input[name="q"]', 'Playwright testing');
await page.press('input[name="q"]', 'Enter');

// Wait for results
await page.waitForSelector('#search');
await expect(page.locator('#search')).toBeVisible();
});

test('results navigation', { tag: ['@e2e', '@search'] }, async ({ page }) => {
await page.goto('https://www.google.com');

await page.fill('input[name="q"]', 'Playwright');
await page.press('input[name="q"]', 'Enter');

// Wait for results
await page.waitForSelector('#search');

// Click on first result
const firstResult = page.locator('#search a').first();
await firstResult.click();

// Verify navigation
await expect(page).not.toHaveURL(/google\.com/);
});
});

What network statistics does TestRelic capture?

TestRelic automatically captures network statistics for each navigation:

tests/network-stats.spec.ts
import { test, expect } from '@testrelic/playwright-analytics/fixture';

test('page with network stats', async ({ page }) => {
// Navigate to a page
await page.goto('https://example.com');

// Wait for network idle
await page.waitForLoadState('networkidle');

// The report will include:
// - Number of requests (images, scripts, stylesheets, etc.)
// - Total bytes transferred
// - Response times for each resource
// - Failed requests and status codes

await expect(page.locator('h1')).toBeVisible();
});

The generated report contains network statistics per timeline entry:

{
"networkStats": {
"totalRequests": 42,
"failedRequests": 0,
"totalBytes": 2458672,
"byType": {
"document": 1,
"script": 9,
"stylesheet": 2,
"image": 27,
"font": 2,
"xhr": 0,
"other": 1
}
}
}

What performance metrics does TestRelic track?

TestRelic tracks key performance metrics:

  • First Contentful Paint (FCP) — When first content appears
  • DOM Content Loaded — When HTML is parsed
  • Load Complete — When all resources are loaded
  • Network Idle — When network activity settles
tests/performance.spec.ts
import { test, expect } from '@testrelic/playwright-analytics/fixture';

test('performance tracking', async ({ page }) => {
const startTime = Date.now();

await page.goto('https://example.com');
await page.waitForLoadState('domcontentloaded');

const domLoadTime = Date.now() - startTime;
console.log(`DOM loaded in ${domLoadTime}ms`);

await page.waitForLoadState('load');
const fullLoadTime = Date.now() - startTime;
console.log(`Page fully loaded in ${fullLoadTime}ms`);

// All timing data is captured in the TestRelic report
});

What are the E2E-specific configuration options?

playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
reporter: [
['@testrelic/playwright-analytics', {
outputPath: './test-results/analytics-timeline.json',
includeStackTrace: true,
includeCodeSnippets: true,
includeNetworkStats: true,
navigationTypes: ['goto', 'link_click', 'back', 'forward', 'spa_route', 'hash_change'],
}],
],
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure',
},
});

How do I run E2E tests?

How do I run all E2E tests?

npx playwright test --grep @e2e

How do I run a specific example?

cd examples/wikipedia
npx playwright test

How do I debug a failing test?

npx playwright test --debug

How do I run in headed mode to watch the browser?

npx playwright test --headed

How do I analyze the E2E report?

After running E2E tests, analyze the generated report:

cat test-results/analytics-timeline.json | jq .

Key metrics to look for:

  • Navigation timeline and sequence
  • Page load times
  • Network request counts
  • Failed requests
  • Performance bottlenecks
Report Visualization

See the Browser Report Documentation for detailed information on report structure and analysis.

What are the best practices for E2E tests?

How do I avoid flaky assertions?

Always wait for critical content before asserting:

await page.goto('https://example.com');
await page.waitForSelector('.main-content');
await expect(page.locator('.main-content')).toBeVisible();

How do I handle dynamic content?

For dynamic content, wait for network idle:

await page.goto('https://example.com');
await page.waitForLoadState('networkidle');

How do I handle popups that block tests?

Close popups that may interfere with tests:

await page.goto('https://example.com');
await page.click('button.close-popup').catch(() => {});

How do I organize tests with tags?

test('homepage loads', { tag: ['@e2e', '@smoke', '@critical'] }, async ({ page }) => {
// Test code
});

How do I structure complex tests with Page Object Model?

pages/HomePage.ts
export class HomePage {
constructor(private page: Page) {}

async goto() {
await this.page.goto('https://example.com');
}

async search(query: string) {
await this.page.fill('input[name="search"]', query);
await this.page.click('button[type="submit"]');
}
}

// In your test:
test('search functionality', async ({ page }) => {
const homePage = new HomePage(page);
await homePage.goto();
await homePage.search('test query');
});

How do I troubleshoot common E2E issues?

Why is my test timing out?

Increase the timeout for slow pages:

test('slow page', async ({ page }) => {
test.setTimeout(60000); // 60 seconds
await page.goto('https://slow-site.com');
});

Why is my test flaky?

Use retries for flaky tests:

playwright.config.ts
export default defineConfig({
retries: 2,
});

How do I handle network errors gracefully?

await page.goto('https://example.com').catch((error) => {
console.error('Navigation failed:', error);
throw error;
});

Where do I go next?

Additional Resources

Was this doc helpful?
Last updated on by Srivishnu Ayyagari