mcpField
P
pw-init

pw-init

github.com/bondar-artem测试与质量138 次安装17 周前更新
代码仓库

关于 pw-init

pw-init 是一项用于在现有项目中搭建 Playwright 端到端测试框架的技能。它先收集环境与认证需求,再按单 Chromium 浏览器约定生成配置、文件和脚本。

主要功能

  1. 01引导配置环境与角色
  2. 02仅使用 Chromium 的 Playwright 配置
  3. 03按角色划分项目与认证状态
  4. 04按环境加载 dotenv 文件
  5. 05生成冒烟测试与测试脚本

适用场景

  1. 01在项目中启用端到端测试
  2. 02配置多环境测试
  3. 03添加认证及访客测试角色

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bondar-artem/playwright-scripting-skills --skill pw-init

安装后在 Claude Code 中输入/pw-init确认已加载。

详细介绍

从头开始在当前项目中初始化 Playwright E2E 框架。请按顺序执行以下步骤。

即使有人要求自主完成,也绝不能跳过本技能中的 AskUserQuestion 步骤。

必须遵循的约定

生成的框架遵循以下结构:

tests/
  auth.setup.ts                   # Auth state persistence (only if roles requested)
  <role>/                         # One subfolder per auth role (e.g. guest, admin)
    smoke.spec.ts                 # Generated sample smoke test
playwright-utils/
  .auth/                          # storageState files — gitignored
  fixtures/
    index.ts                      # Extended test + expect re-export (skeleton)
  helpers/                        # Stateless utilities
  pages/                          # Page objects (empty — created on demand)
  types/
    env.d.ts                      # process.env typing
.env.test.<env>                   # Per-environment vars — gitignored
playwright.config.ts              # Single Chromium browser, one project per role

主要约定:

  • 单一浏览器(Desktop Chrome)。不配置 Firefox/WebKit 项目。
  • 环境文件命名为 .env.test.<env>(例如 .env.test.local、.env.test.qa),通过 dotenv 根据 TEST_ENV 加载。默认值为 local。
  • 在 playwright.config.ts 中按角色配置项目,每个项目都有自己的 testDir: ./tests/<role>;对于已认证角色,还需配置 storageState 和 dependencies: ['auth-setup']。
  • 存储状态位于 playwright-utils/.auth/<role>.json(不是 playwright/.auth/)。

1. 收集需求

使用 AskUserQuestion 和自由对话收集输入。按以下顺序提问:

1.1 环境

使用 AskUserQuestion,让问题在视觉上突出显示;但多数情况下,答案会通过“Other”以自由文本形式给出。按以下方式配置问题:

  • header:Environments
  • question:How many test environments do you need, and what should they be called? Provide a baseURL for each. Example: local: http://localhost:3000, qa: https://qa.example.com
  • multiSelect:false
  • options(预设涵盖常见情况;系统会自动附加“Other”,供用户输入自定义列表):
    1. Just local — Single env, BASE_URL=http://localhost:3000
    2. local + qa — Two envs; I'll ask for the qa baseURL next
    3. local + qa + production — Three envs; I'll ask for qa and production baseURLs next

如果用户选择了需要提供其他 baseURL(qa/production)的预设,请通过普通对话继续询问各个 URL。如果用户选择“Other”,请解析其自由文本列表。

列表中的第一个环境将成为默认环境(未设置 TEST_ENV 时使用)。

1.2 认证角色

使用 AskUserQuestion。按以下方式配置:

  • header:Auth roles
  • question:What auth roles do you need? Each authenticated role gets an entry in auth.setup.ts plus its own project with storageState. "guest" is unauthenticated — no setup needed for it.
  • multiSelect:false
  • options(预设涵盖常见情况;系统会自动附加“Other”,供用户输入自定义列表):
    1. guest only — Unauthenticated tests only; skip auth.setup.ts and the auth-setup project
    2. guest + user — One unauthenticated project plus one authenticated role
    3. user + admin — Two authenticated roles, no guest project
    4. guest + user + admin — One unauthenticated project plus two authenticated roles

如果用户选择“Other”,请解析其自由文本列表。如果最终列表中只有 guest,则跳过生成 auth.setup.ts 和 auth-setup 项目。

1.3 登录流程详情(仅适用于存在已认证角色的情况)

使用 AskUserQuestion。配置:

  • header:Login flow
  • question:How should I figure out the login flow for auth.setup.ts? I need: link text to the login page from /, form field labels for email and password, and the URL each role lands on after login.
  • multiSelect:false
  • options:
    1. Explore the source code — I'll search the codebase for the login page, form fields, and post-login URL, then write the setup
    2. Generate placeholders — I'll use generic <LOGIN_LINK_TEXT>/<EMAIL_LABEL>/<PASSWORD_LABEL>/<POST_LOGIN_PATH> placeholders with a // TODO marker; the user fills them in later
    3. I'll provide the details — User types the link text, field labels, and post-login URL via "Other"

如果用户选择 Explore the source code:搜索登录页面(查看 src/app/login、app/login、src/pages/login、名称匹配 Login* 的组件,或由“Log In”/“Sign In”链接引用的路由)。确定电子邮件/密码输入框的标签以及登录后的重定向目标。生成 auth.setup.ts 时使用这些准确值。如果搜索结果不可靠或没有结果,则改用 Generate placeholders 路径。

如果用户选择 Generate placeholders:使用占位值,并在每个 setup 块上方添加一条 // TODO: confirm selectors 注释。

如果用户选择 I'll provide the details(或在“Other”中输入答案):将其输入解析为 (a) 链接文本、(b) 电子邮件标签、(c) 密码标签、(d) 登录后的路径。

此步骤不要阻塞流程——选择一条路径并继续。

1.4 可选附加项

使用 AskUserQuestion 分别询问每项(单独提问,每项两个选项——是/否):

  • CI webServer 块 — “Should I include a webServer config in playwright.config.ts to auto-start your dev server in CI?” 如果回答是,则询问启动命令(例如 npm run dev)以及服务监听的 URL。
  • 复制 Claude 规则 — “Should I copy playwright-architecture.md and playwright-scripting.md into .claude/rules/ so future AI work follows the conventions?” 仅回答是/否——不要询问源路径。规范源文件是用户级安装器技能:~/.claude/skills/init-playwright-architecture/SKILL.md 和 ~/.claude/skills/init-playwright-scripting/SKILL.md。规则内容嵌入在 和 标记之间。如果这些文件不存在,请明确告知用户并跳过——不要编造内容。

2. 运行 Playwright 安装器

使用 create-playwright 标志以非交互方式运行安装器。这样会跳过向导提示,使整个步骤能够自动运行:

npm init playwright@latest -- --quiet --browser=chromium --install-deps

标志:

  • --quiet — 跳过向导,使用默认值
  • --browser=chromium — 仅安装 Chromium(符合单浏览器约定)
  • --install-deps — 自动安装浏览器和系统依赖
  • TypeScript、tests/ 文件夹以及“无 GitHub Actions 工作流”是静默模式的默认值——无需标志

如果安装失败或卡住,请改为让用户在终端中交互式运行命令。

3. 清理默认内容

删除安装器创建的不符合我们约定的文件:

rm -r tests-examples 2>/dev/null
rm tests/example.spec.ts 2>/dev/null

4. 安装支持性依赖

让用户运行:

npm install -D dotenv

5. 生成 playwright.config.ts

覆盖默认配置。使用收集到的环境和角色。模板:

import { defineConfig, devices } from '@playwright/test'
import dotenv from 'dotenv'

const testEnv = process.env.TEST_ENV ?? '<DEFAULT_ENV>'
process.env.TEST_ENV = testEnv
dotenv.config({ path: `.env.test.${testEnv}`, quiet: true })

const isCI = !!process.env.CI

export default defineConfig({
  testDir: './tests',
  fullyParallel: false,
  retries: isCI ? 2 : 0,
  workers: isCI ? 1 : undefined,
  reporter: isCI ? [['html', { open: 'never' }], ['github']] : [['html', { open: 'never' }]],
  timeout: 60000,
  expect: { timeout: 10000 },
  use: {
    baseURL: process.env.BASE_URL,
    trace: 'on-first-retry'
  },
  projects: [
    // Include only if any authenticated roles exist:
    {
      name: 'auth-setup',
      testMatch: 'auth.setup.ts',
      use: { ...devices['Desktop Chrome'] },
    },
    // Per-role projects — one entry per role.
    // Unauthenticated roles (e.g. guest) omit storageState + dependencies:
    {
      name: '<role>',
      testDir: './tests/<role>',
      use: {
        ...devices['Desktop Chrome'],
        storageState: 'playwright-utils/.auth/<role>.json', // omit for guest
      },
      dependencies: ['auth-setup'], // omit for guest
    },
  ],
  // Include only if user opted into webServer block:
  // webServer: {
  //   command: '<USER_DEV_COMMAND>',
  //   url: '<USER_DEV_URL>',
  //   reuseExistingServer: !process.env.CI,
  //   timeout: 120_000,
  // },
})

将 <DEFAULT_ENV> 替换为用户列出的第一个环境名称。为每个角色生成一个项目条目。

6. 更新 .gitignore

追加以下内容(如果文件不存在则创建):

# Playwright
playwright-utils/.auth/
test-results/
playwright-report/
playwright/.cache/

# Local env files (keep .env.test.example committed)
.env
.env.local
.env.test.*
!.env.test.example

7. 创建目录结构

mkdir -p playwright-utils/{fixtures,helpers,pages,types,.auth}
mkdir -p tests/<role>  # one per role from step 1.2

8. 生成 tests/auth.setup.ts

如果没有需要身份验证的角色,则跳过。否则,根据步骤 1.3 中的登录流程详情,为每个需要身份验证的角色生成一个 setup(...) 代码块:

import { test as setup } from '@playwright/test'

const <role>File = 'playwright-utils/.auth/<role>.json'

setup('authenticate as <role>', async ({ page }) => {
  await page.goto('/')
  await page.getByRole('link', { name: '<LOGIN_LINK_TEXT>' }).click()
  await page.getByRole('textbox', { name: '<EMAIL_LABEL>' }).fill(process.env.<ROLE>_EMAIL!)
  await page.getByLabel('<PASSWORD_LABEL>').fill(process.env.<ROLE>_PASSWORD!)
  await page.getByRole('button', { name: 'Login', exact: true }).click()
  await page.waitForURL('**<POST_LOGIN_PATH>')
  await page.context().storageState({ path: <role>File })
})

如果用户只提供了部分详情,则保留合理的占位内容,并在每个 setup 代码块上方添加一行 // TODO: confirm selectors 注释——用户运行时会完善选择器。(允许的注释:标记需要用户执行操作,不是旁白。)

9. 生成 playwright-utils/types/env.d.ts

export {}

declare global {
  namespace NodeJS {
    interface ProcessEnv {
      TEST_ENV?: '<env1>' | '<env2>' | ...
      BASE_URL?: string
      CI?: string
      // One pair per authenticated role:
      <ROLE>_EMAIL?: string
      <ROLE>_PASSWORD?: string
    }
  }
}

将 namespace NodeJS 声明包裹在 declare global { ... } 中。由于存在 export {},此文件是一个模块——在模块内部扩展全局 NodeJS.ProcessEnv 接口需要使用 declare global,否则 TypeScript 会将其视为局部声明,导致 process.env.<ROLE>_EMAIL 没有类型。

确认 tsconfig.json 包含此文件。Playwright 默认生成的 tsconfig.json 会匹配 **/*.ts,因此会自动包含该文件。

10. 生成 playwright-utils/fixtures/index.ts

用于重新导出扩展版 test 的骨架 — 以便将来接入页面对象:

import { test as base, expect } from '@playwright/test'

type Fixtures = {
  // Add fixtures here as page objects and helpers are built.
}

export const test = base.extend<Fixtures>({})

export { expect }

11. 生成示例冒烟测试

为每个角色创建 tests/<role>/smoke.spec.ts。冒烟测试用于验证框架已正确配置——填写环境变量后,在全新安装中即可通过。

访客冒烟测试模板:

import { test, expect } from '@playwright/test'

test.describe('Guest smoke', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/')
  })

  test('Home page loads', async ({ page }) => {
    await expect(page).toHaveURL('/')
  })
})

需要身份验证的角色冒烟测试模板:

import { test, expect } from '@playwright/test'

test.describe('<Role> smoke', () => {
  test('Authenticated session is active', async ({ page }) => {
    await page.goto('/')
    // TODO: replace with a real authenticated-only assertion
    // (e.g. expect(page.getByRole('button', { name: '<user menu>' })).toBeVisible())
  })
})

12. 更新 package.json 脚本

添加以下脚本(与现有 scripts 合并,不要覆盖):

{
  "scripts": {
    "test:e2e": "playwright test",
    "test:e2e:ui": "playwright test --ui"
  }
}

如果用户定义了多个环境,还要为每个环境添加一个别名(默认环境除外):

"test:e2e:<env>": "TEST_ENV=<env> playwright test"

13. 复制 Claude 规则(仅当用户选择加入时)

如果用户在步骤 1.4 中选择加入,则从用户级安装器技能中提取规则内容,并将其写入新项目的 .claude/rules/ 目录。不要询问用户路径——源文件位置固定。

对于每条规则(architecture 和 scripting):

  1. 来源:~/.claude/skills/init-playwright-<name>/SKILL.md。如果文件不存在,请明确告知用户并跳过该规则——不要编造内容。
  2. 提取 和 标记之间的内容(不包括标记)。删除开头和结尾的空行。
  3. 将提取的内容写入当前项目的 .claude/rules/playwright-<name>.md。
mkdir -p .claude/rules

# Architecture rule
awk '/^$/{flag=1; next} /^$/{flag=0} flag' \
  ~/.claude/skills/init-playwright-architecture/SKILL.md \
  > .claude/rules/playwright-architecture.md

# Scripting rule
awk '/^$/{flag=1; next} /^$/{flag=0} flag' \
  ~/.claude/skills/init-playwright-scripting/SKILL.md \
  > .claude/rules/playwright-scripting.md

如果新项目中已存在目标文件,覆盖前请询问用户选择 Overwrite / Skip。

14. 最终摘要和环境文件(最后一个手动步骤)

技能到此结束。不要暂停等待确认,不要验证文件,也不要运行冒烟测试。

为步骤 1.1 中的每个环境打印一个代码块(加入 gitignore),再为 .env.test.example 打印一个代码块(提交)。每个代码块都包含 BASE_URL=<env baseURL>,以及步骤 1.2 中每个需要身份验证的角色对应的一对空白 <ROLE>_EMAIL / <ROLE>_PASSWORD。.env.test.example 代码块使用第一个环境的 BASE_URL 作为占位值。

将代码块中的环境名和角色名替换为用户提供的实际名称。环境为 local + qa、角色为 user + admin 时的示例:

框架已就绪 — 最后一步,请创建以下环境文件。

.env.test.local(加入 gitignore):

BASE_URL=http://localhost:3000
USER_EMAIL=
USER_PASSWORD=
ADMIN_EMAIL=
ADMIN_PASSWORD=

.env.test.qa(加入 gitignore):

BASE_URL=https://qa.example.com
USER_EMAIL=
USER_PASSWORD=
ADMIN_EMAIL=
ADMIN_PASSWORD=

.env.test.example(提交):

BASE_URL=http://localhost:3000
USER_EMAIL=
USER_PASSWORD=
ADMIN_EMAIL=
ADMIN_PASSWORD=

评论

支持 Markdown