Skip to main content Skills Marketplace Descubra e explore skills de IA criadas pela comunidade.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Copiar promptMostrar detalhes do prompt Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
npx skills add https://github.com/PramodDutta/qaskills --skill playwright-enhancedO comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Baixar Zip Baixando... Mais deste repositório Use when publishing SEO blog articles to qaskills.sh, e.g. "publish today's articles", "daily SEO batch", "write 10 articles from keyword research", "add a blog post", or any request that creates files under packages/web/src/app/blog/posts.
secure-test-data-engineer Generate test data from the schemas you already have. Read OpenAPI, JSON Schema, SQL DDL, or TypeScript models and produce deterministic factories, boundary and negative cases, relational datasets with valid foreign keys, cleanup scripts, and PII-safe synthetic data. Production records never leave the machine.
Analyze a git diff, map affected risks, select the tests that matter, detect coverage gaps on changed lines, run configurable quality gates, and produce a go/no-go release report with cited evidence. Recommends only; never merges or deploys.
Ocupações relacionadas SOC
Baseado na classificação ocupacional SOC
name Playwright Enhanced description Advanced Playwright automation with auto-detection, custom fixtures, trace debugging, visual testing, mobile emulation, and production-grade test architecture. version 1.0.0 author thetestingacademy license MIT tags ["playwright","e2e","advanced","fixtures","trace-viewer","visual-testing","mobile-testing"] testingTypes ["e2e","visual"] frameworks ["playwright"] languages ["typescript","javascript"] domains ["web","mobile"] agents ["claude-code","cursor","github-copilot","windsurf","codex","aider","continue","cline","zed","bolt"]
Playwright Enhanced Skill
You are an expert QA automation engineer specializing in advanced Playwright patterns. When asked to write or enhance Playwright tests, follow these production-grade instructions.
Advanced Configuration
Multi-Environment Setup
import { defineConfig, devices } from '@playwright/test' ;
const env = process.env .TEST_ENV || 'local' ;
const environments = {
local : {
baseURL : 'http://localhost:3000' ,
apiURL : 'http://localhost:8080' ,
},
staging : {
baseURL : 'https://staging.example.com' ,
apiURL : 'https://api-staging.example.com' ,
},
production : {
baseURL : 'https://example.com' ,
apiURL : 'https://api.example.com' ,
},
};
export default defineConfig ({
testDir : './tests' ,
fullyParallel : true ,
forbidOnly : !!process.env .CI ,
retries : process.env .CI ? 2 : 0 ,
workers : process.env .CI ? 1 : undefined ,
reporter : [
['html' , { : , : }],
[ , { : }],
[ , { : }],
process. . ? [ ] : [ ],
],
: {
: environments[env]. ,
: ,
: ,
: ,
: ,
: ,
},
: [
{ : , : },
{
: ,
: { ...devices[ ] },
: [ ],
},
{
: ,
: { ...devices[ ] },
: [ ],
},
{
: ,
: { ...devices[ ] },
: [ ],
},
{
: ,
: { ...devices[ ] },
: [ ],
},
{
: ,
: { ...devices[ ] },
: [ ],
},
{
: ,
: { ...devices[ ] },
: [ ],
},
],
: env === ? {
: ,
: ,
: !process. . ,
: ,
} : ,
});
open
'never'
outputFolder
'test-results/html'
'json'
outputFile
'test-results/results.json'
'junit'
outputFile
'test-results/junit.xml'
env
CI
'github'
'list'
use
baseURL
baseURL
trace
'retain-on-failure'
screenshot
'only-on-failure'
video
'retain-on-failure'
actionTimeout
15000
navigationTimeout
30000
projects
name
'setup'
testMatch
/.*\.setup\.ts/
name
'chromium'
use
'Desktop Chrome'
dependencies
'setup'
name
'firefox'
use
'Desktop Firefox'
dependencies
'setup'
name
'webkit'
use
'Desktop Safari'
dependencies
'setup'
name
'mobile-chrome'
use
'Pixel 5'
dependencies
'setup'
name
'mobile-safari'
use
'iPhone 13'
dependencies
'setup'
name
'tablet'
use
'iPad Pro'
dependencies
'setup'
webServer
'local'
command
'npm run dev'
url
'http://localhost:3000'
reuseExistingServer
env
CI
timeout
120000
undefined
Advanced Custom Fixtures
import { test as base, Page } from '@playwright/test' ;
import { LoginPage } from '../pages/login.page' ;
import { DashboardPage } from '../pages/dashboard.page' ;
type MyFixtures = {
loginPage : LoginPage ;
dashboardPage : DashboardPage ;
authenticatedPage : Page ;
adminPage : Page ;
mockApi : MockApiHelper ;
testData : TestDataFactory ;
};
export const test = base.extend <MyFixtures >({
loginPage : async ({ page }, use) => {
await use (new LoginPage (page));
},
dashboardPage : async ({ page }, use) => {
await use (new DashboardPage (page));
},
authenticatedPage : async ({ browser }, use) => {
const context = await browser.newContext ({
storageState : 'playwright/.auth/user.json' ,
});
const page = await context.newPage ();
await use (page);
await context.close ();
},
adminPage : async ({ browser }, use) => {
const context = await browser.newContext ({
storageState : 'playwright/.auth/admin.json' ,
});
const page = await context.newPage ();
await use (page);
await context.close ();
},
mockApi : async ({ page }, use) => {
const helper = new MockApiHelper (page);
await use (helper);
},
testData : async ({}, use) => {
const factory = new TestDataFactory ();
await use (factory);
await factory.cleanup ();
},
});
export { expect } from '@playwright/test' ;
Advanced Page Object Pattern
import { Page , Locator , expect } from '@playwright/test' ;
export abstract class BasePage {
protected page : Page ;
constructor (page : Page ) {
this .page = page;
}
async navigate (path : string ): Promise <void > {
await this .page .goto (path);
}
async waitForPageLoad (): Promise <void > {
await this .page .waitForLoadState ('networkidle' );
}
async waitForElement (selector : string , timeout = 10000 ): Promise <Locator > {
return this .page .waitForSelector (selector, { timeout });
}
async takeScreenshot (name : string ): Promise <void > {
await this .page .screenshot ({
path : `screenshots/${name} .png` ,
fullPage : true ,
});
}
async scrollToElement (locator : Locator ): Promise <void > {
await locator.scrollIntoViewIfNeeded ();
}
async typeWithDelay (locator : Locator , text : string , delay = 100 ): Promise <void > {
await locator.type (text, { delay });
}
async selectDropdownOption (locator : Locator , option : string ): Promise <void > {
await locator.click ();
await this .page .getByRole ('option' , { name : option }).click ();
}
async uploadFile (locator : Locator , filePath : string ): Promise <void > {
await locator.setInputFiles (filePath);
}
async waitForApiResponse (urlPattern : string | RegExp ): Promise <void > {
await this .page .waitForResponse ((response ) =>
(typeof urlPattern === 'string'
? response.url ().includes (urlPattern)
: urlPattern.test (response.url ())) && response.status () === 200
);
}
}
import { Page , Locator , expect } from '@playwright/test' ;
import { BasePage } from './base.page' ;
export class DashboardPage extends BasePage {
readonly heading : Locator ;
readonly userMenu : Locator ;
readonly notificationBell : Locator ;
readonly searchInput : Locator ;
constructor (page : Page ) {
super (page);
this .heading = page.getByRole ('heading' , { name : 'Dashboard' });
this .userMenu = page.getByRole ('button' , { name : /user menu/i });
this .notificationBell = page.getByTestId ('notification-bell' );
this .searchInput = page.getByPlaceholder ('Search...' );
}
async goto (): Promise <void > {
await this .navigate ('/dashboard' );
await this .expectToBeLoaded ();
}
async expectToBeLoaded (): Promise <void > {
await expect (this .heading ).toBeVisible ();
await this .waitForPageLoad ();
}
async searchFor (query : string ): Promise <void > {
await this .searchInput .fill (query);
await this .searchInput .press ('Enter' );
await this .waitForApiResponse ('/api/search' );
}
async openUserMenu (): Promise <void > {
await this .userMenu .click ();
}
async getNotificationCount (): Promise <number > {
const badge = this .notificationBell .locator ('.badge' );
const text = await badge.textContent ();
return parseInt (text || '0' , 10 );
}
async expectWelcomeMessage (username : string ): Promise <void > {
const message = this .page .getByText (`Welcome, ${username} ` );
await expect (message).toBeVisible ();
}
}
API Mocking Strategies
import { Page , Route } from '@playwright/test' ;
export class MockApiHelper {
constructor (private page : Page ) {}
async mockSuccess (endpoint : string , data : any ): Promise <void > {
await this .page .route (endpoint, async (route : Route ) => {
await route.fulfill ({
status : 200 ,
contentType : 'application/json' ,
body : JSON .stringify (data),
});
});
}
async mockError (endpoint : string , status : number , message : string ): Promise <void > {
await this .page .route (endpoint, async (route : Route ) => {
await route.fulfill ({
status,
contentType : 'application/json' ,
body : JSON .stringify ({ error : message }),
});
});
}
async mockDelay (endpoint : string , delay : number ): Promise <void > {
await this .page .route (endpoint, async (route : Route ) => {
await new Promise ((resolve ) => setTimeout (resolve, delay));
await route.continue ();
});
}
async interceptAndModify (endpoint : string , modifier : (data : any ) => any ): Promise <void > {
await this .page .route (endpoint, async (route : Route ) => {
const response = await route.fetch ();
const json = await response.json ();
const modified = modifier (json);
await route.fulfill ({
response,
body : JSON .stringify (modified),
});
});
}
}
test ('should handle API error gracefully' , async ({ page, mockApi }) => {
await mockApi.mockError ('/api/users' , 500 , 'Internal Server Error' );
await page.goto ('/users' );
await expect (page.getByText ('Something went wrong' )).toBeVisible ();
});
Visual Regression Testing test.describe ('Visual regression' , () => {
test ('homepage snapshot desktop' , async ({ page }) => {
await page.goto ('/' );
await page.waitForLoadState ('networkidle' );
await expect (page).toHaveScreenshot ('homepage-desktop.png' , {
fullPage : true ,
animations : 'disabled' ,
maxDiffPixels : 100 ,
});
});
test ('homepage snapshot mobile' , async ({ page }) => {
await page.setViewportSize ({ width : 375 , height : 667 });
await page.goto ('/' );
await expect (page).toHaveScreenshot ('homepage-mobile.png' , {
fullPage : true ,
animations : 'disabled' ,
});
});
test ('component snapshot' , async ({ page }) => {
await page.goto ('/components/button' );
const button = page.getByRole ('button' , { name : 'Primary' });
await expect (button).toHaveScreenshot ('button-primary.png' );
});
test ('dark mode snapshot' , async ({ page }) => {
await page.emulateMedia ({ colorScheme : 'dark' });
await page.goto ('/' );
await expect (page).toHaveScreenshot ('homepage-dark.png' , {
fullPage : true ,
});
});
});
Mobile Testing Patterns test.describe ('Mobile-specific tests' , () => {
test.use ({ ...devices['iPhone 13' ] });
test ('should handle mobile navigation' , async ({ page }) => {
await page.goto ('/' );
const menuButton = page.getByRole ('button' , { name : 'Menu' });
await expect (menuButton).toBeVisible ();
await menuButton.click ();
await page.getByRole ('link' , { name : 'Products' }).click ();
await expect (page).toHaveURL ('/products' );
});
test ('should handle touch gestures' , async ({ page }) => {
await page.goto ('/gallery' );
const image = page.getByTestId ('gallery-image' );
await image.dragTo (image, {
sourcePosition : { x : 200 , y : 100 },
targetPosition : { x : 50 , y : 100 },
});
await expect (page.getByTestId ('image-2' )).toBeVisible ();
});
test ('should adapt to orientation changes' , async ({ page }) => {
await page.goto ('/' );
await page.setViewportSize ({ width : 375 , height : 667 });
await expect (page.getByTestId ('mobile-menu' )).toBeVisible ();
await page.setViewportSize ({ width : 667 , height : 375 });
await expect (page.getByTestId ('desktop-menu' )).toBeVisible ();
});
});
Network Manipulation test.describe ('Network conditions' , () => {
test ('should handle slow 3G connection' , async ({ page, context }) => {
await context.route ('**/*' , async (route) => {
await new Promise ((resolve ) => setTimeout (resolve, 500 ));
await route.continue ();
});
await page.goto ('/' );
await expect (page.getByTestId ('loading-spinner' )).toBeVisible ();
await expect (page.getByRole ('heading' )).toBeVisible ({ timeout : 20000 });
});
test ('should handle offline mode' , async ({ page, context }) => {
await page.goto ('/' );
await context.setOffline (true );
await page.reload ();
await expect (page.getByText ('You are offline' )).toBeVisible ();
await context.setOffline (false );
await page.reload ();
await expect (page.getByRole ('heading' )).toBeVisible ();
});
});
Advanced Trace Debugging test ('with detailed trace' , async ({ page }) => {
await page.context ().tracing .start ({
screenshots : true ,
snapshots : true ,
sources : true ,
});
await test.step ('Navigate to login page' , async () => {
await page.goto ('/login' );
});
await test.step ('Fill login form' , async () => {
await page.fill ('#email' , 'user@example.com' );
await page.fill ('#password' , 'password123' );
});
await test.step ('Submit form' , async () => {
await page.click ('button[type="submit"]' );
});
await test.step ('Verify dashboard loaded' , async () => {
await expect (page.getByRole ('heading' )).toHaveText ('Dashboard' );
});
await page.context ().tracing .stop ({ path : 'trace.zip' });
});
Parallel Test Execution Optimization
import { test, expect } from './fixtures' ;
test.describe .configure ({ mode : 'parallel' });
test.describe ('Parallel safe tests' , () => {
test ('test 1 with isolated data' , async ({ page, testData }) => {
const user = await testData.createUniqueUser ();
await page.goto (`/users/${user.id} ` );
});
test ('test 2 with isolated data' , async ({ page, testData }) => {
const user = await testData.createUniqueUser ();
await page.goto (`/users/${user.id} ` );
});
});
test.describe .configure ({ mode : 'serial' });
test.describe ('Serial tests (order matters)' , () => {
let orderId : string ;
test ('step 1: create order' , async ({ page }) => {
orderId = 'ORDER-123' ;
});
test ('step 2: process order' , async ({ page }) => {
await page.goto (`/orders/${orderId} ` );
});
});
Performance Monitoring import { chromium } from '@playwright/test' ;
test ('measure page performance' , async ({ page }) => {
await page.goto ('/' );
const metrics = await page.evaluate (() => {
const perfData = window .performance .timing ;
return {
domContentLoaded : perfData.domContentLoadedEventEnd - perfData.navigationStart ,
loadComplete : perfData.loadEventEnd - perfData.navigationStart ,
firstPaint : performance.getEntriesByType ('paint' )[0 ]?.startTime || 0 ,
};
});
console .log ('Performance metrics:' , metrics);
expect (metrics.domContentLoaded ).toBeLessThan (2000 );
expect (metrics.loadComplete ).toBeLessThan (5000 );
});
Best Practices
Use test.step() for readability -- Organize complex tests into logical steps.
Implement custom fixtures -- Share setup logic and state across tests.
Enable trace on failure -- Visual debugging is invaluable.
Use auto-waiting locators -- getByRole and getByText are resilient.
Mock APIs for speed -- Don't rely on real backends for fast feedback.
Test across browsers -- Cross-browser issues are real.
Validate with screenshots -- Visual regression catches CSS bugs.
Isolate test data -- Each test should create its own data.
Use serial mode wisely -- Parallelize when possible.
Monitor performance -- Track load times as part of tests.
Anti-Patterns to Avoid
Not using Page Object Model -- Duplicating selectors everywhere.
Hardcoded waits -- Use auto-waiting instead.
Testing in one browser only -- Cross-browser bugs are common.
Ignoring flaky tests -- Fix them or delete them.
Not using fixtures -- Copy-pasting setup code.
No visual regression -- UI bugs slip through.
Testing against production -- Always use test environments.
Shared state between tests -- Tests must be independent.
Not recording traces -- Debugging is much harder.
Ignoring mobile -- Mobile users are a huge segment.
Playwright is powerful. Use its advanced features to build robust, maintainable test suites that catch bugs before production.