Token导航 LogoToken导航TokenDH.com
前端设计操作浏览器github未标认证来源可访问clear审计异常

e2e-test-buildere2e 测试构建器

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

2,232

周安装

93

GitHub Stars

33

下载量

744
CodexClaudeCursorGemini CLI

安装说明

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

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

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

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

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/patricio0312rev/skills --skill e2e-test-builder

简介

构建可靠的端到端测试,聚焦关键用户流程与 Playwright 配置。

  • 提供测试目录结构、并行策略与跨浏览器支持的最佳实践模板。
  • 支持基础 URL 设置与追踪录制,便于调试与失败重试。
  • 应根据项目实际端口调整 baseURL,避免硬编码造成部署冲突。
  • e2e-test-builder 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

E2E Test Builder

Build reliable end-to-end tests for critical user flows.

Playwright Test Setup

// playwright.config.ts
import { defineConfig } from "@playwright/test";

export default defineConfig({
  testDir: "./e2e",
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: "html",
  use: {
    baseURL: "http://localhost:3000",
    trace: "on-first-retry",
    screenshot: "only-on-failure",
  },
  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,
  },
});

Critical Flow Tests

// e2e/checkout-flow.spec.ts
import { test, expect } from "@playwright/test";

test.describe("Checkout Flow", () => {
  test.beforeEach(async ({ page }) => {
    // Navigate to home page
    await page.goto("/");

    // Login
    await page.getByRole("button", { name: "Login" }).click();
    await page.getByLabel("Email").fill("test@example.com");
    await page.getByLabel("Password").fill("password123");
    await page.getByRole("button", { name: "Sign In" }).click();

    // Wait for dashboard
    await expect(page).toHaveURL("/dashboard");
  });

  test("should complete checkout successfully", async ({ page }) => {
    // 1. Browse products
    await page.getByRole("link", { name: "Products" }).click();
    await expect(page).toHaveURL("/products");

    // 2. Add product to cart
    await page.getByRole("button", { name: "Add to Cart" }).first().click();
    await expect(page.getByText("Added to cart")).toBeVisible();

    // 3. Go to cart
    await page.getByRole("link", { name: "Cart" }).click();
    await expect(page).toHaveURL("/cart");
    await expect(
      page.getByRole("heading", { name: "Shopping Cart" })
    ).toBeVisible();

    // 4. Proceed to checkout
    await page.getByRole("button", { name: "Checkout" }).click();
    await expect(page).toHaveURL("/checkout");

    // 5. Fill shipping information
    await page.getByLabel("Full Name").fill("John Doe");
    await page.getByLabel("Address").fill("123 Main St");
    await page.getByLabel("City").fill("New York");
    await page.getByLabel("ZIP Code").fill("10001");

    // 6. Fill payment information
    await page.getByLabel("Card Number").fill("4242424242424242");
    await page.getByLabel("Expiry Date").fill("12/25");
    await page.getByLabel("CVC").fill("123");

    // 7. Place order
    await page.getByRole("button", { name: "Place Order" }).click();

    // 8. Verify success
    await expect(page).toHaveURL(/\/order\/\d+/);
    await expect(page.getByText("Order confirmed!")).toBeVisible();
    await expect(page.getByText(/Order #\d+/)).toBeVisible();
  });

  test("should show validation errors for empty fields", async ({ page }) => {
    // Navigate to checkout
    await page.goto("/checkout");

    // Try to submit without filling fields
    await page.getByRole("button", { name: "Place Order" }).click();

    // Verify validation errors
    await expect(page.getByText("Name is required")).toBeVisible();
    await expect(page.getByText("Address is required")).toBeVisible();
    await expect(page.getByText("Card number is required")).toBeVisible();
  });

  test("should handle payment failure", async ({ page }) => {
    // Add product and go to checkout
    await page.goto("/products");
    await page.getByRole("button", { name: "Add to Cart" }).first().click();
    await page.goto("/checkout");

    // Fill with failing card number
    await page.getByLabel("Card Number").fill("4000000000000002");
    await page.getByLabel("Expiry Date").fill("12/25");
    await page.getByLabel("CVC").fill("123");

    // Submit
    await page.getByRole("button", { name: "Place Order" }).click();

    // Verify error message
    await expect(page.getByText("Payment failed")).toBeVisible();
    await expect(page.getByText("Please try a different card")).toBeVisible();
  });
});

Page Object Pattern

// e2e/pages/LoginPage.ts
export class LoginPage {
  constructor(private page: Page) {}

  async goto() {
    await this.page.goto("/login");
  }

  async login(email: string, password: string) {
    await this.page.getByLabel("Email").fill(email);
    await this.page.getByLabel("Password").fill(password);
    await this.page.getByRole("button", { name: "Sign In" }).click();
  }

  async expectLoginSuccess() {
    await expect(this.page).toHaveURL("/dashboard");
  }

  async expectLoginError(message: string) {
    await expect(this.page.getByText(message)).toBeVisible();
  }
}

// e2e/pages/ProductPage.ts
export class ProductPage {
  constructor(private page: Page) {}

  async goto() {
    await this.page.goto("/products");
  }

  async addToCart(productName: string) {
    const product = this.page.locator(`[data-product="${productName}"]`);
    await product.getByRole("button", { name: "Add to Cart" }).click();
  }

  async expectProductVisible(productName: string) {
    await expect(
      this.page.getByRole("heading", { name: productName })
    ).toBeVisible();
  }
}

// Usage in tests
test("should login and add product", async ({ page }) => {
  const loginPage = new LoginPage(page);
  const productPage = new ProductPage(page);

  await loginPage.goto();
  await loginPage.login("test@example.com", "password123");
  await loginPage.expectLoginSuccess();

  await productPage.goto();
  await productPage.addToCart("MacBook Pro");
});

Selector Strategy

// Preferred selector priority:
// 1. Role-based (most resilient)
await page.getByRole("button", { name: "Submit" });
await page.getByRole("link", { name: "Products" });
await page.getByRole("textbox", { name: "Email" });

// 2. Label-based (semantic)
await page.getByLabel("Email address");
await page.getByLabel("Password");

// 3. Test ID (for complex cases)
await page.getByTestId("user-menu");
await page.getByTestId("product-card-123");

// 4. Text content (for unique text)
await page.getByText("Welcome back!");
await page.getByText(/Order #\d+/);

// ❌ Avoid: CSS selectors (brittle)
// await page.locator('.btn.btn-primary');
// await page.locator('#submit-button');

Test Data Management

// e2e/fixtures/test-data.ts
export const testData = {
  users: {
    admin: {
      email: "admin@example.com",
      password: "admin123",
    },
    customer: {
      email: "customer@example.com",
      password: "customer123",
    },
  },
  products: {
    laptop: {
      name: "MacBook Pro",
      price: 2499.99,
    },
    phone: {
      name: "iPhone 15",
      price: 999.99,
    },
  },
  cards: {
    valid: "4242424242424242",
    declined: "4000000000000002",
    insufficientFunds: "4000000000009995",
  },
};

// e2e/setup/seed-test-data.ts
export async function seedTestData() {
  const prisma = new PrismaClient();

  // Create test users
  await prisma.user.upsert({
    where: { email: testData.users.customer.email },
    create: {
      email: testData.users.customer.email,
      password: await hash(testData.users.customer.password),
    },
    update: {},
  });

  // Create test products
  await prisma.product.upsert({
    where: { name: testData.products.laptop.name },
    create: testData.products.laptop,
    update: {},
  });

  await prisma.$disconnect();
}

Visual Regression Testing

// e2e/visual/homepage.spec.ts
test("homepage should match screenshot", async ({ page }) => {
  await page.goto("/");

  // Take full page screenshot
  await expect(page).toHaveScreenshot("homepage.png", {
    fullPage: true,
    maxDiffPixels: 100, // Allow minor differences
  });
});

test("product card should match screenshot", async ({ page }) => {
  await page.goto("/products");

  const productCard = page.locator('[data-testid="product-card"]').first();

  // Take element screenshot
  await expect(productCard).toHaveScreenshot("product-card.png");
});

Mobile Testing

// e2e/mobile/checkout-mobile.spec.ts
test.use({ viewport: { width: 375, height: 667 } }); // iPhone SE

test("should complete mobile checkout", async ({ page }) => {
  await page.goto("/");

  // Open mobile menu
  await page.getByRole("button", { name: "Menu" }).click();
  await page.getByRole("link", { name: "Products" }).click();

  // Add to cart
  await page.getByRole("button", { name: "Add to Cart" }).first().click();

  // Continue with checkout
  // ...
});

Network Mocking

// e2e/mocked/payment-api.spec.ts
test("should handle payment API timeout", async ({ page }) => {
  // Mock slow payment API
  await page.route("**/api/payment", async (route) => {
    await new Promise((resolve) => setTimeout(resolve, 5000));
    await route.fulfill({
      status: 200,
      body: JSON.stringify({ success: true }),
    });
  });

  // Proceed with checkout
  await page.goto("/checkout");
  // ... fill form ...
  await page.getByRole("button", { name: "Place Order" }).click();

  // Should show loading state
  await expect(page.getByText("Processing payment...")).toBeVisible();
});

Best Practices

  1. Test user flows: Not individual components
  2. Use role-based selectors: More resilient
  3. Page objects: Reusable and maintainable
  4. Wait for elements: Don't use fixed sleeps
  5. Test critical paths: Login, checkout, signup
  6. Manage test data: Isolated per test
  7. Visual regression: Key pages only

Output Checklist

  • Playwright/Cypress configured
  • Critical flows identified
  • Page objects created
  • Selector strategy defined (role-based)
  • Test data management
  • Setup/teardown hooks
  • Authentication flow tested
  • Error states tested
  • Mobile viewport tests
  • CI integration configured

适合场景

01

用户想查找某类 Agent Skill 时

02

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

03

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

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

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

能力 4

补充不同宿主或平台的使用分布数据

能力 5

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

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

平台分布

Claude Code

30.21%
按下载量换算225

Gemini CLI

22.16%
按下载量换算165

Antigravity

18.91%
按下载量换算141

windsurf

13.77%
按下载量换算102

github-copilot

8.92%
按下载量换算66

Codex

3.79%
按下载量换算28

安全审计

Gen Agent Trust Hub

通过

Socket

可疑

Snyk

未通过

权限和风险

操作浏览器

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

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。

来源信息

继续浏览同类 Skills