Agent skill
qa-engineer-integration
Write integration tests for CLI commands with Vitest
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/qa-engineer-integration
SKILL.md
QA Engineer for Integration Testing
Responsibilities
- This skill ensures integration tests cover CLI behavior changes first.
- Tests remain readable, deterministic, and aligned with how users run commands.
- End-to-end side effects are emphasized: filesystem, API calls, logging, and reports.
When to use
Integration tests are mandatory for every new feature or behavior change. Write these tests before the implementation. Use this skill whenever a change affects CLI command behavior, API interactions, filesystem reads and writes, logging, or reporting.
Best practices
- Use
preconditionshelpers to set up MSW handlers, memfs state, and stubbed dependencies. - Require MSW handlers to be registered inside preconditions so API behavior is explicit per test.
- Drive the CLI via
command.parseAsync([...args])and assert side effects and outputs. - Validate behavior through action spies, manifest files, reports, logs, and console output.
- Test titles must always start with
should.
Patterns to follow
- Preconditions: Group setup helpers in a
preconditionsobject (e.g.,canLoadFiles,canLoadManifest,canCreateRemoteResources,failsToUpdateRemoteResources). Each helper should be focused, deterministic, and reusable across tests. - MSW in preconditions: Define MSW handlers inside those precondition helpers (e.g.,
preconditions.canCreateRemoteResourcesregistershttp.postand returns created items). This keeps request and response behavior close to the test intent. - Filesystem state: Use
memfsandvol.fromJSONto create local files andvol.resetinafterEachto clear state. When you need path resolution, useresolveCommandPathwith the command constants. - Command execution: Import the command module, register the CLI
index, then runcommand.parseAsync(['node', 'test', ...args]). - Assertions: Verify action calls with
expect(actions.method).toHaveBeenCalledWith(...), then check generated manifest entries, reports, log output, and console messages.
Example shape (simplified):
ts
const server = setupServer();
const preconditions = {
canLoadFiles(items: Item[]) {
const dir = resolveCommandPath(directories.items, DEFAULT_SPACE);
vol.fromJSON(Object.fromEntries(items.map(item => [path.join(dir, `${item.slug}.json`), JSON.stringify(item)])));
},
canCreateRemoteItems(items: Item[]) {
const created = items.map(item => ({ ...item, id: getID() }));
server.use(
http.post(`https://mapi.storyblok.com/v1/spaces/${DEFAULT_SPACE}/items`, async ({ request }) => {
const body = await request.json();
const match = created.find(i => i.slug === body.item.slug);
return HttpResponse.json({ item: match });
}),
);
return created;
},
};
describe('command push', () => {
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => {
vi.resetAllMocks();
vi.clearAllMocks();
vol.reset();
server.resetHandlers();
resetReporter();
});
afterAll(() => server.close());
it('should push items and write manifest/report', async () => {
preconditions.canLoadFiles([makeMockItem()]);
preconditions.canCreateRemoteItems([makeMockItem()]);
await command.parseAsync(['node', 'test', 'push', '--space', DEFAULT_SPACE]);
expect(actions.createItem).toHaveBeenCalled();
expect(await parseManifest()).toEqual([expect.objectContaining({ old_id: expect.anything() })]);
expect(getReport()).toEqual(expect.objectContaining({ status: 'SUCCESS' }));
});
});
Didn't find tool you were looking for?