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/loulanyue/awesome-claude-notes --skill e2e-testingO 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... Ocupações relacionadas SOC
Baseado na classificação ocupacional SOC
name e2e-testing description Playwright E2E testing patterns, Page Object Model, configuration, CI/CD integration, artifact management, and flaky test strategies. source_path skills/e2e-testing/SKILL.md origin ECC
E2E Testing Patterns
Comprehensive Playwright patterns for building stable, fast, and maintainable E2E test suites.
Test File Organization
tests/
├── e2e/
│ ├── auth/
│ │ ├── login.spec.ts
│ │ ├── logout.spec.ts
│ │ └── register.spec.ts
│ ├── features/
│ │ ├── browse.spec.ts
│ │ ├── search.spec.ts
│ │ └── create.spec.ts
│ └── api/
│ └── endpoints.spec.ts
├── fixtures/
│ ├── auth.ts
│ └── data.ts
└── playwright.config.ts
Page Object Model (POM)
import { Page , Locator } from '@playwright/test'
export class ItemsPage {
readonly page : Page
readonly searchInput : Locator
readonly :
:
( ) {
. = page
. = page. ( )
. = page. ( )
. = page. ( )
}
( ) {
. . ( )
. . ( )
}
( ) {
. . (query)
. . ( resp. (). ( ))
. . ( )
}
( ) {
. . ()
}
}
itemCards
Locator
readonly
createButton
Locator
constructor
page : Page
this
page
this
searchInput
locator
'[data-testid="search-input"]'
this
itemCards
locator
'[data-testid="item-card"]'
this
createButton
locator
'[data-testid="create-btn"]'
async
goto
await
this
page
goto
'/items'
await
this
page
waitForLoadState
'networkidle'
async
search
query : string
await
this
searchInput
fill
await
this
page
waitForResponse
resp =>
url
includes
'/api/search'
await
this
page
waitForLoadState
'networkidle'
async
getItemCount
return
await
this
itemCards
count
Test Structure import { test, expect } from '@playwright/test'
import { ItemsPage } from '../../pages/ItemsPage'
test.describe ('Item Search' , () => {
let itemsPage : ItemsPage
test.beforeEach (async ({ page }) => {
itemsPage = new ItemsPage (page)
await itemsPage.goto ()
})
test ('should search by keyword' , async ({ page }) => {
await itemsPage.search ('test' )
const count = await itemsPage.getItemCount ()
expect (count).toBeGreaterThan (0 )
await expect (itemsPage.itemCards .first ()).toContainText (/test/i )
await page.screenshot ({ path : 'artifacts/search-results.png' })
})
test ('should handle no results' , async ({ page }) => {
await itemsPage.search ('xyznonexistent123' )
await expect (page.locator ('[data-testid="no-results"]' )).toBeVisible ()
expect (await itemsPage.getItemCount ()).toBe (0 )
})
})
Playwright Configuration import { defineConfig, devices } from '@playwright/test'
export default defineConfig ({
testDir : './tests/e2e' ,
fullyParallel : true ,
forbidOnly : !!process.env .CI ,
retries : process.env .CI ? 2 : 0 ,
workers : process.env .CI ? 1 : undefined ,
reporter : [
['html' , { outputFolder : 'playwright-report' }],
['junit' , { outputFile : 'playwright-results.xml' }],
['json' , { outputFile : 'playwright-results.json' }]
],
use : {
baseURL : process.env .BASE_URL || 'http://localhost:3000' ,
trace : 'on-first-retry' ,
screenshot : 'only-on-failure' ,
video : 'retain-on-failure' ,
actionTimeout : 10000 ,
navigationTimeout : 30000 ,
},
projects : [
{ name : 'chromium' , use : { ...devices['Desktop Chrome' ] } },
{ name : 'firefox' , use : { ...devices['Desktop Firefox' ] } },
{ name : 'webkit' , use : { ...devices['Desktop Safari' ] } },
{ name : 'mobile-chrome' , use : { ...devices['Pixel 5' ] } },
],
webServer : {
command : 'npm run dev' ,
url : 'http://localhost:3000' ,
reuseExistingServer : !process.env .CI ,
timeout : 120000 ,
},
})
Flaky Test Patterns
Quarantine test ('flaky: complex search' , async ({ page }) => {
test.fixme (true , 'Flaky - Issue #123' )
})
test ('conditional skip' , async ({ page }) => {
test.skip (process.env .CI , 'Flaky in CI - Issue #123' )
})
Identify Flakiness npx playwright test tests/search.spec.ts --repeat-each=10
npx playwright test tests/search.spec.ts --retries=3
Common Causes & Fixes
await page.click ('[data-testid="button"]' )
await page.locator ('[data-testid="button"]' ).click ()
await page.waitForTimeout (5000 )
await page.waitForResponse (resp => resp.url ().includes ('/api/data' ))
await page.click ('[data-testid="menu-item"]' )
await page.locator ('[data-testid="menu-item"]' ).waitFor ({ state : 'visible' })
await page.waitForLoadState ('networkidle' )
await page.locator ('[data-testid="menu-item"]' ).click ()
Artifact Management
Screenshots await page.screenshot ({ path : 'artifacts/after-login.png' })
await page.screenshot ({ path : 'artifacts/full-page.png' , fullPage : true })
await page.locator ('[data-testid="chart"]' ).screenshot ({ path : 'artifacts/chart.png' })
Traces await browser.startTracing (page, {
path : 'artifacts/trace.json' ,
screenshots : true ,
snapshots : true ,
})
await browser.stopTracing ()
Video
use : {
video : 'retain-on-failure' ,
videosPath : 'artifacts/videos/'
}
CI/CD Integration
name: E2E Tests
on: [push , pull_request ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
env:
BASE_URL: ${{ vars.STAGING_URL }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
Test Report Template # E2E Test Report
**Date:** YYYY-MM-DD HH:MM
**Duration:** Xm Ys
**Status:** PASSING / FAILING
## Summary
- Total: X | Passed: Y (Z%) | Failed: A | Flaky: B | Skipped: C
## Failed Tests
### test-name
**File:** `tests/e2e/feature.spec.ts:45`
**Error:** Expected element to be visible
**Screenshot:** artifacts/failed.png
**Recommended Fix:** [description]
## Artifacts
- HTML Report: playwright-report/index.html
- Screenshots: artifacts/*.png
- Videos: artifacts/videos/* .webm
- Traces: artifacts/*.zip
Wallet / Web3 Testing test ('wallet connection' , async ({ page, context }) => {
await context.addInitScript (() => {
window .ethereum = {
isMetaMask : true ,
request : async ({ method }) => {
if (method === 'eth_requestAccounts' )
return ['0x1234567890123456789012345678901234567890' ]
if (method === 'eth_chainId' ) return '0x1'
}
}
})
await page.goto ('/' )
await page.locator ('[data-testid="connect-wallet"]' ).click ()
await expect (page.locator ('[data-testid="wallet-address"]' )).toContainText ('0x1234' )
})
Financial / Critical Flow Testing test ('trade execution' , async ({ page }) => {
test.skip (process.env .NODE_ENV === 'production' , 'Skip on production' )
await page.goto ('/markets/test-market' )
await page.locator ('[data-testid="position-yes"]' ).click ()
await page.locator ('[data-testid="trade-amount"]' ).fill ('1.0' )
const preview = page.locator ('[data-testid="trade-preview"]' )
await expect (preview).toContainText ('1.0' )
await page.locator ('[data-testid="confirm-trade"]' ).click ()
await page.waitForResponse (
resp => resp.url ().includes ('/api/trade' ) && resp.status () === 200 ,
{ timeout : 30000 }
)
await expect (page.locator ('[data-testid="trade-success"]' )).toBeVisible ()
})
原文
ナビゲーション