mcpField
E
emulate-seed

emulate-seed

github.com/yonatangross测试与质量29991 次安装今天更新
代码仓库

关于 emulate-seed

这是一项为 emulate 生成和管理种子配置的技能;emulate 是有状态的 API 仿真工具。它帮助开发者通过服务数据、Webhook 投递和 CI 配置,为支持的服务搭建测试环境。

主要功能

  1. 01根据依赖发现可用仿真服务
  2. 02生成测试数据种子 YAML
  3. 03仿真有状态 API 行为
  4. 04按服务签名投递 Webhook
  5. 05配置并行 CI 工作进程与端口
  6. 06覆盖 OAuth、支付和云服务

适用场景

  1. 01为集成测试配置带种子的 API 服务
  2. 02测试 Webhook 处理和签名校验
  3. 03在并行 CI 中运行服务测试
  4. 04断言捕获的邮件或结账流程

安装

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

$npx skills add https://github.com/yonatangross/orchestkit --skill emulate-seed

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

test-cases.json
references/
api-coverage.md
cli-reference.md
dep-to-emulator-map.json
ork-delta.md
upstream-github.md
upstream-google.md
upstream-vercel.md
upstream.md
rules/
_sections.md
_template.md
auth-tokens.md
parallel-ci.md
seed-config.md
service-selection.md
webhook-setup.md
scripts/
auto-discover.sh

详细介绍

上游版本参考:emulate 0.12.0(2026-09-30)。

Emulate 种子配置

为 emulate(Apache-2.0)生成并管理种子配置——这是 Vercel Labs 的有状态 API 仿真工具。每个类别都有单独的规则文件,存放在 rules/ 中,并按需加载。

配套 Agent: 此技能与 emulate-engineer 子 Agent(subagent_type: "ork:emulate-engineer")配合使用。如果任务涉及从头生成完整的 emulate 配置、设置 webhook HMAC、集成 CI 流水线,或隔离并行工作器端口,请启动该 Agent,而不是在此处直接处理——它的上下文中包含完整的 13 个仿真器服务端口矩阵和种子规则。

不是 Mock。 Emulate 提供完整的状态机,支持级联删除、游标分页、webhook 投递和 HMAC 签名验证。通过 API 创建 PR 后,它会出现在 GET /repos/:owner/:repo/pulls 中。删除仓库时,其 issues、PR 和 webhook 也会级联删除。

2026-04 新增(emulate 0.4.x)

  • 模块化的 @emulators/* 包——每项服务都是独立的包(@emulators/github、@emulators/stripe 等);顶层 emulate 重新导出 createEmulator 和 CLI。
  • 新增 4 项服务(共 12 项):mongoatlas:4007、okta:4008、resend:4009、stripe:4010,并提供可直接使用的种子 YAML 配置块。
  • Resend 本地收件箱——GET http://localhost:4009/inbox 返回捕获的邮件,方便进行断言,无需访问真实服务提供商。
  • Stripe 托管结账——真实的会话重定向流程,以及 checkout.session.completed/expired webhook 投递,适用于 E2E 支付测试。
  • MongoDB Atlas——Admin API v2(项目/集群/数据库用户)和支持完整 CRUD + 聚合操作的 Data API v1。
  • Okta OIDC——完整支持 discovery、JWKS、authorize/token/userinfo/revoke/introspect,以及 Users/Groups/Apps CRUD。
  • Entra / Apple / Slack 扩展(v0.4.0)——PKCE + 刷新轮换(Entra)、RS256 JWKS(Apple)、OAuth v2 授权同意界面(Slack)。
  • @emulators/adapter-next——全捕获 Next.js 路由处理器可在与应用相同的源上运行仿真器;修复 Vercel 预览部署中的 OAuth 回调 URL 漂移问题。

自动发现(M125 #4)

scripts/auto-discover.sh 会扫描项目的 package.json,将依赖与 references/dep-to-emulator-map.json 进行匹配,然后报告匹配结果或写入 emulate.config.yaml。有三种模式:

模式行为
(默认)在 stderr 上报告匹配的依赖和仿真器并集;不写入文件
--json输出机器可读的 JSON,而非人类可读的报告
--apply写入 emulate.config.yaml(未指定 --force 时拒绝覆盖)
$ bash "${CLAUDE_SKILL_DIR}/scripts/auto-discover.sh"
emulate-seed --auto — scanning /path/to/package.json

Detected:
  @octokit/rest  →  github · Any GitHub API client
  next-auth  →  google-oauth, apple-auth, microsoft-entra · Default OAuth providers
  stripe  →  stripe
  @vercel/blob  →  aws · @vercel/blob is S3-compatible

Union: apple-auth, aws, github, google-oauth, microsoft-entra, stripe

$ bash "${CLAUDE_SKILL_DIR}/scripts/auto-discover.sh" --apply
…
✓ Wrote /path/to/emulate.config.yaml with 6 service(s)

多仿真器依赖默认选择所有合理的服务提供商;之后用户可从 YAML 中删减。未映射的依赖会被静默跳过——扩展覆盖范围只需提交文档 PR(编辑 references/dep-to-emulator-map.json),无需修改代码。

dev 启动时会读取生成的 emulate.config.yaml——参见 src/skills/dev/scripts/boot.sh。

快速参考

类别规则影响使用场景
种子配置1高为测试环境配置 emulate.config.yaml
服务选择1中为测试选择 GitHub/Vercel/Google
Webhook 设置1中使用 HMAC 验证测试 webhook 投递
并行 CI1高并行运行测试,避免端口冲突
认证令牌1中为仿真用户预置映射后的令牌

共计:5 个类别中的 5 条规则

快速入门

# Install (packages published under @emulators/* scope)
npm install --save-dev emulate

# Start all services
npx emulate

# Start specific services with seed data
npx emulate --service github,stripe --seed ./emulate.config.yaml

# Generate a starter config
npx emulate init --service github

服务(0.10.0 — 14 个模拟器)

各版本新增内容:

  • 0.5.0 — 新增 Clerk、MongoDB Atlas、Stripe、Resend 和 Okta 模拟器;支持无端口集成(嵌入式模拟器无需专用端口);支持 Google OAuth hd 声明;新增 Stripe Checkout 和 Resend 魔法链接示例;AWS S3 模拟器现在与官方 SDK 的线路格式一致。
  • 0.6.0 — 扩展 Slack(OAuth v2 授权同意界面、对话/表情回应)。
  • 0.6.1 — Vercel Blob 存储。
  • 0.7.0 — 新增 Linear(第 13 个提供方):有状态的组织/团队/问题/周期 + Webhook。
  • 0.8.0 — 新增 Twilio(第 14 个提供方):账户、电话号码、消息、通话、对话、消息服务、Verify 流程和模拟器端点,并提供 Next.js 短信验证示例。
  • 0.9.0 — 新增 Nuxt 模拟器适配器(与 Next.js 适配器并列);提供方数量不变。
  • 0.10.0 — GitHub 仓库内容和提交历史改为有状态(GET /repos/:owner/:repo/readme、GET/PUT/DELETE /repos/:owner/:repo/contents/:path,写入操作会生成真实提交、GET /repos/:owner/:repo/commits,以及通过数字 ID 调用的 GET /repositories/:id);Emulator 对象新增只读 generatedSecrets 数组,并导出新的 GeneratedSecret 类型;GitHub App JWT 验证现在同时接受 PKCS#8 和 PKCS#1 密钥。提供方数量不变。

所有更改均向后兼容,但有一项行为变更值得注意:0.10.0 将 Stripe Webhook 投递切换为 Stripe 自有的 Stripe-Signature 标头格式。上游将此归类为错误修复,而非重大变更,但断言 Stripe 投递中旧版 GitHub 风格 sha256= 标头的测试现在会失败。两种格式请参阅下文的 Webhook 投递。

服务默认端口覆盖范围
Vercel:4000项目、部署、域名、环境变量、团队
GitHub:4001仓库、PR、问题、评论、审查、Actions、Webhook、组织、团队
Google OAuth:4002OAuth 2.0 授权、令牌交换、用户信息
Slack:4003聊天、对话、用户、表情回应、带授权同意界面的 OAuth v2
Apple Auth:4004使用 Apple 登录 — OIDC 发现、JWKS(RS256)、授权流程、令牌交换
Microsoft Entra:4005OAuth 2.0/OIDC v2.0、授权码 + PKCE、刷新令牌轮换、v1 令牌端点、Graph /users/{id}
AWS:4006S3 存储桶、SQS 队列、IAM 用户/角色、STS 身份
MongoDB Atlas (0.4+):4007Admin API v2(项目、集群、数据库用户)+ Data API v1(完整 CRUD + 聚合)
Okta (0.4+):4008OIDC 发现、JWKS、授权/令牌/用户信息/撤销/内省、用户/群组/应用 CRUD
Resend (0.4+):4009发送 + 批量(每请求 100 条)、列出/检索/取消、域名、API 密钥、受众、联系人、本地收件箱(GET /inbox)
Stripe (0.4+):4010客户、支付方式、客户会话、支付意图、扣款、产品、价格、带 Webhook 投递的托管结账会话
Clerk (0.5+)(按需)用户、会话、组织
Linear (0.7+)(按需)组织、团队、问题、周期、Webhook
Twilio (0.8+)(按需)账户、电话号码、消息、通话、对话、消息服务、Verify 流程、模拟器端点

完整端点列表请参阅 references/api-coverage.md。

Next.js 适配器(0.4+)— @emulators/adapter-next

通过全捕获路由处理程序,在与 Next.js 应用相同的源站上运行模拟器。解决 Vercel 预览部署中的 OAuth 回调 URL 漂移问题——不再出现与 http://localhost:4001 不匹配的重定向。

// next.config.js
const { withEmulate } = require('@emulators/adapter-next')
module.exports = withEmulate({ /* your next config */ })

// app/api/[...emulate]/route.ts
import { createEmulateHandler } from '@emulators/adapter-next'
export const { GET, POST } = createEmulateHandler({
  services: ['github', 'stripe', 'resend'],
  persistence: { /* load(), save() or built-in filePersistence */ },
})

Seed Config 结构

Seed Config 会预先填充令牌、用户、仓库和项目,让测试从已知状态开始。

# emulate.config.yaml
tokens:
  dev_token:
    login: yonatangross
    scopes: [repo, workflow, admin:org]
  ci_token:
    login: ci-bot
    scopes: [repo]

github:
  users:
    - login: yonatangross
      name: Yonatan Gross
    - login: ci-bot
      name: CI Bot
  repos:
    - owner: yonatangross
      name: my-project
      private: false
      default_branch: main
      topics: [typescript, testing]

vercel:
  users:
    - username: yonatangross
      email: [email protected]
  projects:
    - name: my-docs
      framework: next

# NEW in 0.4.x — drop-in seed blocks
okta:
  users:
    - login: [email protected]
      firstName: Alice
      lastName: Smith
  groups: [{ name: Everyone }, { name: Admins }]
  apps: [{ name: My Web App }]
  authorization_servers:
    - name: default
      audiences: ["api://default"]

resend:
  domains: [{ name: example.com }]
  api_keys: [{ name: default }]
  # In tests: GET http://localhost:4009/inbox to assert captured emails

stripe:
  customers:
    - name: Test Customer
      email: [email protected]
  products: [{ name: Pro Plan }, { name: Starter Plan }]
  prices:
    - { product: Pro Plan, unit_amount: 4900, currency: usd, recurring: { interval: month } }
    - { product: Starter Plan, unit_amount: 1900, currency: usd, recurring: { interval: month } }
  # Webhook delivery fires on checkout.session.completed / expired

mongoatlas:
  projects: [{ name: my-project }]
  clusters: [{ project: my-project, name: my-cluster }]
  database_users: [{ project: my-project, username: app-user }]

完整架构和最佳实践请参阅 rules/seed-config.md。

程序化 SDK

服务包位于 @emulators/* 作用域下(例如 @emulators/github、@emulators/stripe)。程序化 API(createEmulator)从顶层 emulate 包导出。

import { createEmulator } from 'emulate'

const github = await createEmulator({ service: 'github', port: 4001 })
// github.url -> 'http://localhost:4001'

// State is real — create a PR and it appears in the list
const res = await fetch(`${github.url}/repos/org/repo/pulls`, {
  method: 'POST',
  headers: { Authorization: 'Bearer dev_token' },
  body: JSON.stringify({ title: 'Test PR', head: 'feature', base: 'main' })
})

const prs = await fetch(`${github.url}/repos/org/repo/pulls`)
// -> includes the PR we just created

// Auto-generated credentials (0.10.0+): readonly GeneratedSecret[], each
// { service, kind, id, label, value }. A GitHub App emulator, for example,
// generates its own RSA key rather than making you supply one.
github.generatedSecrets

// Cleanup
github.reset()       // Synchronous state wipe
await github.close() // Shut down server

此处的 seed 是已解析的对象,而不是路径。只有 CLI 的 --seed 标志才接受文件名。 有关多服务设置、生命周期钩子以及 Vitest/Jest 接线方式,请参阅 references/upstream.md。有关 ork 对该 API 的修正,请参阅 references/ork-delta.md。

Webhook 投递

Emulate 会在状态发生变化时,使用 HMAC-SHA256 签名投递真实 webhook。 签名格式因提供方而异,因此一种通用验证器无法覆盖所有服务。 GitHub 格式的标头仍为默认格式;Stripe 自 0.10.0 起使用自有格式。

import crypto from 'crypto'

// GitHub format (the default for most services): sha256=<hmac over the raw body>
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
}

// Stripe format, as of emulate 0.10.0: Stripe-Signature: t=<timestamp>,v1=<hmac>,
// where the HMAC covers `<timestamp>.<raw body>`, NOT the body alone. Verifying a
// Stripe delivery with the GitHub helper above fails on both counts.
function verifyStripeWebhook(rawBody: string, header: string, secret: string): boolean {
  const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=')))
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${parts.t}.${rawBody}`)
    .digest('hex')
  return crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected))
}

Webhook 接收器模式请参阅 rules/webhook-setup.md。

CI 集成

# .github/workflows/test.yml
jobs:
  test:
    steps:
      - uses: actions/checkout@v4
      - name: Start emulate
        run: npx emulate --service github --seed .emulate/ci.yaml &
      - name: Wait for emulate
        run: sleep 2
      - name: Run tests
        run: npm test
        env:
          GITHUB_API_BASE: http://localhost:4001
          VERCEL_API_BASE: http://localhost:4000
并行测试执行

每个测试工作进程都会获得独立端口,以避免竞态条件:

// vitest.config.ts
const workerPort = 4001 + parseInt(process.env.VITEST_WORKER_ID || '0')

完整的并行隔离模式请参阅 rules/parallel-ci.md。

决策矩阵

工具适用场景有状态?平台
emulate(首选)GitHub/Vercel/Google/Slack/Apple/Entra/AWS/Okta/Resend/Stripe/MongoDB/Clerk/Linear 测试是全部 13 项服务
Pact服务间的契约验证否任意
MSW浏览器内/Node HTTP 模拟否任意
NockNode.js HTTP 拦截否任意
WireMockHTTP 模拟服务部分任意

在以下情况下使用 emulate:

  • 测试调用 GitHub、Vercel、Google、Slack、Apple、Entra、AWS、Okta、Resend、Stripe、MongoDB Atlas、Clerk 或 Linear 的代码
  • 需要在一次测试中的多个 API 调用之间持久化状态
  • 希望投递带有真实 HMAC 签名的 webhook(GitHub、Stripe)
  • 需要断言级联副作用(删除仓库 -> PR 随之级联删除)
  • 需要在不访问真实提供方的情况下断言已发送的邮件(Resend 本地 /inbox)
  • 需要在测试中使用托管的 Stripe 结账会话和真实重定向流程

在以下情况下使用 MSW/Nock:

  • 模拟 emulate 未覆盖的任意 HTTP API
  • 需要在浏览器内拦截(MSW)
  • 测试只需要单个请求/响应对

上游内容覆盖范围(不要重复说明)

此技能是一个封装层,加上我们自己的增量内容。emulate 为每项服务提供了自己的参考文档;把这些文档复制到这里,只会导致内容在下次发布时过时。如果涉及以下主题,请阅读一手资料,而非转述内容。

主题一手资料
程序化 API(createEmulator、url、reset()、close())、Vitest/Jest 接线、配置自动检测顺序、令牌回退references/upstream.md(从 vercel-labs/emulate、skills/emulate/SKILL.md 同步)
GitHub 端点示例、GitHub App JWT 预置、Octokit 和 Auth.js 基础 URL 接线、GitHub OAuth 流程https://github.com/vercel-labs/emulate/blob/main/skills/github/SKILL.md
Google OIDC 发现、JWKS、authorize/token/userinfo/revoke、PKCE、google-auth-library、Passport、openid-clienthttps://github.com/vercel-labs/emulate/blob/main/skills/google/SKILL.md
Vercel 端点示例、游标分页、团队范围限定、集成 OAuth 流程https://github.com/vercel-labs/emulate/blob/main/skills/vercel/SKILL.md
所有其他模拟器(Slack、Apple、Entra、AWS、Okta、Resend、Stripe、MongoDB Atlas、Clerk、Linear、Twilio)https://github.com/vercel-labs/emulate/tree/main/skills

我们保留的内容: references/ork-delta.md(任何供应商文档中都没有的修正和内部约定)、references/cli-reference.md、references/api-coverage.md、references/dep-to-emulator-map.json、scripts/auto-discover.sh,以及 rules/ 中的所有内容。

从供应商文档复制任何代码片段前,请先阅读 references/ork-delta.md。其中记录了供应商文档未明确说明的两个 API 事实(导出的工厂函数是 createEmulator,程序化选项中的 seed 是对象而非路径),以及本仓库使用的 *_API_BASE 环境变量约定,该约定不同于供应商的 *_EMULATOR_URL。

相关技能

  • testing-integration — 集成测试模式(API 测试优先使用 emulate)
  • testing-e2e — 使用模拟后端的端到端测试模式
  • testing-unit — 单元测试模式(依赖 API 的单元测试使用 emulate)
  • security-patterns — 身份验证令牌模式(使用 emulate 预置令牌)

CLI 参考

所有 CLI 标志和命令请参阅 references/cli-reference.md。

评论

支持 Markdown