testing-api-overrides
Skill173 starsChanged 5 months agoApache-2.0View on GitHub
Test that components send correct query parameters or request arguments. Use when testing filtering, sorting, pagination, or any read operation where request parameters matter. Use for test-scoped mock customization.
In this repository20 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- bug-fix-tddSkill
- deep-linksSkill
- devcontainer-devSkill
- security-vuln-remediationSkill
- skill-creatorSkill
- skill-editorSkill
- testing-api-assertionsSkill
- testing-api-overridesSkill
- testing-with-api-mocksSkill
- bug-fix-tddSkill
- deep-linksSkill
- devcontainer-devSkill
- security-vuln-remediationSkill
- skill-creatorSkill
- skill-editorSkill
- testing-api-assertionsSkill
- testing-with-api-mocksSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Test that your code sends correct API parameters by using conditional overrides that respond differently based on the request.
- Distinctive: line 24
If the code sends wrong parameters, the mock returns wrong data, the UI shows wrong content, and the test fails.
- Very specific: line 177
Use .overrideHandler() for full control over the response:
- Very specific: line 193
All overrides are automatically reset before each test via resetAllAutoAPIMocks() in vitest.setup.ts.
- Very specific: line 197
When the same response override is needed across many tests, define it as a scenario in the fixture instead of duplicating .override() …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Testing API Overrides
Test that your code sends correct API parameters by using conditional overrides that respond differently based on the request. This approach tests actual user-facing behavior rather than inspecting internal request details.
Philosophy
Good tests verify what users see, not implementation details.
Instead of:
- ❌ Recording the request and checking query params
- ❌ Asserting on internal function calls
Do this:
- ✅ Set up conditional mocks that respond based on params
- ✅ Verify the component renders the expected data
If the code sends wrong parameters, the mock returns wrong data, the UI shows wrong content, and the test fails. This catches real bugs.
When to Use Conditional Overrides
- Testing list filtering (e.g., filter by group, status, search term)
- Testing pagination parameters
- Testing sort order
- Any read operation where request parameters affect what data is returned
Note: For mutations (create/update/delete), use recordRequests() instead. See the testing-api-assertions skill.
conditionalOverride()
Returns different data based on request properties:
import { mockedGetApiV1BetaWorkloads } from '@mocks/fixtures/workloads/get'
mockedGetApiV1BetaWorkloads.conditionalOverride(
// Predicate: when should this override apply?
({ query }) => query.group === 'archive',
// Transform: what data to return?
(data) => ({
...data,
workloads: [], // Archive group is empty
})
)Predicate Function
The predicate receives parsed request info with easy access to query params, path params, body, and headers:
;({ query, path, body, headers }) => {
// Query parameters (pre-parsed)
query.group // '?group=archive' -> 'archive'
query.status // '?status=running' -> 'running'
// Path parameters (from route like /workloads/:name)
path.name // for /workloads/:name
// Request body (for POST/PUT/DELETE)
body?.name // parsed JSON body
// Headers
headers.get('Authorization')
return true // or false
}Transform Function
The transform receives default data and returns modified data:
;(data) => ({
...data, // Spread defaults
workloads: data.workloads?.filter(
// Modify as needed
(w) => w.status === 'running'
),
})Example: Testing Group Filter
import { mockedGetApiV1BetaWorkloads } from '@mocks/fixtures/workloads/get'
it('shows only workloads from the selected group', async () => {
// Default mock returns workloads from multiple groups
// Add conditional override for 'production' group
mockedGetApiV1BetaWorkloads.conditionalOverride(
({ query }) => query.group === 'production',
(data) => ({
...data,
workloads: [
{ name: 'prod-server-1', group: 'production', status: 'running' },
{ name: 'prod-server-2', group: 'production', status: 'running' },
],
})
)
render(<WorkloadsList group="production" />)
// If component sends ?group=production, it gets the filtered data
// If component forgets the param, it gets default data with mixed groups
await waitFor(() => {
expect(screen.getByText('prod-server-1')).toBeVisible()
expect(screen.getByText('prod-server-2')).toBeVisible()
})
// These would appear if the filter param wasn't sent correctly
expect(screen.queryByText('dev-server')).not.toBeInTheDocument()
})Example: Testing Empty State
it('shows empty message when group has no workloads', async () => {
mockedGetApiV1BetaWorkloads.conditionalOverride(
({ query }) => query.group === 'empty-group',
() => ({ workloads: [] })
)
render(<WorkloadsList group="empty-group" />)
await waitFor(() => {
expect(screen.getByText(/no workloads found/i)).toBeVisible()
})
})Multiple Conditional Overrides
Chain multiple overrides for different conditions:
mockedGetApiV1BetaWorkloads
.conditionalOverride(
({ query }) => query.group === 'production',
() => ({ workloads: productionWorkloads })
)
.conditionalOverride(
({ query }) => query.group === 'staging',
() => ({ workloads: stagingWorkloads })
)Later overrides wrap earlier ones. If no predicate matches, the default fixture data is returned.
Simple Overrides (No Condition)
For test-scoped data changes without conditions, use .override():
// Override for entire test - no condition
mockedGetApiV1BetaGroups.override(() => ({
groups: [{ name: 'only-group', registered_clients: [] }],
}))
// Modify default data
mockedGetApiV1BetaGroups.override((data) => ({
...data,
groups: data.groups?.slice(0, 1),
}))Error Responses
Use .overrideHandler() for full control over the response:
import { HttpResponse } from 'msw'
// Return error
mockedGetApiV1BetaGroups.overrideHandler(() =>
HttpResponse.json({ error: 'Server error' }, { status: 500 })
)
// Network failure
mockedGetApiV1BetaGroups.overrideHandler(() => HttpResponse.error())Automatic Reset
All overrides are automatically reset before each test via resetAllAutoAPIMocks() in vitest.setup.ts. No cleanup needed.
Reusable Scenarios
When the same response override is needed across many tests, define it as a scenario in the fixture instead of duplicating .override() calls.
Defining Scenarios (in fixtures)
// In fixtures/workloads/get.ts
export const mockedGetApiV1BetaWorkloads = AutoAPIMock<...>({
workloads: [/* default data */],
}).scenario('empty', (mock) => mock.override(() => ({ workloads: [] })))Using Scenarios (in tests)
mockedGetApiV1BetaWorkloads.activateScenario('empty')Scenario names are defined in renderer/src/common/mocks/scenarioNames.ts. Use existing names when possible to keep scenarios consolidated.
Related Skills
- testing-with-api-mocks - Auto-generated mocks and fixture basics
- testing-api-assertions - Verifying mutations with
recordRequests()(create/update/delete only)
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.

