Playwright Automation with TypeScript: A Modern Approach
November 20, 2024
Playwright Automation with TypeScript: A Modern Approach
Playwright has revolutionized browser automation with its powerful API and excellent TypeScript support. Let's explore why this combination is a game-changer for modern test automation.
Why Playwright + TypeScript?
The combination of Playwright and TypeScript offers several compelling advantages:
- Type Safety: Catch errors at compile time, not runtime
- IntelliSense: Get intelligent code completion in your IDE
- Refactoring: Safely rename and restructure your test code
- Better Tooling: Enhanced debugging and code navigation
Getting Started
First, install Playwright with TypeScript support:
bash1npm init playwright@latest
This command sets up a complete TypeScript project with:
- Playwright test runner
- TypeScript configuration
- Example tests
- GitHub Actions workflow
Writing Your First Test
Here's a simple but powerful test example:
typescript1import { test, expect } from '@playwright/test'; 2 3test('homepage has correct title', async ({ page }) => { 4 await page.goto('https://example.com'); 5 6 // Type-safe selectors with IntelliSense 7 const title = await page.title(); 8 expect(title).toContain('Example Domain'); 9 10 // Auto-waiting and retry logic built-in 11 await expect(page.locator('h1')).toBeVisible(); 12});
Advanced Patterns
Page Object Model with TypeScript
Create type-safe page objects:
typescript1export class LoginPage { 2 constructor(private page: Page) {} 3 4 readonly emailInput = this.page.locator('#email'); 5 readonly passwordInput = this.page.locator('#password'); 6 readonly submitButton = this.page.locator('button[type="submit"]'); 7 8 async login(email: string, password: string): Promise<void> { 9 await this.emailInput.fill(email); 10 await this.passwordInput.fill(password); 11 await this.submitButton.click(); 12 } 13}
Custom Fixtures
Extend Playwright's capabilities with typed fixtures:
typescript1import { test as base } from '@playwright/test'; 2import { LoginPage } from './pages/login-page'; 3 4type CustomFixtures = { 5 loginPage: LoginPage; 6}; 7 8export const test = base.extend<CustomFixtures>({ 9 loginPage: async ({ page }, use) => { 10 await use(new LoginPage(page)); 11 }, 12});
Best Practices
1. Use Strict Selectors
typescript1// Good - specific and maintainable 2await page.locator('button[data-testid="submit-button"]').click(); 3 4// Avoid - fragile and unclear 5await page.locator('div > button:nth-child(3)').click();
2. Leverage Auto-Waiting
Playwright automatically waits for elements to be actionable:
typescript1// No need for manual waits! 2await page.locator('#button').click(); 3// Playwright waits for element to be visible, enabled, and stable
3. Use TypeScript Enums for Test Data
typescript1enum UserRole { 2 Admin = 'admin', 3 User = 'user', 4 Guest = 'guest', 5} 6 7test('admin can access dashboard', async ({ page }) => { 8 await loginAs(page, UserRole.Admin); 9 await expect(page.locator('#admin-panel')).toBeVisible(); 10});
Debugging TypeScript Tests
Playwright offers excellent debugging tools:
bash1# Debug with Playwright Inspector 2npx playwright test --debug 3 4# Generate trace files for post-mortem debugging 5npx playwright test --trace on
Real-World Example: E2E Shopping Flow
typescript1test.describe('Shopping Cart Flow', () => { 2 test('user can complete purchase', async ({ page }) => { 3 // Navigate and add product 4 await page.goto('/products'); 5 await page.locator('[data-product-id="123"]').click(); 6 await page.locator('button:has-text("Add to Cart")').click(); 7 8 // Verify cart update 9 await expect(page.locator('.cart-count')).toHaveText('1'); 10 11 // Complete checkout 12 await page.locator('.cart-icon').click(); 13 await page.locator('button:has-text("Checkout")').click(); 14 15 // Fill shipping info with type-safe data 16 await page.fill('#email', 'customer@example.com'); 17 await page.fill('#card-number', '4242424242424242'); 18 19 // Submit and verify 20 await page.locator('button:has-text("Place Order")').click(); 21 await expect(page.locator('.success-message')).toBeVisible(); 22 }); 23});
Performance Optimization
Parallel Execution
typescript1// playwright.config.ts 2export default defineConfig({ 3 workers: process.env.CI ? 2 : undefined, 4 fullyParallel: true, 5});
Test Sharding for CI/CD
bash1# Split tests across multiple machines 2npx playwright test --shard=1/3 3npx playwright test --shard=2/3 4npx playwright test --shard=3/3
Conclusion
Playwright with TypeScript provides a powerful, type-safe approach to browser automation. The combination offers:
ā Compile-time error checking ā Excellent IDE support ā Maintainable test code ā Fast and reliable test execution
Whether you're building end-to-end tests, scraping websites, or automating browser tasks, Playwright + TypeScript is an excellent choice for modern development workflows.
Next Steps
- Explore Playwright's visual regression testing
- Integrate with CI/CD pipelines
- Learn about API testing with Playwright
- Master advanced selectors and locators
Happy automating! š
Was this helpful?
0
0
0
Comments (0)
Join the Discussion
Sign in to share your thoughts and connect with other readers
Related Articles
Playwright Automation with Python: Simplicity Meets Power
Learn how to leverage Playwright with Python for efficient browser automation. Discover Pythonic patterns, async/await usage, and practical testing strategies.
Getting Started with Playwright Automation: A Beginner's Guide
New to test automation? Learn the fundamentals of Playwright from installation to writing your first automated tests. Perfect for beginners starting their automation journey.
Selenium with Python: Complete Automation Guide
Master web automation with Selenium and Python. Learn from basics to advanced techniques including waits, page objects, and parallel testing strategies.