Claude Code Plugins

Community-maintained marketplace

Feedback

Playwright E2E testing with Page Object pattern, web-first assertions, and proper locators. Triggers on playwright, e2e, page object, getByRole.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name playwright
description Playwright E2E testing with Page Object pattern, web-first assertions, and proper locators. Triggers on playwright, e2e, page object, getByRole.
triggers playwright, e2e, page object, getByRole, getByLabel, getByTestId
Write reliable E2E tests using Playwright with the Page Object pattern. Use web-first assertions that auto-wait and retry, with proper locator strategies. **CRITICAL: Always fetch Playwright documentation for current API.**
MCPSearch({ query: "select:mcp__plugin_devtools_context7__query-docs" })
// Locator patterns
mcp__context7__query_docs({
  libraryId: "/microsoft/playwright",
  query: "How do I use getByRole, getByLabel, getByTestId, and locator?",
});

// Assertions
mcp__context7__query_docs({
  libraryId: "/microsoft/playwright",
  query: "How do I use expect with toBeVisible, toHaveText, and toContainText?",
});

// Page interactions
mcp__context7__query_docs({
  libraryId: "/microsoft/playwright",
  query: "How do I use click, fill, check, and waitFor?",
});

Note: Context7 v2 uses server-side filtering. Use descriptive natural language queries.

**Page Object pattern:**
// pages/login.page.ts
class LoginPage extends BasePage {
  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 verifyLoggedIn() {
    await expect(
      this.page.getByRole("heading", { name: "Dashboard" }),
    ).toBeVisible();
  }
}

Test structure:

import { test, expect } from "@playwright/test";
import { Pages } from "../pages/pages";

test.describe.serial("Login flow", () => {
  let pages: ReturnType<typeof Pages>;

  test.beforeEach(async ({ page }) => {
    pages = Pages(page);
  });

  test("should login successfully", async () => {
    await pages.loginPage.goto();
    await pages.loginPage.login("user@example.com", "password");
    await pages.loginPage.verifyLoggedIn();
  });
});
Use locators in this order (most to least preferred):
  1. getByRole() - Accessible name
  2. getByLabel() - Form labels
  3. getByText() - Visible text
  4. getByTestId() - Test IDs
  5. CSS selectors - Last resort
// ✅ Preferred
page.getByRole("button", { name: "Submit" });
page.getByLabel("Email");
page.getByText("Welcome");

// ⚠️ Use when needed
page.getByTestId("submit-button");

// ❌ Avoid
page.locator(".btn-primary");
page.locator("#submit");
**Web-first assertions (auto-wait):**
await expect(locator).toBeVisible();
await expect(locator).toHaveText("expected");
await expect(locator).toContainText("partial");
await expect(locator).toHaveValue("value");
await expect(locator).toBeEnabled();
await expect(locator).toBeChecked();
await expect(page).toHaveURL(/pattern/);
await expect(page).toHaveTitle("Title");
**Banned:** Selectors in test files (use page objects), `isVisible()`, CSS class selectors, `page.waitForTimeout()`, `.only`/`.skip` in commits

Required:

  • Page Objects extend BasePage
  • test.describe.serial() for related tests
  • Web-first assertions (auto-wait/retry)
  • Extended timeouts for slow operations

Locator Priority: getByRole()getByLabel()getByText()getByTestId() → CSS

```bash npx playwright test # Run all tests npx playwright test --ui # Interactive UI mode npx playwright test --headed # Show browser npx playwright test -g "login" # Filter by name npx playwright show-report # View HTML report ```
  • Context7 docs fetched for current API
  • Page objects encapsulate selectors
  • Web-first assertions used
  • Tests are isolated
  • Proper locator strategy