Browser Test Reports

Browser test reports from TestRelic provide analytics about your E2E tests, including a navigation timeline, network statistics per page visit, test results, and failure diagnostics — all written to a single JSON file.
What does a browser test report contain?
When you run E2E tests with the TestRelic reporter and fixture, a JSON file is generated containing:
- Navigation Timeline — Every URL visited during each test, in chronological order
- Network Statistics — Request counts, bytes transferred, and resource type breakdowns per navigation
- Test Results — Pass/fail/flaky/skipped status, duration, retry count, and tags
- Failure Diagnostics — Error messages, source code snippets pointing to the exact failure line, and optional stack traces
- CI Metadata — Auto-detected provider (GitHub Actions, GitLab CI, Jenkins, CircleCI) with build ID, commit SHA, and branch
What does the report schema look like?
What is the top-level structure?
{
"schemaVersion": "1.0.0",
"testRunId": "797128f5-c86d-466c-8d6d-8ec62dfc70b6",
"startedAt": "2026-02-07T10:41:28.759Z",
"completedAt": "2026-02-07T10:41:36.794Z",
"totalDuration": 8035,
"summary": {
"total": 6,
"passed": 5,
"failed": 1,
"flaky": 0,
"skipped": 0
},
"ci": {
"provider": "github-actions",
"buildId": "12345678",
"commitSha": "abc123def456",
"branch": "main"
},
"timeline": [...]
}
What fields does the top-level object contain?
| Field | Type | Description |
|---|---|---|
schemaVersion | string | Report format version |
testRunId | string | Auto-generated UUID for this run (overridable via config) |
startedAt | string | ISO timestamp when the run started |
completedAt | string | ISO timestamp when the run completed |
totalDuration | number | Total run duration in milliseconds |
summary | object | Counts of total, passed, failed, flaky, and skipped tests |
ci | object | null | Auto-detected CI environment details, or null if not in CI |
timeline | array | Chronological list of page navigations with associated tests |
What does the navigation timeline look like?
The timeline array is the core of the report. Each entry represents a single page navigation:
{
"url": "https://en.wikipedia.org/wiki/Main_Page",
"navigationType": "goto",
"visitedAt": "2026-02-07T10:41:29.844Z",
"duration": 216,
"specFile": "tests/homepage.spec.ts",
"domContentLoadedAt": "2026-02-07T10:41:30.200Z",
"networkStats": {
"totalRequests": 40,
"failedRequests": 0,
"totalBytes": 1289736,
"byType": {
"xhr": 0,
"document": 1,
"script": 9,
"stylesheet": 2,
"image": 27,
"font": 2,
"other": 0
}
},
"tests": [
{
"title": "homepage.spec.ts > Homepage > loads correctly",
"status": "passed",
"duration": 1028,
"failure": null
}
]
}
What fields does each timeline entry contain?
| Field | Type | Description |
|---|---|---|
url | string | The visited URL |
navigationType | string | How the navigation occurred (see table below) |
visitedAt | string | ISO timestamp when the navigation started |
duration | number | Time in milliseconds to complete the navigation |
specFile | string | Path to the test file that triggered this navigation |
domContentLoadedAt | string | ISO timestamp when the DOM finished parsing |
networkStats | object | Network request summary for this page visit |
tests | array | Test results associated with this navigation |
What navigation types does TestRelic detect?
| Type | Description | Triggered by |
|---|---|---|
goto | Explicit navigation call | page.goto() |
link_click | Navigation from clicking a link | page.click('a') |
back | Browser back navigation | page.goBack() |
forward | Browser forward navigation | page.goForward() |
spa_route | Single-page app route change | Client-side routing |
hash_change | URL hash change | Anchor link click or location.hash change |
What does the networkStats object contain?
| Field | Type | Description |
|---|---|---|
totalRequests | number | Total number of network requests for this page |
failedRequests | number | Number of failed requests (4xx, 5xx) |
totalBytes | number | Total bytes transferred |
byType | object | Breakdown of request counts by resource type |
Resource types tracked in byType: document, script, stylesheet, image, font, xhr, other.
What does each test result inside a timeline entry contain?
| Field | Type | Description |
|---|---|---|
title | string | Full test title including file and suite |
status | string | Result: passed, failed, flaky, or skipped |
duration | number | Test execution time in milliseconds |
failure | object | null | Error details if the test failed; null otherwise |
When failure is present:
{
"failure": {
"message": "Timeout 30000ms exceeded.",
"snippet": {
"file": "tests/homepage.spec.ts",
"line": 15,
"lines": [
" test('homepage loads', async ({ page }) => {",
" await page.goto('https://example.com');",
">>> await expect(page.locator('.missing')).toBeVisible();",
" });"
]
},
"stack": "Error: Timeout 30000ms exceeded.\n at ..."
}
}
The >>> marker indicates the exact line where the error occurred.
How does CI integration work?
TestRelic automatically detects your CI environment and captures:
- GitHub Actions — workflow run ID, commit SHA, branch, PR number
- GitLab CI — pipeline ID, job ID, commit SHA, branch
- Jenkins — build number, commit SHA, branch
- CircleCI — build number, workflow ID, commit SHA, branch
If not running in CI, the ci field will be null.
How do I analyze browser reports?
How do I query reports with jq?
# View summary
cat test-results/analytics-timeline.json | jq '.summary'
# List all timeline entries (url + navigationType)
cat test-results/analytics-timeline.json | jq '.timeline[] | {url, navigationType, duration}'
# Find failed tests
cat test-results/analytics-timeline.json | jq '.timeline[].tests[] | select(.status == "failed")'
# Get navigation timeline for all entries
cat test-results/analytics-timeline.json | jq '.timeline[] | {url, navigationType, visitedAt}'
# Calculate average navigation duration
cat test-results/analytics-timeline.json | jq '[.timeline[].duration] | add / length'
# Get network stats per page
cat test-results/analytics-timeline.json | jq '.timeline[] | {url, totalRequests: .networkStats.totalRequests, totalBytes: .networkStats.totalBytes}'
# Find pages with failed requests
cat test-results/analytics-timeline.json | jq '.timeline[] | select(.networkStats.failedRequests > 0)'
How do I analyze reports programmatically in Node.js?
const fs = require('fs');
const report = JSON.parse(
fs.readFileSync('test-results/analytics-timeline.json', 'utf-8')
);
// Summary
console.log('Test Summary:', report.summary);
// Find slowest navigations
const slowest = report.timeline
.sort((a, b) => b.duration - a.duration)
.slice(0, 5)
.map(t => ({ url: t.url, duration: t.duration }));
console.log('Slowest Navigations:', slowest);
// Find failed tests
const failed = report.timeline
.flatMap(entry => entry.tests)
.filter(t => t.status === 'failed');
console.log('Failed Tests:', failed.map(t => t.title));
// Network stats summary
const totalBytes = report.timeline
.reduce((sum, entry) => sum + entry.networkStats.totalBytes, 0);
console.log(`Total bytes transferred: ${totalBytes}`);
How do I analyze reports in Python?
import json
with open('test-results/analytics-timeline.json', 'r') as f:
report = json.load(f)
# Summary
print(f"Passed: {report['summary']['passed']}")
print(f"Failed: {report['summary']['failed']}")
# Average navigation duration
durations = [entry['duration'] for entry in report['timeline']]
if durations:
print(f"Average navigation duration: {sum(durations) / len(durations):.2f}ms")
# Failed tests
failed = [
t for entry in report['timeline']
for t in entry['tests'] if t['status'] == 'failed'
]
for test in failed:
print(f"FAILED: {test['title']}")
if test['failure']:
print(f" Error: {test['failure']['message']}")
What are the best practices for using browser reports?
How do I track performance trends over time?
Archive reports with timestamps after each run:
cp test-results/analytics-timeline.json \
reports/$(date +%Y%m%d-%H%M%S)-report.json
How do I integrate report analysis into CI/CD?
# .github/workflows/test.yml
- name: Run Tests
run: npx playwright test
- name: Check for failures
run: |
FAILED=$(jq '.summary.failed' test-results/analytics-timeline.json)
if [ "$FAILED" -gt 0 ]; then
echo "Tests failed: $FAILED"
exit 1
fi
Where do I go next?
- 📖 API Report Structure — Understand API test reports
- 📖 Unified Report Structure — Combined E2E + API reports
- 📖 E2E Testing Guide — Writing browser tests
- ⚙️ Configuration Reference — Report configuration options