Source profileQuality 64/100Review permissions

affaan-m/ECC/docs/zh-CN/skills/e2e-testing/SKILL.md

e2e-testing

Use it for testing tasks; the detail page covers purpose, installation, and practical steps.

Source repository stars
234,327
Declared platforms
0
Static risk flags
2
Last source update
2026-07-27
Source checked
2026-07-28

Decision brief

What it does—and where it fits

用于构建稳定、快速且可维护的 E2E 测试套件的全面 Playwright 模式。

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/affaan-m/ECC --skill "docs/zh-CN/skills/e2e-testing"
    Safe inspection promptEditorial

    Inspect the Agent Skill "e2e-testing" from https://github.com/affaan-m/ECC/blob/4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38/docs/zh-CN/skills/e2e-testing/SKILL.md at commit 4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      测试文件组织

      Review the “测试文件组织” section in the pinned source before continuing.

      Review and apply the “测试文件组织” source section.
    2. 02

      页面对象模型 (POM)

      Review the “页面对象模型 (POM)” section in the pinned source before continuing.

      Review and apply the “页面对象模型 (POM)” source section.
    3. 03

      测试结构

      Review the “测试结构” section in the pinned source before continuing.

      Review and apply the “测试结构” source section.
    4. 04

      Playwright 配置

      Review the “Playwright 配置” section in the pinned source before continuing.

      Review and apply the “Playwright 配置” source section.
    5. 05

      不稳定测试模式

      Review the “不稳定测试模式” section in the pinned source before continuing.

      Review and apply the “不稳定测试模式” source section.

    Permission review

    Static risk signals and limitations

    Network access

    medium · line 111

    The documentation includes network, browsing, or remote request actions.

    baseURL: process.env.BASE_URL || 'http://localhost:3000',

    Network access

    medium · line 126

    The documentation includes network, browsing, or remote request actions.

    url: 'http://localhost:3000',

    Runs scripts

    medium · line 152

    The documentation asks the agent to run terminal commands or scripts.

    npx playwright test tests/search.spec.ts --repeat-each=10

    Runs scripts

    medium · line 153

    The documentation asks the agent to run terminal commands or scripts.

    npx playwright test tests/search.spec.ts --retries=3

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score64/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars234,327SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    affaan-m/ECC
    Skill path
    docs/zh-CN/skills/e2e-testing/SKILL.md
    Commit
    4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38
    License
    MIT
    Collected
    2026-07-28
    Default branch
    main
    View the original SKILL.md

    E2E 测试模式

    用于构建稳定、快速且可维护的 E2E 测试套件的全面 Playwright 模式。

    测试文件组织

    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
    

    页面对象模型 (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()
      }
    }
    

    测试结构

    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 配置

    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,
      },
    })
    

    不稳定测试模式

    隔离

    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...
    })
    

    识别不稳定性

    npx playwright test tests/search.spec.ts --repeat-each=10
    npx playwright test tests/search.spec.ts --retries=3
    

    常见原因与修复

    竞态条件:

    // Bad: assumes element is ready
    await page.click('[data-testid="button"]')
    
    // Good: auto-wait locator
    await page.locator('[data-testid="button"]').click()
    

    网络时序:

    // Bad: arbitrary timeout
    await page.waitForTimeout(5000)
    
    // Good: wait for specific condition
    await page.waitForResponse(resp => resp.url().includes('/api/data'))
    

    动画时序:

    // 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()
    

    产物管理

    截图

    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' })
    

    跟踪记录

    await browser.startTracing(page, {
      path: 'artifacts/trace.json',
      screenshots: true,
      snapshots: true,
    })
    // ... test actions ...
    await browser.stopTracing()
    

    视频

    // In playwright.config.ts
    use: {
      video: 'retain-on-failure',
      videosPath: 'artifacts/videos/'
    }
    

    CI/CD 集成

    # .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
    

    测试报告模板

    # E2E 测试报告
    
    **日期:** YYYY-MM-DD HH:MM
    **持续时间:** Xm Ys
    **状态:** 通过 / 失败
    
    ## 概要
    - 总计:X | 通过:Y (Z%) | 失败:A | 不稳定:B | 跳过:C
    
    ## 失败的测试
    
    ### test-name
    **文件:** `tests/e2e/feature.spec.ts:45`
    **错误:** 期望元素可见
    **截图:** artifacts/failed.png
    **建议修复:** [description]
    
    ## 产物
    - HTML 报告:playwright-report/index.html
    - 截图:artifacts/*.png
    - 视频:artifacts/videos/*.webm
    - 追踪文件:artifacts/*.zip
    

    钱包 / Web3 测试

    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')
    })
    

    金融 / 关键流程测试

    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()
    })
    

    Alternatives

    Compare before choosing