
Playwright with TypeScript Setup: The Only Guide You Need in 2026
Setting up Playwright with TypeScript in 2026 is one of the best investments you can make as a QA engineer or automation tester. In under 30 minutes, you will have a fully working browser automation framework that is faster than Selenium, more reliable than most tools on the market, and built for modern web applications. This guide walks you through every single step — from a blank folder to a running test — with real TypeScript code you can copy and use immediately.
Whether you are completely new to test automation, switching from Selenium, or just evaluating Playwright for your team, this tutorial covers everything you need: installation, configuration, writing tests, using locators, adding assertions, structuring your code with the Page Object Model, and running your tests in a CI/CD pipeline using GitHub Actions.
Playwright is developed and maintained by Microsoft and has become the fastest-growing test automation framework in 2024 and 2025 and same continues in 2026 as well. Its built-in auto-waiting, cross-browser support, and powerful debugging tools — especially the Trace Viewer — make it significantly easier to build and maintain a stable test suite compared to older tools.
By the end of this tutorial, you will have a complete, production-ready Playwright with TypeScript project that you can build on for any web application.
| What you will learn | Time required | Difficulty |
| Playwright with TypeScript full setup | 25–30 minutes | Beginner friendly |
| Writing first test with assertions | 10 minutes | Easy |
| Page Object Model structure | 15 minutes | Intermediate |
| CI/CD with GitHub Actions | 10 minutes | Intermediate |
Table of Contents
- What is Playwright? (And why choose it over Selenium in 2026)
- Why Playwright with TypeScript is the right choice?
- Prerequisites: what you need before starting
- Step 1 — Install Node.js
- Step 2 — Create your project folder
- Step 3 — Install Playwright with TypeScript using the CLI
- Step 4 — Understand the generated project structure
- Step 5 — Configure playwright.config.ts (the right way)
- Step 6 — Write your first Playwright TypeScript test
- Step 7 — Run your tests and read the output
- Step 8 — Master Playwright locators in TypeScript
- Step 9 — Write powerful assertions with expect()
- Step 10 — Implement the Page Object Model
- Step 11 — Run tests across multiple browsers and devices
- Step 12 — Debug with Trace Viewer, screenshots, and videos
- Step 13 — Integrate with GitHub Actions CI/CD
- Playwright vs Selenium: honest comparison for 2026
- Common setup errors and how to fix them
- Frequently asked questions
- What to learn next
1. What is Playwright?
Playwright is an open-source end-to-end testing and browser automation framework created by Microsoft. It was first released in January 2020 and has seen extraordinary growth in adoption since then, now ranking consistently among the top three browser automation tools globally alongside Selenium and Cypress.
Unlike traditional browser automation tools that rely on browser-specific WebDriver implementations, Playwright communicates directly with browsers using native browser protocols — the Chrome DevTools Protocol for Chromium, and equivalent protocols for Firefox and WebKit. This direct communication is what makes Playwright so much faster and more stable than older approaches.
Playwright supports three major browser engines out of the box: Chromium (which powers Google Chrome and Microsoft Edge), Firefox, and WebKit (which powers Apple Safari). This means you can run the exact same test code across all three engines without any modifications — a genuine cross-browser test suite with one codebase.
Key features that make Playwright stand out in 2026:
- Auto-waiting: Playwright automatically waits for elements to be actionable before interacting with them. No more Thread.sleep(), no more complicated explicit wait logic
- Built-in assertions: The expect() library comes with automatic retry — assertions keep trying until they pass or the timeout is reached
- Multiple browser contexts: Simulate multiple users simultaneously without opening multiple browser instances
- Network interception: Mock API responses, modify request headers, and simulate network failures directly from your test code
- Trace Viewer: An interactive visual debugger that records every action, DOM snapshot, screenshot, and network request during a test run
- Codegen: Record your browser interactions and auto-generate TypeScript test code — perfect for getting started quickly
- API testing: A built-in HTTP client for testing REST APIs alongside your UI tests
- Component testing: Experimental support for testing React, Vue, and Angular components in isolation
2. Why Playwright with TypeScript is the right choice?
Playwright officially supports both JavaScript and TypeScript. However, TypeScript has become the overwhelming community preference for Playwright projects, and for very good reasons. If you are going to invest time building a test automation framework, you want TypeScript.
| Benefit | JavaScript | TypeScript |
| Type checking | Runtime errors only | Compile-time errors caught early |
| IDE autocomplete | Limited | Full IntelliSense in VS Code |
| Refactoring safety | Risky — easy to miss usages | Compiler validates all changes |
| Page Object Models | No interface enforcement | Interfaces ensure correct structure |
| Team onboarding | Hard to know expected types | Types act as documentation |
| Error messages | Generic runtime errors | Specific, location-pinned errors |
| Industry adoption | Being phased out in most teams | Standard for enterprise QA teams |
The most practical benefit you will notice immediately: when you rename a method in your Page Object Model, TypeScript instantly highlights every test file that calls the old method name. In plain JavaScript, you discover those broken references only when the tests actually run — which could be much later in your CI pipeline.
PRO TIP Install the Playwright Test for VS Code extension (ms-playwright.playwright) before you start. It adds a test runner sidebar, lets you run and debug individual tests with one click, and provides instant autocomplete for all Playwright APIs.
3. Prerequisites: What You Need Before Starting
Before you install Playwright, make sure the following are in place on your machine:
| Requirement | Minimum version | How to check | Where to get it |
| Node.js | 16.x | node –version | nodejs.org |
| npm | 7.x | npm –version | Included with Node.js |
| VS Code | Any | — | code.visualstudio.com |
| Git | Any | git –version | git-scm.com |
| OS | Windows 10 / macOS 11 / Ubuntu 18.04 | — | — |
You do not need to install TypeScript separately. The Playwright CLI installs and configures TypeScript automatically as part of the project setup. You also do not need to install browser binaries separately — Playwright downloads its own versions of Chromium, Firefox, and WebKit.
⚠ Do not use Node.js version 14 or below. Playwright requires Node.js 16 at minimum, and Node.js 20 LTS is strongly recommended for the best performance and compatibility.
4. Step 1 — Install Node.js
If you already have Node.js 16 or higher installed, you can skip to Step 2. To check your current version, open your terminal and run:
node –version
If the command returns v16.x.x or higher, you are good. If not, install or update Node.js using one of the following methods:
Windows
- Go to nodejs.org and click the LTS download button
- Run the downloaded .msi installer
- Accept all defaults and complete the installation
- Open a new Command Prompt window and run: node –version
macOS (using Homebrew — recommended)
brew install node
If you do not have Homebrew, install it first from brew.sh, or download the macOS installer directly from nodejs.org.
Ubuntu / Debian Linux
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash –
sudo apt-get install -y nodejs
Verify installation:
node –version # Should show v20.x.x or similar
npm –version # Should show 10.x.x or similar
5. Step 2 — Create Your Project Folder
Create a new directory for your Playwright project. Choose a name that reflects your project — for a QA automation project for qatribe.in, something like playwright-qatribe works well.
mkdir playwright-qatribe
cd playwright-qatribe
This folder will become the root of your automation framework. Everything — test files, page objects, configuration, reports — will live inside this directory.
PRO TIP If you are adding Playwright tests to an existing application repository, create the playwright project inside a dedicated tests/ or e2e/ subdirectory within that repo. This keeps test code cleanly separated from application source code.
6. Step 3 — Install Playwright with TypeScript Using the CLI
Playwright provides an official CLI that handles the entire scaffolding — TypeScript configuration, example tests, browser downloads, and CI configuration. Run this single command inside your project folder:
npm init playwright@latest
The CLI will ask you a series of setup questions. Here is exactly what to enter for a TypeScript project:
| CLI prompt | Your answer | Why this choice |
| TypeScript or JavaScript? | TypeScript | Type safety, better IDE support |
| Where to put your end-to-end tests? | tests | Standard, clean project structure |
| Add a GitHub Actions workflow? | true (yes) | Sets up CI/CD from day one |
| Install Playwright browsers? | true (yes) | Downloads Chromium, Firefox, WebKit |
After you answer the prompts, Playwright will:
- Create package.json with all required dependencies
- Install @playwright/test and its TypeScript types
- Generate playwright.config.ts with sensible defaults
- Create tsconfig.json configured for Playwright
- Download Chromium, Firefox, and WebKit browser binaries (this may take 2–5 minutes)
- Create a .github/workflows/playwright.yml CI file
- Generate example test files in the tests/ folder
When it completes, you will see a success message with the commands to run your first test. You now have a fully working Playwright TypeScript project.
⚠ If you get an EACCES permission error on Linux or macOS, prefix the command with sudo or fix your npm global directory permissions. Never run Node.js project commands as root in a production environment.
7. Step 4 — Understand the Generated Project Structure
After installation, your project folder will contain these files and directories:
├── tests/
│ └── example.spec.ts ← Your first test file
├── tests-examples/
│ └── demo-todo-app.spec.ts ← More complex example tests
├── playwright.config.ts ← Master configuration file
├── package.json ← Node project metadata + scripts
├── package-lock.json ← Exact dependency versions
├── tsconfig.json ← TypeScript compiler configuration
└── .github/
└── workflows/
└── playwright.yml ← GitHub Actions CI workflowWhat each file does:
- tests/ — This is where all your test files live. Every file ending in .spec.ts inside this folder will be automatically discovered and run by Playwright
- playwright.config.ts — The control centre of your framework. Controls which browsers run, timeouts, base URLs, reporters, and much more (covered in depth in Step 5)
- package.json — Contains your project metadata and the npm scripts. The most important script is test: playwright test
- tsconfig.json — Tells the TypeScript compiler how to process your .ts files. Playwright’s default tsconfig is correctly configured — do not change it unless you have a specific reason
- .github/workflows/playwright.yml — The GitHub Actions workflow that runs your tests automatically on every push or pull request
PRO TIP Add test-results/ and playwright-report/ to your .gitignore file. These folders contain generated output from test runs and should not be committed to version control.
8. Step 5 — Configure playwright.config.ts (The Right Way)
The default playwright.config.ts is a good starting point, but a few targeted changes will make your framework significantly more robust. Here is a well-configured version with comments explaining every choice:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
// Where Playwright looks for test files
testDir: './tests',
// Run tests within each file in parallel (requires independent tests)
fullyParallel: true,
// Fail the build if test.only() is accidentally left in code
forbidOnly: !!process.env.CI,
// Retry failed tests twice in CI, never locally
retries: process.env.CI ? 2 : 0,
// Use 2 parallel workers in CI, auto on local
workers: process.env.CI ? 2 : undefined,
// Combine terminal output + HTML report
reporter: [['list'], ['html', { open: 'never' }]],
use: {
// Base URL — use relative paths in tests (e.g., page.goto('/blogs'))
baseURL: 'https://qatribe.in',
// Record trace only on first retry — best for debugging CI failures
trace: 'on-first-retry',
// Take screenshot only when test fails
screenshot: 'only-on-failure',
// Keep video for failed tests only
video: 'retain-on-failure',
// Max time per action (click, fill, etc.)
actionTimeout: 10000,
// Max time for page navigation
navigationTimeout: 30000,
// Simulate Indian locale and timezone
locale: 'en-IN',
timezoneId: 'Asia/Kolkata',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
// Mobile viewports
{ name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } },
{ name: 'Mobile Safari', use: { ...devices['iPhone 13'] } },
],
});PRO TIP Set locale: ‘en-IN’ and timezoneId: ‘Asia/Kolkata’ if your website serves Indian users. This ensures date formats, currency symbols, and timezone-sensitive features are tested in the correct regional context.
9. Step 6 — Write Your First Playwright TypeScript Test
Open the file tests/example.spec.ts and replace its contents with the following. This is a real test against qatribe.in that you can run immediately:
import { test, expect } from '@playwright/test';
// Test group — organises related tests together
test.describe('QATribe Homepage', () => {
test('page loads with correct title', async ({ page }) => {
// Navigate to the homepage
await page.goto('/');
// Assert the page title contains 'QATRIBE'
await expect(page).toHaveTitle(/QATRIBE/i);
});
test('main navigation links are visible', async ({ page }) => {
await page.goto('/');
// Check key navigation items are present
await expect(page.getByRole('link', { name: 'Blogs' })).toBeVisible();
await expect(page.getByRole('link', { name: 'Playwright' })).toBeVisible();
await expect(page.getByRole('link', { name: 'Selenium' })).toBeVisible();
});
test('clicking Blogs navigates correctly', async ({ page }) => {
await page.goto('/');
await page.getByRole('link', { name: 'Blogs' }).click();
await expect(page).toHaveURL(/blogs/i);
});
});Let us break down each part of this test file:
- import { test, expect } — Playwright’s test runner and assertion library. Both are fully typed with TypeScript
- test.describe() — Groups related tests. Helps organise your test output and lets you run just one group at a time
- async ({ page }) — The page fixture is automatically provided by Playwright. It represents a new browser page for each test
- await page.goto(‘/’) — Navigates to the baseURL set in your config. Using ‘/’ instead of the full URL makes your tests environment-agnostic
- await expect(page).toHaveTitle() — A built-in assertion. The /QATRIBE/i is a case-insensitive regex, which makes the assertion more resilient to capitalisation changes
- page.getByRole() — A semantic locator. This is Playwright’s recommended way to find elements — it mirrors how real users and screen readers interact with the page
10. Step 7 — Run Your Tests and Read the Output
Running Playwright tests is a single command. From your project root:
npx playwright testThis runs every .spec.ts file in your tests/ folder, across all browser projects defined in your config. You will see real-time output in your terminal as each test runs.
Essential run commands — memorise these:
| Command | What it does |
| npx playwright test | Run all tests on all configured browsers |
| npx playwright test –headed | Run with visible browser window — great for watching tests |
| npx playwright test –project=chromium | Run on Chromium only (skip Firefox and WebKit) |
| npx playwright test example.spec.ts | Run a specific test file only |
| npx playwright test -g ‘page loads’ | Run tests whose name matches the pattern |
| npx playwright test –debug | Open Playwright Inspector — step through tests manually |
| npx playwright codegen https://qatribe.in | Record your browser actions and auto-generate test code |
| npx playwright show-report | Open the HTML test report in your browser |
After the run, Playwright generates an HTML report in the playwright-report/ folder. Open it with npx playwright show-report to see a visual breakdown of every test — passed, failed, and skipped — with screenshots, videos, and trace links for any failures.
PRO TIP During development, run with –headed and –project=chromium. This is the fastest feedback loop — one browser, visible window, instant results. Save the full cross-browser run for your CI pipeline.
11. Step 8 — Master Playwright Locators in TypeScript
Locators are how Playwright finds elements on the page to interact with them. Choosing the right locator strategy is one of the most important decisions you make in test automation — bad locators are the number-one cause of flaky tests.
Playwright strongly recommends semantic, user-facing locators over CSS selectors and XPath. Here is the complete hierarchy you should follow:
| Priority | Locator | TypeScript example | Use when |
| 1st (best) | getByRole() | page.getByRole(‘button’, { name: ‘Submit’ }) | Element has an ARIA role and accessible name |
| 2nd | getByLabel() | page.getByLabel(‘Email address’) | Form input is associated with a visible label |
| 3rd | getByPlaceholder() | page.getByPlaceholder(‘Enter your email’) | Input has placeholder text |
| 4th | getByText() | page.getByText(‘Welcome back!’) | Finding by visible text content |
| 5th | getByAltText() | page.getByAltText(‘QATribe logo’) | Images with alt text |
| 6th | getByTestId() | page.getByTestId(‘submit-btn’) | Element has data-testid attribute |
| Last resort | locator(css/xpath) | page.locator(‘.submit-btn’) | When semantic locators are unavailable |
Why semantic locators make your tests more stable:
Consider a button that has the text ‘Submit Form’. If a developer changes the button’s CSS class from .btn-submit to .btn-primary, a test using page.locator(‘.btn-submit’) will break immediately. But page.getByRole(‘button’, { name: ‘Submit Form’ }) will still work — because the developer almost certainly did not change the button’s text or its semantic role.
Semantic locators are tied to what the element IS and what it DOES, not to how it happens to be styled at a given moment.
Chaining and filtering locators:
// Find a specific cell in a table row
const row = page.getByRole('row', { name: 'Playwright Tutorial' });
await row.getByRole('link', { name: 'Read More' }).click();
// Filter a list to find a specific item
const articles = page.getByRole('article');
const playwrightArticle = articles.filter({ hasText: 'Playwright TypeScript' });
await playwrightArticle.getByRole('link', { name: 'Read More' }).click();
// nth() — target a specific element when multiple match
const firstLink = page.getByRole('link', { name: 'Read More' }).nth(0);
await firstLink.click();12. Step 9 — Write Powerful Assertions with expect()
Playwright’s expect() library is built directly into the framework and comes with a critical feature: automatic retry. Every assertion keeps trying until the condition becomes true or the configured timeout is reached. This eliminates an entire category of flaky tests that are caused purely by timing issues.
| Assertion | Example | What it checks |
| toHaveTitle() | await expect(page).toHaveTitle(‘QATribe’) | Page document title |
| toHaveURL() | await expect(page).toHaveURL(/\/blogs/) | Current browser URL |
| toBeVisible() | await expect(locator).toBeVisible() | Element is in viewport and not hidden |
| toBeHidden() | await expect(locator).toBeHidden() | Element is hidden or not in DOM |
| toHaveText() | await expect(locator).toHaveText(‘Hello World’) | Element’s exact text content |
| toContainText() | await expect(locator).toContainText(‘Playwright’) | Element’s text contains substring |
| toHaveValue() | await expect(input).toHaveValue(‘test@qatribe.in’) | Input field’s current value |
| toBeEnabled() | await expect(button).toBeEnabled() | Element is not disabled |
| toBeDisabled() | await expect(button).toBeDisabled() | Element is disabled |
| toBeChecked() | await expect(checkbox).toBeChecked() | Checkbox or radio is checked |
| toHaveCount() | await expect(locator).toHaveCount(5) | Number of matching elements |
| toHaveAttribute() | await expect(link).toHaveAttribute(‘href’, ‘/blogs’) | Element attribute value |
| toHaveClass() | await expect(el).toHaveClass(/active/) | Element has CSS class |
Soft assertions — run all checks before failing:
Standard assertions stop the test the moment one fails. Soft assertions let the test continue collecting all failures, then fail at the end. This is useful when you want to validate an entire page at once:
test('validate homepage elements', async ({ page }) => {
await page.goto('/');
// Soft assertions — test keeps running even if one fails
await expect.soft(page).toHaveTitle(/QATRIBE/i);
await expect.soft(page.getByRole('link', { name: 'Blogs' })).toBeVisible();
await expect.soft(page.getByRole('link', { name: 'Playwright' })).toBeVisible();
await expect.soft(page.getByRole('link', { name: 'Selenium' })).toBeVisible();
await expect.soft(page.getByRole('link', { name: 'API Testing' })).toBeVisible();
// This hard assertion fails if ANY of the soft assertions above failed
expect(test.info().errors).toHaveLength(0);
});13. Step 10 — Implement the Page Object Model
The Page Object Model (POM) is a design pattern that separates your page interaction code from your test logic. Instead of writing page.getByRole(‘link’, { name: ‘Blogs’ }).click() directly in every test, you create a class that represents a page and encapsulates all interactions with it.
TypeScript makes POM significantly more powerful. Interfaces and type annotations ensure your page objects are used correctly, and the compiler catches mistakes before tests even run.
Create the folder structure:
├── tests/
│ └── homepage.spec.ts
├── pages/
│ ├── HomePage.ts
│ └── BlogsPage.ts
└── playwright.config.tspages/HomePage.ts — the page object:
import { Page, Locator, expect } from '@playwright/test';
export class HomePage {
// Page reference
readonly page: Page;
// All locators defined once, used everywhere
readonly blogsLink: Locator;
readonly playwrightLink: Locator;
readonly seleniumLink: Locator;
readonly apiTestingLink: Locator;
readonly searchBox: Locator;
readonly pageHeading: Locator;
constructor(page: Page) {
this.page = page;
this.blogsLink = page.getByRole('link', { name: 'Blogs' });
this.playwrightLink = page.getByRole('link', { name: 'Playwright' });
this.seleniumLink = page.getByRole('link', { name: 'Selenium' });
this.apiTestingLink = page.getByRole('link', { name: 'API Testing' });
this.searchBox = page.getByRole('searchbox');
this.pageHeading = page.getByRole('heading', { level: 1 });
}
// Navigation
async navigate(): Promise<void> {
await this.page.goto('/');
}
// Actions
async clickBlogs(): Promise<void> {
await this.blogsLink.click();
}
async search(keyword: string): Promise<void> {
await this.searchBox.fill(keyword);
await this.searchBox.press('Enter');
}
// Assertions
async assertPageLoaded(): Promise<void> {
await expect(this.page).toHaveTitle(/QATRIBE/i);
await expect(this.blogsLink).toBeVisible();
}
}tests/homepage.spec.ts — clean tests using the page object:
import { test, expect } from ‘@playwright/test’;
import { HomePage } from ‘../pages/HomePage’;
test.describe(‘QATribe Homepage’, () => {
test(‘homepage loads correctly’, async ({ page }) => {
const home = new HomePage(page);
await home.navigate();
await home.assertPageLoaded();
});
test(‘navigating to Blogs works’, async ({ page }) => {
const home = new HomePage(page);
await home.navigate();
await home.clickBlogs();
await expect(page).toHaveURL(/blogs/i);
});
test(‘search returns results’, async ({ page }) => {
const home = new HomePage(page);
await home.navigate();
await home.search(‘playwright’);
await expect(page.getByRole(‘article’).first()).toBeVisible();
});
});Notice how clean the test file is. It reads like plain English — navigate to home, click blogs, verify URL. All the selector details are hidden inside the page object. When a selector needs to change, you update it in one place and every test that uses it is automatically fixed.
14. Step 11 — Run Tests Across Multiple Browsers and Devices
One of Playwright’s headline features is genuine cross-browser testing with zero additional code. Your playwright.config.ts already defines multiple projects. Running npx playwright test executes every test on every project automatically.
Run on a specific browser only:
npx playwright test --project=chromiumnpx playwright test --project=firefoxnpx playwright test --project=webkitnpx playwright test --project='Mobile Chrome'Testing on real mobile viewports:
The devices object from @playwright/test contains presets for over 50 real devices, each with the correct viewport dimensions, user agent string, device pixel ratio, and touch support flags.
// In playwright.config.ts — add to projects array
{ name: ‘Pixel 7’, use: { …devices[‘Pixel 7’] } },
{ name: ‘iPhone 14’, use: { …devices[‘iPhone 14’] } },
{ name: ‘iPad Pro’, use: { …devices[‘iPad Pro 11’] } },
{ name: ‘Galaxy S23’, use: { …devices[‘Galaxy S8’] } },
PRO TIP For a QA blog like qatribe.in which serves a predominantly mobile Indian audience, always include at least one Android and one iOS device in your projects. Real traffic from India is heavily mobile-first.
15. Step 12 — Debug with Trace Viewer, Screenshots and Videos
When a test fails in CI and you cannot see the browser, Playwright’s built-in debugging tools give you complete visibility into what happened.
The Trace Viewer — Playwright’s most powerful debug tool:
The Trace Viewer is a browser-based interactive timeline that shows every action your test took, with a DOM snapshot at each step, all network requests, console logs, and screenshots. It is the equivalent of having a video recording of your test with the ability to pause and inspect the page state at any moment.
# Generate a trace for a specific test
npx playwright test --trace on# Open and inspect the trace
npx playwright show-trace test-results/example-test/trace.zipTake screenshots manually inside tests:
test('capture screenshot', async ({ page }) => {
await page.goto('/');
// Full page screenshot
await page.screenshot({
path: 'screenshots/homepage-full.png',
fullPage: true
});
// Screenshot of a specific element only
const header = page.getByRole('banner');
await header.screenshot({ path: 'screenshots/header.png' });
});Use the Playwright Inspector for step-by-step debugging:
npx playwright test --debugThe Inspector opens alongside the browser and lets you step through your test one action at a time, see the current DOM state, and explore element selectors interactively. This is invaluable for understanding why a locator is not finding what you expect.
16. Step 13 — Integrate with GitHub Actions CI/CD
If you selected ‘Yes’ to the GitHub Actions question during setup, your project already has a working CI workflow file at .github/workflows/playwright.yml. Here is a production-ready version with all the important options configured:
name: Playwright Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
– name: Checkout repository
uses: actions/checkout@v4
– name: Set up Node.js 20
uses: actions/setup-node@v4
with:
node-version: ’20’
cache: ‘npm’
– name: Install dependencies
run: npm ci
– name: Install Playwright browsers
run: npx playwright install –with-deps
– name: Run Playwright tests
run: npx playwright test
env:
CI: true
– name: Upload test report
uses: actions/upload-artifact@v4
if: always() # Upload even if tests fail
with:
name: playwright-report
path: playwright-report/
retention-days: 30
With this workflow in place, every push to main or pull request will automatically run your full Playwright test suite. If tests fail, the HTML report is uploaded as a GitHub Actions artifact that you can download and open to see exactly what went wrong.
PRO TIP Add if: always() to the upload-artifact step. Without it, the report is only uploaded when tests pass — the exact situation where you want it least.
17. Playwright vs Selenium: Honest Comparison for 2026
If you are coming from a Selenium background, here is an honest, side-by-side comparison to help you understand exactly what changes and what stays the same. Playwright with Typescript is the best choice in terms of below points
| Feature | Playwright with TypeScript | Selenium with Java/Python |
| Setup time | 5–10 minutes (CLI handles everything) | 20–45 minutes (manual config) |
| Auto-waiting | Built-in, intelligent, always on | Manual — Thread.sleep() or explicit waits |
| Speed | Very fast (direct browser protocol) | Slower (WebDriver protocol overhead) |
| Cross-browser support | Chromium, Firefox, WebKit natively | All major browsers via WebDriver |
| Mobile testing | Device emulation built-in | Requires Appium separately |
| API testing | Built-in HTTP client | Requires separate library (REST Assured etc.) |
| Trace Viewer | Built-in visual debugger | Not available natively |
| Codegen | Built-in test recorder | Selenium IDE (limited) |
| Network interception | First-class feature | Limited, needs proxy setup |
| Parallel execution | Native, easy to configure | Complex — requires TestNG/JUnit + grid |
| Community size | Growing very rapidly | Very large, mature, established |
| Job market (India) | High demand, growing | Very high demand, well established |
| Learning curve | Moderate (requires JS/TS knowledge) | Moderate (requires Java/Python) |
The honest take: Playwright is the better choice for new projects in 2026 because of its speed, built-in tooling, and modern API. However, Selenium still dominates the job market in India and has a much larger existing ecosystem. If your goal is immediate employability, learn both — start with Playwright for your personal projects and understand Selenium for interviews.
18. Common Setup Errors and How to Fix Them?
Below are the error message , Root cause and Fixes you may faced during using Playwright with Typescript.
| Error message | Root cause | Fix |
| ‘playwright’ is not recognized as a command | Playwright not installed | Run npm ci or npm install inside your project folder |
| Error: browserType.launch: Executable doesn’t exist | Browsers not downloaded | Run: npx playwright install |
| Timeout 30000ms exceeded waiting for selector | Wrong locator or element not loading | Use –debug to inspect, check your locator with page.locator().highlight() |
| Cannot find module ‘@playwright/test’ | npm install not run | Run: npm install or npm ci |
| TypeScript error: Property X does not exist | Type mismatch or missing import | Check your import statements and tsconfig.json |
| error TS2307: Cannot find module | tsconfig paths not configured | Check tsconfig.json — ensure paths and baseUrl are set correctly |
| net::ERR_CONNECTION_REFUSED | Wrong baseURL or server not running | Check baseURL in playwright.config.ts, verify server is running |
| Test is flaky — passes sometimes, fails others | Race condition in app or test | Use Playwright’s built-in waits; never use page.waitForTimeout() |
| EACCES permission error on npm install | Wrong npm directory permissions | Fix npm permissions or use nvm to manage Node.js versions |
19. Frequently Asked Questions
Is Playwright free to use?
Yes, completely. Playwright is open-source and released under the Apache 2.0 licence. There is no paid version, no feature gating, and no usage limits.
Can I use Playwright with JavaScript instead of TypeScript?
Yes, Playwright fully supports JavaScript. However, Playwright with TypeScript is strongly recommended for any serious project. The type safety and IDE support benefits compound significantly as your test suite grows.
Does Playwright work on Windows?
Yes. Playwright fully supports Windows 10 and Windows 11. The setup process is identical — install Node.js from nodejs.org, run npm init playwright@latest, and you are ready.
How is Playwright different from Cypress?
Both are modern browser automation frameworks. Key differences: Playwright supports multiple browsers (Chromium, Firefox, WebKit) while Cypress’s Firefox and WebKit support is more limited. Playwright can test multiple tabs and origins in a single test; Cypress has historically had restrictions here. Playwright uses async/await throughout; Cypress uses a custom chaining syntax. Playwright has better support for API testing, mobile testing, and CI integration out of the box.
Can I use Playwright with Jest or Mocha?
Playwright has its own built-in test runner (@playwright/test) which is the strongly recommended approach. It integrates natively with Playwright’s fixtures, parallel execution, and reporting. While it is technically possible to use Playwright’s browser APIs with Jest or Mocha, you lose most of the framework’s power. Use the built-in test runner.
How do I update Playwright to the latest version?
npm install @playwright/test@latest
npx playwright install # Update browser binaries to match
Is Playwright suitable for beginners?
Yes. Playwright’s CLI makes setup trivial, the official documentation is excellent, and the auto-waiting features mean you do not need to understand complex timing concepts to write reliable tests. The main prerequisite is basic JavaScript or TypeScript knowledge.
20. What to Learn Next
Now that your Playwright with TypeScript setup is complete and you have written your first tests, here is the recommended learning path to take your skills to the next level:
- Playwright Config Deep Dive — understand every option in playwright.config.ts (read our detailed guide on qatribe.in)
- Advanced Locators — getByRole(), filter(), locator chaining, and when to use data-testid
- Fixtures in Playwright — create reusable setup and teardown logic that is shared across tests
- API Testing with Playwright — test your backend APIs and combine API setup with UI tests
- Visual regression testing — use Playwright’s screenshot comparison to catch unintended UI changes
- Authentication patterns — use storageState to log in once and share the session across all tests
- Parallel execution and sharding — run your suite across multiple CI machines for maximum speed
- Allure reporting — generate rich, interactive test reports beyond the built-in HTML reporter
Summary:
In this complete Playwright with TypeScript setup guide, you learned how to install Node.js and create a new project, use the Playwright CLI to scaffold a full TypeScript project with browser downloads included, configure playwright.config.ts with the right settings for local development and CI/CD, write clean TypeScript tests using semantic locators and retry-capable assertions, structure your code professionally with the Page Object Model, run tests across multiple browsers and mobile device viewports, debug failures using the Trace Viewer and Playwright Inspector, and integrate your tests into a GitHub Actions CI/CD pipeline.
Playwright with TypeScript is the most productive browser automation setup available in 202. Its auto-waiting, excellent debugging tools, and first-class TypeScript support make it faster to write tests and faster to fix them when they fail.
If this guide helped you, bookmark qatribe.in and check out the next post in this series: our complete deep-dive into every playwright.config.ts option — including how to configure it for production use, multiple environments, and advanced CI/CD scenarios.
External Links for reference :
Playwright official documentation
Playwright GitHub repository
🔥 Continue Your Learning Journey
Want to go beyond Playwright with Typescript setup and crack interviews faster? Check these hand-picked guides:
👉 🚀 Master TestNG Framework (Enterprise Level)
Build scalable automation frameworks with CI/CD, parallel execution, and real-world architecture
➡️ Read: TestNG Automation Framework – Complete Architect Guide
👉 🧠 Learn Cucumber (BDD from Scratch to Advanced)
Understand Gherkin, step definitions, and real-world BDD framework design
➡️ Read: Cucumber Automation Framework – Beginner to Advanced Guide
👉 🔐 API Authentication Made Simple
Master JWT, OAuth, Bearer Tokens with real API testing examples
➡️ Read: Ultimate API Authentication Guide
👉 ⚡ Crack Playwright Interviews (2026 Ready)
Top real interview questions with answers and scenarios
➡️ Read: Playwright Interview Questions Guide
[…] For detailed post , go through Playwright with TypeScript Setup […]