
With Playwright and TypeScript ready, it’s time to explore the real power of this setup.
In this blog, we’ll walk through writing your first Playwright test, applying the Page Object Model (POM) for scalable test design, mastering locator strategies for stability, using Playwright’s debugging tools to resolve issues faster, and analyzing test reports for actionable insights.
How To Write a First Playwright Test in TypeScript?
Before writing your first test with Playwright, ensure your framework includes essential configuration files for TypeScript support, code quality, and documentation. These help maintain consistency, readability, and scalability as your test suite grows.
Essential File
- tsconfig.json – Enables TypeScript compilation and type safety, supports path aliases, and ensures modern JavaScript features like async/await.
{
“compilerOptions”: {
“target”: “ESNext”,
“module”: “CommonJS”,
“moduleResolution”: “Node”,
“types”: [“@playwright/test”],
“esModuleInterop”: true,
“strict”:
true,
“skipLibCheck”:
true,
“baseUrl”: “.”,
“paths”: {
“@pages/*”: [“src/pageObject/pages/*”],
“@tests/*”: [“src/tests/*”]
}
},
“include”: [“src/**/*.ts”, “tests/**/*.ts”, “playwright.config.ts”]
}
Best Practices
- typedoc.json – Generates documentation for page objects and helper classes, making the framework easier to understand and maintain.
- eslint.config.json – Enforces code quality and consistency, catches common errors, and integrates with VS Code and CI pipelines.
Basic Test Structure with TypeScript Annotations
When starting your first Playwright test in TypeScript, define your test file with the .ts extension and use Playwright Test’s built-in test runner. TypeScript annotations ensure that your variables, parameters, and return types are correctly enforced at compile time, reducing runtime errors.
Example
import { test, expect } from ‘@playwright/test’;
test(‘basic navigation example’, async ({ page }) => {
await page.goto(‘https://example.com’);
const title = await page.title();
expect(title).toBe(‘Example Domain’);
});
Here, page is strongly typed, so IntelliSense guides you with valid methods and properties.
Page Object Initialization & Browser Context
To make your tests maintainable, implement the Page Object Model (POM) using TypeScript classes. A browser context isolates cookies, sessions, and storage between tests—perfect for parallel execution.
Example
export class LoginPage {
constructor(private page: Page) {}
async navigate() {
await this.page.goto(‘https://app.example.com/login’);
}
async login(username: string, password: string) {
await this.page.fill(‘#username’, username);
await this.page.fill(‘#password’, password);
await this.page.click(‘#loginBtn’);
}
}
This approach makes your test scripts cleaner and reusable across multiple test scenarios.
Navigation & Element Interactions
Playwright supports fast and reliable navigation with automatic waiting. Element interactions such as clicking buttons, filling forms, and dragging elements are asynchronous and work seamlessly with await.
Example
await page.goto(‘https://app.example.com/dashboard’);
await page.click(‘text=New Project’);
await page.fill(‘#projectName’, ‘My First Project’);
await page.click(‘button:has-text(“Create”)’);
Locator Strategies with IntelliSense Support
With TypeScript, IntelliSense helps you avoid incorrect locator usage. Playwright offers multiple locator methods like getByRole, getByText, and locator. These improve test resilience by targeting elements based on role, label, or accessibility attributes rather than brittle CSS selectors.
Example
const submitButton = page.getByRole(‘button’, { name: ‘Submit’ });
await submitButton.click();
This improves both test readability and maintainability over time.
Error Handling & Async/Await Patterns
Async/await keeps your code readable and avoids callback nesting. Combine it with robust error handling using try…catch to capture and log failures for debugging.
Example:
try {
await page.goto(‘https://app.example.com’);
await page.click(‘#nonExistentElement’); // Will throw if element not found
} catch (error) {
console.error(‘Test failed due to:’, error);
}
TypeScript’s type safety ensures that you handle potential nulls, undefined values, and incorrect method calls before the test even runs.
Running Playwright Tests and Understanding Results
1. Command-Line Execution with Customization Flags
Playwright’s CLI allows precise control over how and what you execute. By combining flags, you can filter tests, target environments, and debug efficiently. For example:
- npx playwright test –grep “@smoke” → Runs only tests tagged as smoke.
- npx playwright test –project=chromium → Runs tests in Chromium only.
- npx playwright test –headed → Executes in a visible browser for debugging.
- npx playwright test –debug → Opens the interactive debugging mode with step-by-step execution.
- npx playwright test –ui → Launches the Test Runner UI, enabling you to run, debug, and monitor tests visually.
This approach is especially useful when running targeted scenarios during development or isolating flaky tests.
2. VS Code Extension Integration and Debugging
The official Playwright VS Code extension simplifies running and debugging tests without leaving your editor:
- Tests appear in the Test Explorer panel, grouped by file and project.
- You can run or debug a single test, a file, or an entire suite with one click.
- Breakpoints can be set directly in your TypeScript files to inspect application state.
- Live logs, step-by-step execution, and screenshots are integrated into the debug console.
This tight integration speeds up your development cycle by reducing context switching.
3. HTML Report Analysis and Debugging Artifacts
After execution, Playwright generates an HTML report that provides a clear view of your test outcomes:
- Test summary with pass/fail counts and execution time.
- Failure diagnostics including stack traces, console logs, and request/response data.
- Artifacts like screenshots, videos, and trace files for reproducing issues.
Opening the report locally or hosting it on a CI artifact server helps QA teams quickly identify root causes and share findings with developers.
4. Headed vs. Headless Execution Modes
Choosing between headed and headless execution impacts both debugging and performance:
- Headed Mode (–headed or headless: false) → Perfect for visually inspecting test flows during local development.
- Headless Mode (default) → Ideal for CI pipelines, offering faster execution with fewer system resources.
Switching modes is as simple as toggling a config option or adding a CLI flag, allowing flexibility between local debugging and automated runs.
How to Debug Tests with Playwright’s Built-In Tools?
Playwright offers several practical debugging tools to quickly detect and fix issues in test scripts:
- Interactive Debug Mode
Run tests with the debug flag
npx playwright test –debug
This launches the Playwright Inspector, pausing execution at each step and allowing interactive control over the browser state, DOM elements, and network activity. It helps step through flaky or failing tests to understand timing or selector problems.
Trace Viewer
Enable tracing in playwright.config.ts:
use: {
trace: ‘retain-on-failure’
}
When a test fails, a trace file is generated. Open it with:
npx playwright show-trace trace.zip
The Trace Viewer displays a detailed timeline of actions, DOM snapshots, network requests, and screenshots, providing deep insight into the failure context.
- Screenshots and Video Recording
Configure automatic screenshot and video capture on failures
use: {
screenshot: ‘only-on-failure’,
video: ‘retain-on-failure’
}
These artifacts help visually diagnose UI changes or rendering issues without rerunning tests.
- Console Log Capture
Listen to browser console logs within tests
page.on(‘console’, msg => console.log(msg.text()));
Capturing console warnings and errors reveals client-side issues that may not cause immediate test failures but affect stability.
How to Analyze Test Results and Reports in Playwright?
Playwright’s reporting tools give actionable insights to optimize test reliability and speed:
- HTML Report
Enable HTML reporting in playwright.config.ts
reporter: [[‘html’, { outputFolder: ‘playwright-report’ }]]
After test execution, open playwright-report/index.html to review test statuses, failure messages, embedded screenshots, videos, and trace links.
- Custom Reporters
Playwright supports multiple reporters (JSON, JUnit, Allure). For example, to add Allure:
npm install -D @playwright/test allure-playwright
Then configure in playwright.config.ts:
reporter: [[‘allure-playwright’]]
After running your tests, generate and open the Allure report with:
npx allure serve allure-results
Integrate Allure reports in CI/CD pipelines for trend analysis and flaky test detection.
- Retry Logic
Control retries for flaky tests in config:
retries: 2,
The report tracks retry attempts, helping identify unstable tests requiring fixes.
- Parallel Execution Metrics
Playwright runs tests in parallel by default; reports include data on worker distribution and execution time, useful for balancing test load and optimizing runtime
End Note
Writing, running, and debugging Playwright test in TypeScript gives teams a powerful way to build reliable and scalable test suites. By combining Playwright’s cross-browser automation with TypeScript’s type safety, you gain both flexibility and confidence in your testing process.
With clear structure, reusable code, and effective debugging, testing shifts from being a challenge to becoming a catalyst for faster, higher-quality releases.
As a leading Automation Testing Company, At Testrig Technologies, we leverage Playwright with TypeScript to build reliable, scalable, and maintainable automation test frameworks.