Testing utilities
Write unit tests against your fabric instance without scaffolding the runtime each time.
Subpath: @fabricorg/integrations/testing.
Quick example
import { describe, it, expect } from 'vitest';
import { slack } from '@fabricorg/integrations/plugins';
import {
createTestFabric,
mockFetcher,
webhookFixture,
expectPath,
} from '@fabricorg/integrations/testing';
describe('our slack notifier', () => {
it('posts to the right channel', async () => {
const fetcher = mockFetcher((req) => {
if (req.url.endsWith('/chat.postMessage')) {
return { body: { ok: true, channel: 'C1', ts: '0.0' } };
}
return { status: 404, body: { error: 'not_found' } };
});
const fabric = createTestFabric([
slack({ botToken: 'xoxb-test', fetcher }),
]);
await fabric.slack.api.messages.send({ channel: 'C1', text: 'hi' });
expect(fetcher.calls).toHaveLength(1);
expect(fetcher.calls[0].headers.Authorization).toBe('Bearer xoxb-test');
});
});API
createTestFabric(plugins)
Wraps createFabric with sensible test defaults. Same code path the runtime takes — hooks, permissions, key resolution, error handlers all run identically.
mockFetcher(handler)
Typed factory for the fetcher option each plugin accepts. The handler can return a real Response or an object shorthand:
const fetcher = mockFetcher((req) => {
if (req.method === 'GET') return { body: { ok: true } };
return new Response('explicit', { status: 201 });
});| Property | Description |
|---|---|
fetcher.calls | Array of every captured request (url, method, headers, body) |
fetcher.reset() | Clear the calls log without recreating |
webhookFixture(input)
Build a normalized WebhookRequest for processWebhook tests. Defaults to POST + application/json so test bodies stay focused on payloads.
const fixture = webhookFixture({
url: 'https://hooks.test/slack',
headers: { 'x-slack-signature': 'v0=abc123' },
body: { type: 'event_callback', event: { type: 'message', text: 'hi' } },
});expectPath(fabric, dotPath)
Walk a dot-path, return the leaf or undefined. Use for assertions against the bound fabric surface:
expect(expectPath(fabric, 'slack.api.users.list')).toBeTypeOf('function');
expect(expectPath(fabric, 'stripe.api.charges.create')).toBeTypeOf('function');Re-exports
To keep test files focused, the /testing subpath also re-exports the four in-memory store classes so you can construct isolated stores per test:
| Re-export | From |
|---|---|
InMemoryKeyStore, KeyStore | auth/key-store |
InMemoryEntityStore, EntityStore, EntityRecord | db/entity-store |
InMemoryPermissionStore, PermissionStore, PermissionRecord, PermissionStatus, CreatePermissionInput | permissions/store |
InMemoryEventLogger, EventLogger, EventLogRecord | events |
Each is a fresh instance — perfect for beforeEach setup.