Token导航 LogoToken导航TokenDH.com
研究检索操作浏览器github未标认证来源可访问许可证需确认审计通过

e2e-testing端到端测试

Agent Skill

用于辅助测试设计、自动化测试、用例整理和回归验证。它适合让 Agent 编写单元测试、端到端测试、测试计划或根据失败日志定位问题。使用时需要确认项目测试框架、运行命令和夹具数据,避免为了通过测试而改坏真实逻辑;涉及浏览器或外部服务时,应区分本地模拟、测试环境和生产环境。

总安装

35,280

周安装

1,473

GitHub Stars

8

下载量

12,360
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:e2e-testing(端到端测试)
来源仓库:https://github.com/hieutrtr/ai1-skills
仓库路径:skills/e2e-testing
安装命令:
npx skills add https://github.com/hieutrtr/ai1-skills --skill e2e-testing
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/hieutrtr/ai1-skills --skill e2e-testing

简介

与 Playwright 一起对全栈 Python/React 应用程序进行端到端测试模式。

  • 涵盖测试结构、页面对象模型、选择器策略(data-testid > 角色 > 标签)以及可靠的跨浏览器测试的等待策略
  • 包括身份验证状态重用以避免重复登录、通过 API 帮助程序进行测试数据管理以及针对不稳定测试的调试技术
  • 提供 CI 集成示例、用于身份验证的固定装置设置以及测试、页面和定位器的命名约定
  • 支持 Chromium、Firefox 和 WebKit 浏览器,具有显式等待条件和网络感知测试执行

SKILL.md

E2E Testing

When to Use

Activate this skill when:

  • Writing E2E tests for complete user workflows (login, CRUD operations, multi-page flows)
  • Creating critical path regression tests that validate the full stack
  • Testing cross-browser compatibility (Chromium, Firefox, WebKit)
  • Validating authentication flows end-to-end
  • Testing file upload/download workflows
  • Writing smoke tests for deployment verification

Do NOT use this skill for:

  • React component unit tests (use react-testing-patterns)
  • Python backend unit/integration tests (use pytest-patterns)
  • TDD workflow enforcement (use tdd-workflow)
  • API contract testing without a browser (use pytest-patterns with httpx)

Instructions

Test Structure

e2e/
├── playwright.config.ts         # Global Playwright configuration
├── fixtures/
│   ├── auth.fixture.ts          # Authentication state setup
│   └── test-data.fixture.ts     # Test data creation/cleanup
├── pages/
│   ├── base.page.ts             # Base page object with shared methods
│   ├── login.page.ts            # Login page object
│   ├── users.page.ts            # Users list page object
│   └── user-detail.page.ts     # User detail page object
├── tests/
│   ├── auth/
│   │   ├── login.spec.ts
│   │   └── logout.spec.ts
│   ├── users/
│   │   ├── create-user.spec.ts
│   │   ├── edit-user.spec.ts
│   │   └── list-users.spec.ts
│   └── smoke/
│       └── critical-paths.spec.ts
└── utils/
    ├── api-helpers.ts           # Direct API calls for test setup
    └── test-constants.ts        # Shared constants

Naming conventions:

  • Test files: <feature>.spec.ts
  • Page objects: <page-name>.page.ts
  • Fixtures: <concern>.fixture.ts
  • Test names: human-readable sentences describing the user action and expected outcome

Page Object Model

Every page gets a page object class that encapsulates selectors and actions. Tests never interact with selectors directly.

Base page object:

// e2e/pages/base.page.ts
import { type Page, type Locator } from "@playwright/test";

export abstract class BasePage {
  constructor(protected readonly page: Page) {}

  /** Navigate to the page's URL. */
  abstract goto(): Promise<void>;

  /** Wait for the page to be fully loaded. */
  async waitForLoad(): Promise<void> {
    await this.page.waitForLoadState("networkidle");
  }

  /** Get a toast/notification message. */
  get toast(): Locator {
    return this.page.getByRole("alert");
  }

  /** Get the page heading. */
  get heading(): Locator {
    return this.page.getByRole("heading", { level: 1 });
  }
}

Concrete page object:

// e2e/pages/users.page.ts
import { type Page, type Locator } from "@playwright/test";
import { BasePage } from "./base.page";

export class UsersPage extends BasePage {
  // ─── Locators ─────────────────────────────────────────
  readonly createButton: Locator;
  readonly searchInput: Locator;
  readonly userTable: Locator;

  constructor(page: Page) {
    super(page);
    this.createButton = page.getByTestId("create-user-btn");
    this.searchInput = page.getByRole("searchbox", { name: /search users/i });
    this.userTable = page.getByRole("table");
  }

  // ─── Actions ──────────────────────────────────────────
  async goto(): Promise<void> {
    await this.page.goto("/users");
    await this.waitForLoad();
  }

  async searchFor(query: string): Promise<void> {
    await this.searchInput.fill(query);
    // Wait for search results to update (debounced)
    await this.page.waitForResponse("**/api/v1/users?*");
  }

  async clickCreateUser(): Promise<void> {
    await this.createButton.click();
  }

  async getUserRow(email: string): Promise<Locator> {
    return this.userTable.getByRole("row").filter({ hasText: email });
  }

  async getUserCount(): Promise<number> {
    // Subtract 1 for header row
    return (await this.userTable.getByRole("row").count()) - 1;
  }
}

Rules for page objects:

  • One page object per page or major UI section
  • Locators are public readonly properties
  • Actions are async methods
  • Page objects never contain assertions -- tests assert
  • Page objects handle waits internally after actions

Selector Strategy

Priority order (highest to lowest):

PrioritySelectorExampleWhen to Use
1data-testidgetByTestId("submit-btn")Interactive elements, dynamic content
2RolegetByRole("button", {name: /save/i})Buttons, links, headings, inputs
3LabelgetByLabel("Email")Form inputs with labels
4PlaceholdergetByPlaceholder("Search...")Search inputs
5TextgetByText("Welcome back")Static text content

NEVER use:

  • CSS selectors (.class-name, #id) -- brittle, break on styling changes
  • XPath (//div[@class="foo"]) -- unreadable, extremely brittle
  • DOM structure selectors (div > span:nth-child(2)) -- break on layout changes

Adding data-testid attributes:

// In React components -- add data-testid to interactive elements
<button data-testid="create-user-btn" onClick={handleCreate}>
  Create User
</button>

// Convention: kebab-case, descriptive
// Pattern: <action>-<entity>-<element-type>
// Examples: create-user-btn, user-email-input, delete-confirm-dialog

Wait Strategies

NEVER use hardcoded waits:

// BAD: Hardcoded wait -- flaky, slow
await page.waitForTimeout(3000);

// BAD: Sleep
await new Promise((resolve) => setTimeout(resolve, 2000));

Use explicit wait conditions:

// GOOD: Wait for a specific element to appear
await page.getByRole("heading", { name: "Dashboard" }).waitFor();

// GOOD: Wait for navigation
await page.waitForURL("/dashboard");

// GOOD: Wait for API response
await page.waitForResponse(
  (response) =>
    response.url().includes("/api/v1/users") && response.status() === 200,
);

// GOOD: Wait for network to settle
await page.waitForLoadState("networkidle");

// GOOD: Wait for element state
await page.getByTestId("submit-btn").waitFor({ state: "visible" });
await page.getByTestId("loading-spinner").waitFor({ state: "hidden" });

Auto-waiting: Playwright auto-waits for elements to be actionable before clicking, filling, etc. Explicit waits are needed only for assertions or complex state transitions.

Auth State Reuse

Avoid logging in before every test. Save auth state and reuse it.

Setup auth state once:

// e2e/fixtures/auth.fixture.ts
import { test as base } from "@playwright/test";
import path from "path";

const AUTH_STATE_PATH = path.resolve("e2e/.auth/user.json");

export const setup = base.extend({});

setup("authenticate", async ({ page }) => {
  // Perform real login
  await page.goto("/login");
  await page.getByLabel("Email").fill("testuser@example.com");
  await page.getByLabel("Password").fill("TestPassword123!");
  await page.getByRole("button", { name: /sign in/i }).click();

  // Wait for auth to complete
  await page.waitForURL("/dashboard");

  // Save signed-in state
  await page.context().storageState({ path: AUTH_STATE_PATH });
});

Reuse in tests:

// playwright.config.ts
export default defineConfig({
  projects: [
    // Setup project runs first and saves auth state
    { name: "setup", testDir: "./e2e/fixtures", testMatch: "auth.fixture.ts" },
    {
      name: "chromium",
      use: {
        storageState: "e2e/.auth/user.json",  // Reuse auth state
      },
      dependencies: ["setup"],
    },
  ],
});

Test Data Management

Principles:

  • Tests create their own data (never depend on pre-existing data)
  • Tests clean up after themselves (or use API to reset)
  • Use API calls for setup, not UI interactions (faster, more reliable)

API helpers for test data:

// e2e/utils/api-helpers.ts
import { type APIRequestContext } from "@playwright/test";

export class TestDataAPI {
  constructor(private request: APIRequestContext) {}

  async createUser(data: { email: string; displayName: string }) {
    const response = await this.request.post("/api/v1/users", { data });
    return response.json();
  }

  async deleteUser(userId: number) {
    await this.request.delete(`/api/v1/users/${userId}`);
  }

  async createOrder(userId: number, items: Array<Record<string, unknown>>) {
    const response = await this.request.post("/api/v1/orders", {
      data: { user_id: userId, items },
    });
    return response.json();
  }
}

Usage in tests:

test("edit user name", async ({ page, request }) => {
  const api = new TestDataAPI(request);

  // Setup: create user via API (fast)
  const user = await api.createUser({
    email: "edit-test@example.com",
    displayName: "Before Edit",
  });

  try {
    // Test: edit via UI
    const usersPage = new UsersPage(page);
    await usersPage.goto();
    // ... perform edit via UI ...
  } finally {
    // Cleanup: remove test data
    await api.deleteUser(user.id);
  }
});

Debugging Flaky Tests

1. Use trace viewer for failures:

// playwright.config.ts
use: {
  trace: "on-first-retry",  // Capture trace only on retry
}

View trace: npx playwright show-trace trace.zip

2. Run in headed mode for debugging:

npx playwright test --headed --debug tests/users/create-user.spec.ts

3. Common causes of flaky tests:

CauseFix
Hardcoded waitsUse explicit wait conditions
Shared test dataEach test creates its own data
Animation interferenceSet animations: "disabled" in config
Race conditionsWait for API responses before assertions
Viewport-dependent behaviorSet explicit viewport in config
Session leaks between testsUse storageState correctly, clear cookies

4. Retry strategy:

// playwright.config.ts
export default defineConfig({
  retries: process.env.CI ? 2 : 0,  // Retry in CI only
});

CI Configuration

# .github/workflows/e2e.yml
name: E2E Tests
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium

      - name: Start application
        run: |
          docker compose up -d
          npx wait-on http://localhost:3000 --timeout 60000

      - name: Run E2E tests
        run: npx playwright test

      - name: Upload test report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 14

      - name: Upload traces on failure
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: test-traces
          path: test-results/

Use scripts/run-e2e-with-report.sh to run Playwright with HTML report output locally.

Examples

See references/page-object-template.ts for annotated page object class. See references/e2e-test-template.ts for annotated E2E test. See references/playwright-config-example.ts for production Playwright config.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

38.89%
按下载量换算4,807

Claude

32.1%
按下载量换算3,968

Cursor

16.78%
按下载量换算2,074

Gemini CLI

9.26%
按下载量换算1,145

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills