e2e-testing
Playwright E2E testing patterns, Page Object Model, configuration, CI/CD integration, artifact management, and flaky test strategies. Use when writing Playwright tests, structuring page objects, or fixing flaky E2E runs in CI.
DeepseekModel
官方收录技能
质量 优秀 · 90
v1.0.0
获取
https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-skills-e2e-testing-skill-md&format=skill
下载 .skill
标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name e2e-testing description Playwright E2E testing patterns, Page Object Model, configuration, CI/CD integration, artifact management, and flaky test strategies. Use when writing Playwright tests, structuring page objects, or fixing flaky E2E runs in CI. metadata {"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 itemCards : Locator readonly createButton : Locator constructor ( page : Page ) { this . page = page this . searchInput = page. locator ( '[data-testid="search-input"]' ) this . itemCards = page. locator ( '[data-testid="item-card"]' ) this . createButton = page. 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 (query) await this . page . waitForResponse ( resp => 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 code... }) test ( 'conditional skip' , async ({ page }) => { test. skip (process. env . CI , 'Flaky in CI - Issue #123' ) // test code... }) Identify Flakiness npx playwright test tests/search.spec.ts --repeat-each=10 npx playwright test tests/search.spec.ts --retries=3 Common Causes & Fixes Race conditions: // Bad: assumes element is ready await page. click ( '[data-testid="button"]' ) // Good: auto-wait locator await page. locator ( '[data-testid="button"]' ). click () Network timing: // Bad: arbitrary timeout await page. waitForTimeout ( 5000 ) // Good: wait for specific condition await page. waitForResponse ( resp => resp. url (). includes ( '/api/data' )) Animation timing: // Bad: click during animation await page. click ( '[data-testid="menu-item"]' ) // Good: wait for stability 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 , }) // ... test actions ... await browser. stopTracing () Video // In playwright.config.ts use : { video : 'retain-on-failure' , videosPath : 'artifacts/videos/' } CI/CD Integration # .github/workflows/e2e.yml 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 }) => { // Mock wallet provider 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 }) => { // Skip on production — real money 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' ) // Verify preview const preview = page. locator ( '[data-testid="trade-preview"]' ) await expect (preview). toContainText ( '1.0' ) // Confirm and wait for blockchain 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 () })
Agent 识别该技能的关键词,点击任意一个即可复制。
该技能未提供触发词。
下载的 .skill 包内含以下字段。
| 字段 | 说明 |
|---|---|
| format | 格式标识(skill/v1) |
| skill_id | 技能唯一 ID |
| name | 技能名称 |
| version | 版本号 |
| description | 技能描述 |
| category | 所属分类(数组) |
| trigger_words | 触发词列表 |
| tags | 标签列表 |
| source | 来源标识 |
| source_url | 来源链接(本页地址) |
| exported_at | 导出时间(每次下载生成) |
| system_prompt | 系统提示词正文 |
| model_config | 模型参数:provider / model / temperature / max_tokens / top_p |
| examples | 示例 |
| install_guide | 各平台导入说明(Coze / Dify / Claude / 自定义框架) |