| name | typespec-ts-add-spector-test |
| description | Add or update Spector end-to-end tests for the @azure-tools/typespec-ts emitter in packages/typespec-ts. Use when given Spector case paths, links to http-specs or azure-http-specs cases, or pull requests that add or change Spector scenarios and the TypeScript emitter must opt into generation, implement Vitest client tests, regenerate the declaration baseline, and validate against the mock server. |
Add Spector Tests for typespec-ts
Work in packages/typespec-ts and process every requested Spector case.
Scope Boundary
This skill adds Spector tests for behavior already supported by the TypeScript emitter.
Do not modify emitter production code, shared runtime code, TypeSpec specifications, or Spector mock APIs while applying this skill. If a scenario exposes unsupported behavior or a defect, diagnose it only far enough to report a concise, evidence-based blocker. Defer the implementation or fix to a separate issue or pull request.
Do not work around unsupported behavior by weakening assertions, changing expected requests, omitting required calls, or adding a skipped test.
Inputs
Accept one or more of:
- A path relative to a
specs directory, such as encode/numeric or azure/core/model.
- A link under
microsoft/typespec/packages/http-specs/specs or Azure/typespec-azure/packages/azure-http-specs/specs.
- A pull request in either repository that adds or changes specs.
For a pull request, inspect changed files under packages/http-specs/specs or packages/azure-http-specs/specs and identify each affected case directory.
Expected Changes
For a new supported case, usually commit:
- An enabled entry in
packages/typespec-ts/spector.config.yaml.
packages/typespec-ts/test/azure-modular-integration/generated/<output-path>/tspconfig.yaml.
packages/typespec-ts/test/azure-modular-integration/generated/<output-path>/.gitignore.
- The generated
packages/typespec-ts/test/azure-modular-integration/generated/<output-path>/src/index.d.ts.
- A hand-written
packages/typespec-ts/test/azure-modular-integration/<descriptive-kebab-name>.test.ts.
Generated client implementation files are ignored and must not be force-added.
Workflow
1. Prepare the Package
Ensure the core submodule is initialized at the commit pinned by the repository. If it is missing or uninitialized, run:
git submodule update --init core
Do not overwrite a locally modified or intentionally checked-out submodule; use a clean worktree instead.
If mise is installed, prefix the commands below with mise exec --; otherwise, use pnpm directly.
Install dependencies only when they are missing:
pnpm install
Build the emitter and its dependencies from the repository root:
pnpm -r --filter "@azure-tools/typespec-ts..." build
From packages/typespec-ts, stage the current specs:
pnpm copy:typespec
Run this once for a batch of cases.
2. Resolve and Validate Each Case
Normalize links to the path beneath specs/.
Check temp/specs/<spec-path> and find its entry point, preferring client.tsp, then main.tsp; a config key may also name a .tsp file directly.
Find and read the applicable mockapi.ts.
If the path or mock API does not exist, stop processing that case and report the invalid path rather than guessing.
Read all TypeSpec files used by the case, not only the entry point.
Extract every Scenarios.<name> assignment and understand the validated HTTP method, URI, parameters, headers, body, response, and status.
3. Inspect Existing Coverage
Search spector.config.yaml for the exact spec key and inspect test/azure-modular-integration for the corresponding hand-written test.
The config is the only opt-in source; do not add a hard-coded spec list.
Resolve config entries as follows:
true enables a case with outputPath equal to the spec key.
{ options: { outputPath: "..." } } changes the generated folder and the --filter value.
- A list generates multiple outputs for one spec.
false documents an intentionally disabled case.
Compare the mock API scenarios with existing tests.
If all scenarios are covered and passing, make no change for that case.
If coverage is partial, preserve existing behavior and add only the missing scenarios.
4. Opt Into Generation
Add a new enabled entry under specs in spector.config.yaml:
specs:
encode/numeric: true
Use options.outputPath only when the spec needs multiple configurations, names an individual .tsp entry point, or the generated folder must differ from the key:
specs:
client/naming/enum-conflict: { options: { outputPath: client/naming-enum-conflict } }
For multiple configurations, use a list with a unique outputPath for each item.
Do not change the shared Spector packages' own selection groups.
If the case is intentionally unsupported, use false only when requested or when the repository convention requires tracking it, and add a nearby reason with an issue link.
5. Add the Generated-Package Configuration
Create test/azure-modular-integration/generated/<output-path>/tspconfig.yaml.
Read references/naming-and-templates.md for the current tspconfig.yaml and .gitignore templates.
Start from the minimal template or the nearest current sibling configuration, then keep only options supported by the current emitter and required by the case.
6. Generate the Focused Client
From packages/typespec-ts, generate the selected output:
node ./test/commands/gen-spector.js --filter="$outputPath" --phase=client
The filter matches the resolved outputPath exactly, not necessarily the spec key.
Confirm test/azure-modular-integration/generated/<output-path>/src/index.ts exists and exports a usable client.
Read generated src/index.ts and the referenced client and model files to determine exact constructors, operation groups, method signatures, option bags, and return types.
Do not hand-write tests from TypeSpec names alone.
If generation fails, determine whether the failure comes from invalid test configuration or unsupported emitter behavior. Correct test configuration mistakes. For unsupported behavior or an emitter failure, stop implementing that scenario and report the observed blocker; do not modify emitter production code.
7. Implement the Vitest Test
Choose a descriptive kebab-case filename ending in .test.ts.
Search nearby tests by feature and generated path because historical filenames are not mechanically derived from spec paths.
Read references/naming-and-templates.md for current naming guidance, test boilerplate, imports, and assertion patterns.
Construct clients with the actual generated signature rather than assuming the common constructor shape.
Use port 3002, allow insecure HTTP, and disable retries where the client options permit it.
Write tests that invoke every mock API scenario and assert meaningful response values when a response exists.
Match request values exactly to mockapi.ts.
Use generated model and options types rather than casts or any.
Follow current nearby patterns for paging, long-running operations, credentials, multipart requests, and error assertions.
Do not remove a failing scenario merely to make the file green.
Treat a correctly written failing test as unsupported behavior or an emitter/runtime defect to report. Do not fix that defect as part of this skill.
Do not add new skipped tests for unsuccessful scenarios. Exclude their incomplete test changes and report the failure instead. Preserve existing skipped tests unless their linked issue is resolved and the test now passes.
8. Validate Against Spector
Start the server from packages/typespec-ts in a separate process:
pnpm start-test-server
Wait until the server is listening on port 3002, then run only the affected test files:
pnpm exec vitest run --project integration-azure-modular "test/azure-modular-integration/$testFile.test.ts"
Always stop the server afterward, including after failures:
pnpm stop-test-server
For a failure, first correct mistakes in the test by rechecking mockapi.ts, TypeSpec semantics, and generated signatures. If the test is correct and the generated client still cannot satisfy the scenario, report the blocker and remove the incomplete test changes. Do not change production code.
Do not run the full spector-test command for focused validation because it regenerates and tests every opted-in case.
9. Regenerate the Tracked Baseline
After focused tests pass, run both generation phases for each changed output:
node ./test/commands/gen-spector.js --filter="$outputPath"
Confirm generated/<output-path>/src/index.d.ts exists.
The client phase removes this tracked rollup and the declaration phase restores it, so do not finish after --phase=client.
Review git status for the expected config, test, .gitignore, tspconfig.yaml, and src/index.d.ts changes.
From the repository root, run the required formatting and lint commands:
pnpm format
pnpm lint
If the changes will be submitted in a pull request, add a Chronus change description for @azure-tools/typespec-ts:
pnpm change add
Use the internal change kind for test-only Spector coverage unless the changes have a user-facing impact requiring another kind. Do not add a change description when no implementation pull request will be created.
10. Report
Report each processed spec path and output path, newly covered scenarios, already-covered scenarios, and unsuccessful scenarios.
For each unsuccessful scenario, report the stage that failed (generation, compilation, request validation, or response validation), the observed generated-client behavior, the expected behavior from mockapi.ts, and an existing issue link when one is available.
Do not propose or implement an emitter fix unless a separate task explicitly requests it.
If working on a pull request, keep its implementation-status section accurate.