feat(core-testing): scaffold shared testing utilities package

Adds @repo/core-testing (tag: tooling) with:
- factory/defineFactory: monotonic-sequence object factories with overrides
- contract/defineContractSuite: shared test suites runnable against multiple impls
- react/renderWithProviders + createMockTrpcClient: RTL helpers
- payload/stubPayloadConfig + mockPayloadModule: Payload mocking helpers
- setup/{jsdom,node}: vitest setup files

Spec: docs/superpowers/specs/2026-05-05-tdd-foundation-design.md §5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-05 13:37:35 +02:00
parent 1ab3a3274f
commit 4ca083690f
25 changed files with 946 additions and 10 deletions

View File

@@ -0,0 +1,29 @@
import { createTRPCClient, httpBatchLink } from "@trpc/client";
import superjson from "superjson";
import type { AnyTRPCRouter } from "@trpc/server";
// Returns a tRPC client whose fetch is a stub honouring the provided mocks.
// Mocks are keyed by procedure path ("blog.articleBySlug") returning the
// raw response body.
export function createMockTrpcClient<TRouter extends AnyTRPCRouter>(
mocks: Record<string, unknown> = {},
) {
const fetchStub: typeof fetch = async (input) => {
const url = typeof input === "string" ? input : (input as Request).url;
const path = new URL(url, "http://mock").pathname.replace(/^\/api\/trpc\//, "");
const result = mocks[path];
if (result === undefined) {
return new Response(JSON.stringify([{ error: { code: -32603, message: `No mock for ${path}` } }]), { status: 200 });
}
return new Response(JSON.stringify([{ result: { data: superjson.serialize(result) } }]), { status: 200 });
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const link = httpBatchLink<any>({
url: "http://mock/api/trpc",
transformer: superjson,
fetch: fetchStub,
});
return createTRPCClient<TRouter>({ links: [link] });
}