TestKase Docs
AutomationTest Frameworks

Playwright

Set up Playwright for browser testing and integrate test results with TestKase.

Overview

Playwright is a browser automation framework by Microsoft for end-to-end testing across Chromium, Firefox, and WebKit. It provides auto-waiting, network interception, and multi-browser support out of the box.

To integrate Playwright results with TestKase, you have two options:

  • JSON reporter (recommended) — use --format playwright for the richest data
  • JUnit XML reporter — use --format junit for cross-framework compatibility

Prerequisites

  • Node.js 18+

Installation

Use the Playwright installer to create a new project with config and example tests:

npm init playwright@latest

The interactive setup will:

  • Create a playwright.config.ts file
  • Add example test files in tests/
  • Install browser binaries for Chromium, Firefox, and WebKit
  • Optionally set up a GitHub Actions workflow

To add Playwright to an existing project instead:

npm install --save-dev @playwright/test
npx playwright install

Project Setup

The generated playwright.config.ts provides a solid starting point. Customize it for your application:

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

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  retries: process.env.CI ? 2 : 0,
  reporter: 'html',

  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

Writing Tests

Create a test file (e.g., tests/login.spec.ts):

// tests/login.spec.ts
import { test, expect } from '@playwright/test';

test.describe('login page', () => {
  test('[48271] should accept valid credentials', async ({ page }) => {
    await page.goto('/login');
    await page.fill('[data-testid="email"]', 'user@example.com');
    await page.fill('[data-testid="password"]', 'password123');
    await page.click('[data-testid="login-button"]');
    await expect(page).toHaveURL('/dashboard');
  });

  test('[48272] should show error for invalid password', async ({ page }) => {
    await page.goto('/login');
    await page.fill('[data-testid="email"]', 'user@example.com');
    await page.fill('[data-testid="password"]', 'wrong');
    await page.click('[data-testid="login-button"]');
    await expect(page.locator('.error-message')).toBeVisible();
  });

  test('[48273] should require email field', async ({ page }) => {
    await page.goto('/login');
    await page.click('[data-testid="login-button"]');
    await expect(page.locator('[data-testid="email-error"]')).toHaveText('Email is required');
  });
});

Each test name includes a 5-digit Automation ID in square brackets. The @testkase/reporter CLI extracts these IDs using the regex \[(\d{5})\]. For the example above, the extracted Automation IDs are:

  • 48271 → linked to the "valid credentials" test case in TestKase
  • 48272 → linked to the "invalid password" test case in TestKase
  • 48273 → linked to the "email required" test case in TestKase

Generate Automation IDs in TestKase first, then embed them in your test names. The [XXXXX] pattern can appear anywhere in the test name — the reporter extracts all 5-digit IDs found in brackets.

Running Tests

Run all tests:

npx playwright test

The JSON reporter provides the richest data for the TestKase reporter. Set the PLAYWRIGHT_JSON_OUTPUT_NAME environment variable and use the --reporter=json flag:

PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=json

You can also combine reporters to keep the HTML report alongside the JSON output:

PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=json,html

Report with --format playwright:

npx @testkase/reporter report \
  --format playwright \
  --results-file test-results/playwright.json \
  ...

Option B: JUnit XML Reporter

Playwright has a built-in JUnit reporter that produces standard JUnit XML output. This is useful if you already use --format junit for other frameworks in your pipeline:

PLAYWRIGHT_JUNIT_OUTPUT_NAME=test-results/junit.xml npx playwright test --reporter=junit

You can also combine reporters:

PLAYWRIGHT_JUNIT_OUTPUT_NAME=test-results/junit.xml npx playwright test --reporter=junit,html

Report with --format junit:

npx @testkase/reporter report \
  --format junit \
  --results-file test-results/junit.xml \
  ...

Both formats extract Automation IDs from test names using the same [XXXXX] pattern. Choose JSON (--format playwright) for richer metadata, or JUnit XML (--format junit) for cross-framework compatibility. If you need different reporters locally vs CI, use a Playwright config with conditional reporters based on process.env.CI.

TestKase Integration

After generating the report file, report results to TestKase. Use --format playwright for JSON or --format junit for JUnit XML:

With JSON output

npx @testkase/reporter report \
  --token $TESTKASE_PAT \
  --project-id PRJ-1 \
  --org-id 1173 \
  --cycle-id TCYCLE-5 \
  --format playwright \
  --results-file test-results/playwright.json

--cycle-id is optional. If not provided, results are reported to TCYCLE-1 — the master test cycle for the project.

With JUnit XML output

npx @testkase/reporter report \
  --token $TESTKASE_PAT \
  --project-id PRJ-1 \
  --org-id 1173 \
  --cycle-id TCYCLE-5 \
  --format junit \
  --results-file test-results/junit.xml

Automation ID Mapping

The reporter extracts 5-digit Automation IDs from Playwright test titles using the [XXXXX] bracket pattern:

Test CodeExtracted ID
test('[48271] should accept valid credentials', ...)48271
test('[48272] should show error for invalid password', ...)48272
test.describe('auth', () => { test('[48273] validates email', ...) })48273

The [XXXXX] pattern can appear anywhere in the test() title. The describe block structure does not affect the Automation ID — only the 5-digit number inside brackets matters.

Complete Example

1. Test File

// tests/login.spec.ts
import { test, expect } from '@playwright/test';

test.describe('login page', () => {
  test('[48271] should accept valid credentials', async ({ page }) => {
    await page.goto('/login');
    await page.fill('[data-testid="email"]', 'user@example.com');
    await page.fill('[data-testid="password"]', 'password123');
    await page.click('[data-testid="login-button"]');
    await expect(page).toHaveURL('/dashboard');
  });
});

2. Run Tests and Generate JSON Report

PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json \
  npx playwright test --reporter=json

3. Report Results to TestKase

npx @testkase/reporter report \
  --token $TESTKASE_PAT \
  --project-id PRJ-1 \
  --org-id 1173 \
  --cycle-id TCYCLE-5 \
  --format playwright \
  --results-file test-results/playwright.json

Troubleshooting

JSON output file is empty or missing

Ensure you are setting the PLAYWRIGHT_JSON_OUTPUT_NAME environment variable and using --reporter=json. Without both, Playwright will not write JSON output to a file:

# Correct — both env var and reporter flag
PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=json

# Incorrect — missing env var, JSON goes to stdout only
npx playwright test --reporter=json

If redirecting to stdout, pipe it to a file:

npx playwright test --reporter=json > test-results/playwright.json

JUnit XML output file is empty or missing

For JUnit XML output, use the PLAYWRIGHT_JUNIT_OUTPUT_NAME environment variable with --reporter=junit:

# Correct
PLAYWRIGHT_JUNIT_OUTPUT_NAME=test-results/junit.xml npx playwright test --reporter=junit

# Incorrect — missing env var
npx playwright test --reporter=junit

Browser not installed

If tests fail with a browser launch error, install the required browsers:

npx playwright install

To install a specific browser only:

npx playwright install chromium

Automation IDs not being extracted

Ensure your test names include the [XXXXX] bracket pattern with a 5-digit Automation ID. For example:

test.describe('login page', () => {
  test('[48271] should accept valid credentials', async ({ page }) => { ... });
});

The reporter extracts 48271 from the test name. Without the [XXXXX] pattern, the test will be skipped.

Use --dry-run to preview the exact Automation IDs the reporter extracts:

npx @testkase/reporter report \
  --format playwright \
  --results-file test-results/playwright.json \
  --dry-run --verbose