e2e-tests
Skill30 starsChanged 16 days agoApache-2.0View on GitHub
Write, run, and debug end-to-end tests for the Braintrust SDK. Use when asked to add an e2e test, create a scenario, write an e2e scenario, add e2e coverage, debug e2e test, fix e2e snapshot, or any task involving the e2e/ directory.
- Reads credentials
- Installs packages
10 other projects use a version of this.
Adopted by
Most recently taken up by
- piskelapp/piskeltheir own version, first seen Nov 9, 2026
- microsoft/physical-ai-toolchaintheir own version, first seen Nov 1, 2026
- pablopetr/claude-skillstheir own version, first seen Oct 25, 2026
- rterakedis/leanwheel-skillstheir own version, first seen Oct 17, 2026
- vstorm-co/agenticostheir own version, first seen Oct 16, 2026
- borgbase/vykartheir own version, first seen Oct 8, 2026
Other versions10 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 10
- vitessio/vitess★ 21ksame name
- piskelapp/piskel★ 13ksame name
- borgbase/vykar★ 722same name
- vstorm-co/agenticos★ 241same name
- microsoft/physical-ai-toolchain★ 138same name
- issue-orchestrator/issue-orchestrator★ 10same name
- Joomla-Bible-Study/joomla-skills★ 8same name
- GlamgarOnDiscord/claude-saas-blueprint★ 2same name
- rterakedis/leanwheel-skills★ 2same name
- pablopetr/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository4 other files it gives its agents.
- AGENTS.mdAGENTS.md
- create-changesetSkill
- create-pull-requestSkill
- instrumentationSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
19 rules. 0 are common, 9 are distinctive, and 10 are very specific to this project.
0
Common
Most of the 9 edited versions we read keep these.
9
Distinctive
This author's own choices. Worth a look.
10
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 21
Start from the closest existing scenario and keep its structure unless the new case clearly needs a new pattern.
- Very specific: line 22
Default to module-scope setup with prepareScenarioDir({ scenarioDir: resolveScenarioDir(import.meta.url) }).
- Very specific: line 23
Use withScenarioHarness(...) for every scenario test.
- Distinctive: line 28
Run the narrowest test first, then rerun updated scenarios three times before treating snapshots as stable.
- Distinctive: line 32
Run workspace scripts from the repo root when you want the standard e2e entrypoints:
- Distinctive: line 46
Use real, valid inputs that the model can process.
- Distinctive: line 47
If recording is blocked by missing credentials, model access, or provider availability, report the blocker and the remaining recording work.
- Distinctive: line 48
Default to cheap provider models for real API calls and cassette recordings, unless the user explicitly requests otherwise.
- Very specific: line 65
Keep the expensive setup at module scope with prepareScenarioDir(...).
- Very specific: line 66
Run every scenario through withScenarioHarness(...).
- Very specific: line 67
Keep reusable logic in e2e/helpers/.
- Very specific: line 71
When a scenario family already has assertions.ts, keep version- or provider-specific test setup in scenario.test.ts and reuse the shared …
- Distinctive: line 73
Run new or updated scenarios three times in a row before considering snapshots stable.
- Distinctive: line 74
Do not add tests directly asserting on the auto instrumentation configs.
- Very specific: line 82
Test runner integration scenarios (deno, vitest, jest, ...): keep the outer e2e suite in scenario.test.ts, the spawned entry in …
- Very specific: line 86
Only add a scenario-local package.json for truly scenario-specific external dependencies.
- Very specific: line 88
Do not use workspace: specs in scenario-local manifests.
- Distinctive: line 89
If a scenario manifest exists, commit its lockfile.
- Very specific: line 101
If the scenario is external-provider backed, first confirm it has a cassette or run in BRAINTRUST_E2E_CASSETTE_MODE=record with the …
“Common” is measured: kept by at least 6 in 10 of the 9 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
E2E Tests
E2E tests run SDK scenarios in subprocesses against a mock Braintrust server. Prefer extending the closest existing scenario over inventing a new pattern.
The goal for provider e2e tests is always to exercise actual models with real, valid input data, either live during recording or through cassettes populated with actual model responses. The mock Braintrust server captures telemetry; provider behavior should come from the real provider.
Read first:
e2e/README.md- Closest
e2e/scenarios/<name>/scenario.test.ts - Relevant shared helper in
e2e/helpers/ - Relevant
assertions.tsfile when the scenario family already factors shared checks that way
Workflow
- Start from the closest existing scenario and keep its structure unless the new case clearly needs a new pattern.
- Default to module-scope setup with
prepareScenarioDir({ scenarioDir: resolveScenarioDir(import.meta.url) }). This copies the scenario into an isolated temp directory and installs any scenario-local dependencies before the test bodies run. - Use
withScenarioHarness(...)for every scenario test. Pick the runner that matches the real entrypoint:runScenarioDir()for defaulttsx-driven TypeScript scenariosrunNodeScenarioDir()for plain Node entrypoints and hook coveragerunDenoScenarioDir()for nested Deno runners
- Snapshot stable contracts, not raw noise. Normalize before snapshotting and prefer focused summaries over full payload dumps.
- Run the narrowest test first, then rerun updated scenarios three times before treating snapshots as stable.
Commands
Run workspace scripts from the repo root when you want the standard e2e entrypoints:
pnpm run test:e2e
pnpm run test:e2e:record # re-record provider cassettes and update snapshotsTry not to use specific test narrowing commands unless hunting down a very nasty and specific bug.
Cassettes
Cassettes mock provider HTTP responses (OpenAI, Anthropic, ...) so external-provider scenarios replay in CI without provider keys. The harness starts a local @braintrust/seinfeld cassette server and points provider SDK base URL env vars at that server, so subprocesses and SDK-launched binaries are covered too.
- Record cassettes by calling actual provider models through the real SDK. Do not hand-author model responses, embedding vectors, or usage data, or replace the provider with a synthetic HTTP server or fetch stub to make an e2e scenario pass. Synthetic responses belong in focused unit tests and do not satisfy provider e2e coverage.
- Use real, valid inputs that the model can process. Multimodal scenarios need decodable images, audio, video, and documents; arbitrary bytes labeled with a media MIME type do not qualify.
- If recording is blocked by missing credentials, model access, or provider availability, report the blocker and the remaining recording work. Do not fabricate cassette data or silently substitute synthetic provider responses.
- Default to cheap provider models for real API calls and cassette recordings, unless the user explicitly requests otherwise. Choose a model that supports the behavior under test, and keep prompts, output limits, and media duration small while preserving meaningful coverage.
- External-provider tests should thread
runContext: { variantKey: "...", originalScenarioDir }into the scenario runner. In normal replay mode, missing cassette entries fail loudly instead of skipping or falling back to live providers. Inrecord/record-missingmode, they run so new cassettes can be authored. - Thread
runContext: { variantKey: "...", originalScenarioDir }intorunScenarioDir/runNodeScenarioDir. Cassettes live ate2e/scenarios/<name>/__cassettes__/<variantKey>.cassette.json(parallel to__snapshots__/). Only setrunContext.cassetteexplicitly for unusual cases, such ascassette: falseon a non-provider mode inside an otherwise provider-backed scenario. To re-record after changing a scenario:
ANTHROPIC_API_KEY=... OPENAI_API_KEY=... \ pnpm --filter=@braintrust/js-e2e-tests run test:e2e:record -- scenarios/<name>/scenario.test.tsThen run again in
BRAINTRUST_E2E_CASSETTE_MODE=replaywith no provider keys to confirm the cassette is sufficient.- Volatile fields in request bodies (e.g. AI-SDK
experimental_generateMessageId) need a per-scenario filter. Add or update<scenario-dir>/cassette-filter.mjswith a namedfilterexport. The cassette server loads that filter throughwithScenarioHarness(...). - After recording, always inspect the cassette for leaked API keys before committing. The recorder redacts common patterns (
paranoidpreset), but confirm that no real keys appear in request headers, response bodies, or any URL query parameters. If a key slips through, remove the cassette, add a customredactrule, and re-record.
Preferred Patterns
- Keep the expensive setup at module scope with
prepareScenarioDir(...). Only callinstallScenarioDependencies(...)directly when you are testing installer behavior or need a nonstandard setup. - Run every scenario through
withScenarioHarness(...). - Keep reusable logic in
e2e/helpers/. Keep one-off fixtures and scenario-specific files inside the scenario directory. - Snapshot stable contracts, not raw noise. Use
normalizeForSnapshot(...)before inline snapshots andformatJsonFileSnapshot(...)plus file snapshots for larger payloads or version matrices. - For span-tree snapshots, use
matchSpanTreeSnapshot(...). It writes and asserts paired.span-tree.jsonand.span-tree.txtfiles from the same normalized span tree. The JSON file is the structural contract that is easiest to parse mechanically; the TXT file is the ASCII tree that is easiest to review by eye. Keep them in sync by updating both through the e2e update/record commands, and never hand-edit only one side of the pair. - For tracing-instrumentation span-tree snapshots, always capture
input,output,metadata,context,error, andmetrics. Normalize volatile values within these fields, but do not omit a field or selectively filter its semantic contents to reduce snapshot size or noise. - When a scenario family already has
assertions.ts, keep version- or provider-specific test setup inscenario.test.tsand reuse the shared assertions file. - Keep the CI e2e summary up to date. If a scenario version matrix or
variantKeychanges, updatee2e/config/pr-comment-scenarios.jsonin the same change and follow the established pattern used by other versioned scenarios: one summary row per version, not separate wrapped/auto rows unless that pattern already exists for the scenario family. - Run new or updated scenarios three times in a row before considering snapshots stable.
- Do not add tests directly asserting on the auto instrumentation configs.
Scenario Patterns
- SDK primitive scenarios: use
scenario.tswith normal SDK calls and assert ontestRunEvents(). Seetrace-primitives-basic. - Wrapper scenarios: use
events()rather thantestRunEvents(), find the root span first, and scope payload snapshots withpayloadRowsForRootSpan(...). Pair span and payload snapshots when the wrapper emits merged log rows. - Provider instrumentation scenarios often split setup and shared assertions. See
e2e/scenarios/anthropic-instrumentation/assertions.ts,e2e/scenarios/google-genai-instrumentation/assertions.ts, and similar directories before creating a new pattern. - Version matrix scenarios: put shared logic in
scenario.impl.*or shared assertion helpers, then loop over versions from aliases or helper-generated scenario lists. Do not duplicate the same assertions per version by hand. - Test runner integration scenarios (deno, vitest, jest, ...): keep the outer e2e suite in
scenario.test.ts, the spawned entry inscenario.ts, and nested test files in names likerunner.case.ts. Do not name nested runner files*.test.ts.
Scenario-Local Dependencies
- Only add a scenario-local
package.jsonfor truly scenario-specific external dependencies. - Workspace packages belong in
e2e/package.jsonasworkspace:^, not in scenario manifests. - Do not use
workspace:specs in scenario-local manifests. - If a scenario manifest exists, commit its lockfile.
Generate the lockfile with:
pnpm install --dir e2e/scenarios/<name> --ignore-workspace --lockfile-only --strict-peer-dependencies=falseDebugging
- Flaky snapshot: normalize the changing field instead of snapshotting around it.
- Request-flow assertions: grab
requestCursor()before running the scenario, then inspectrequestsAfter(...). - If the scenario is external-provider backed, first confirm it has a cassette or run in
BRAINTRUST_E2E_CASSETTE_MODE=recordwith the required provider env var set. - Deno/browser scenarios may intentionally differ from Node. Assert the real runtime contract instead of copying Node expectations blindly.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

