skills/strataljs/stratal/stratal-testing

stratal-testing

SKILL.md

@stratal/testing

Test utilities for Stratal applications: module compilation with provider overrides, fluent HTTP client, storage fakes, fetch mocking, and auth testing helpers. Full documentation at stratal.dev/testing.

Setup

Docs: Overview

// vitest.setup.ts
import 'reflect-metadata';
import { Test } from '@stratal/testing';
Test.setBaseModules([CoreModule]);

Test file convention: src/**/__tests__/**/*.spec.ts. Always call module.close() in afterEach.

Creating Test Modules

Docs: Testing Module

const module = await Test.createTestingModule({
  imports: [UsersModule],
})
  .overrideProvider(EMAIL_TOKEN)
  .useValue(mockEmailService)
  .withEnv({ DATABASE_URL: 'test-url' })
  .compile();

Access services: module.get(TOKEN). Access HTTP client: module.http. Access container: module.container.

Provider Overrides

Chain overrides before .compile():

Test.createTestingModule({ imports: [AppModule] })
  .overrideProvider(TOKEN_A).useValue(mockA)
  .overrideProvider(TOKEN_B).useClass(FakeB)
  .overrideProvider(TOKEN_C).useFactory(() => stub)
  .compile();

Use .withEnv() to set environment variables. Use Test.setBaseModules() for modules shared across all tests.

HTTP Testing

Docs: HTTP Testing

const response = await module.http
  .post('/api/v1/users')
  .withBody({ email: 'test@example.com' })
  .withHeaders({ 'X-Custom': 'value' })
  .send();

response.assertCreated();
await response.assertJsonPath('data.email', 'test@example.com');

Assertion methods: assertOk(), assertCreated(), assertNotFound(), assertUnauthorized(), assertForbidden(), assertStatus(code), assertJsonPath(path, value), assertJsonStructure(shape).

FakeStorageService

Docs: Mocks & Fakes

Auto-registered in test modules. Access via module.storage. Assertions: assertExists(path), assertMissing(path), assertEmpty(), assertCount(n). Utility: getStoredPaths(), getFile(path), clear().

Fetch Mocking

Docs: Mocks & Fakes

import { createFetchMock } from '@stratal/testing';

const mock = createFetchMock();
// In beforeEach: mock.activate(); mock.disableNetConnect()
// In afterEach:  mock.reset()

mock.mockJsonResponse('https://api.example.com/data', { result: 'ok' });
mock.mockError('https://api.example.com/fail', 503, 'Service Unavailable');

Deep Mocks

Docs: Mocks & Fakes

import { createMock } from '@stratal/testing/mocks';

const mockEmailService = createMock<EmailService>();
mockEmailService.send.mockResolvedValueOnce(undefined);

Use with overrideProvider(TOKEN).useValue(mockEmailService).

Auth Testing (ActingAs)

import { ActingAs } from '@stratal/testing';

const actingAs = new ActingAs(module.get(AUTH_SERVICE));
const headers = await actingAs.createSessionForUser({ id: 'user-1' });
const response = await module.http
  .withHeaders(headers)
  .get('/api/v1/profile')
  .send();

Database Testing

// Truncate tables between tests
await module.truncateDb();

// Seed test data
await module.seed(new UserSeeder());

// Database assertions
await module.assertDatabaseHas('user', { email: 'test@example.com' });
await module.assertDatabaseMissing('user', { email: 'deleted@example.com' });
await module.assertDatabaseCount('user', 5);

Test Patterns

  • Create module in beforeEach, call module.close() in afterEach
  • Override external services (email, storage, external APIs) with mocks/fakes
  • Use module.runInRequestScope() to test request-scoped services
  • Use factories for test data, seeders for complex test setup
  • Assert HTTP responses with fluent assertion chains
  • Use module.getDb() for direct database access in tests
Weekly Installs
4
GitHub Stars
6
First Seen
7 days ago
Installed on
opencode4
gemini-cli4
claude-code4
github-copilot4
codex4
kimi-cli4