feat(core-testing): RecordingRealtimeBroadcaster (local-type-alias pattern)
This commit is contained in:
@@ -2,3 +2,4 @@ export { RecordingTracer, type RecordedSpan } from "./recording-tracer";
|
||||
export { RecordingLogger, type RecordedCapture } from "./recording-logger";
|
||||
export { RecordingJobQueue } from "./recording-job-queue";
|
||||
export { RecordingEventBus } from "./recording-event-bus";
|
||||
export { RecordingRealtimeBroadcaster } from "./recording-realtime-broadcaster";
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { z } from "zod";
|
||||
import { RecordingRealtimeBroadcaster } from "@/instrumentation/recording-realtime-broadcaster";
|
||||
|
||||
const ch = {
|
||||
name: "test.ch" as const,
|
||||
schema: z.object({ x: z.number() }).strict(),
|
||||
scope: "public" as const,
|
||||
};
|
||||
|
||||
describe("RecordingRealtimeBroadcaster", () => {
|
||||
it("records every broadcast call after schema validation", async () => {
|
||||
const b = new RecordingRealtimeBroadcaster();
|
||||
await b.broadcast(ch, { x: 1 });
|
||||
await b.broadcast(ch, { x: 2 });
|
||||
expect(b.broadcasts).toEqual([
|
||||
{ channel: "test.ch", payload: { x: 1 } },
|
||||
{ channel: "test.ch", payload: { x: 2 } },
|
||||
]);
|
||||
});
|
||||
|
||||
it("rejects payloads that fail schema validation", async () => {
|
||||
const b = new RecordingRealtimeBroadcaster();
|
||||
await expect(b.broadcast(ch, { x: "wrong" } as never)).rejects.toThrow();
|
||||
expect(b.broadcasts).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
// Local type aliases mirroring @repo/core-realtime's contracts. Kept inline to
|
||||
// avoid a build-graph cycle between core-testing (tooling) and core-realtime (core).
|
||||
// Same pattern recording-event-bus + recording-job-queue use.
|
||||
import type { z } from "zod";
|
||||
|
||||
type RealtimeChannelDescriptor<TName extends string, TSchema extends z.ZodType> = {
|
||||
readonly name: TName;
|
||||
readonly schema: TSchema;
|
||||
readonly scope?: string;
|
||||
};
|
||||
|
||||
interface IRealtimeBroadcaster {
|
||||
broadcast<T>(
|
||||
descriptor: RealtimeChannelDescriptor<string, z.ZodType<T>>,
|
||||
payload: T,
|
||||
): Promise<void>;
|
||||
}
|
||||
|
||||
export class RecordingRealtimeBroadcaster implements IRealtimeBroadcaster {
|
||||
readonly broadcasts: { channel: string; payload: unknown }[] = [];
|
||||
|
||||
async broadcast<T>(
|
||||
descriptor: RealtimeChannelDescriptor<string, z.ZodType<T>>,
|
||||
payload: T,
|
||||
): Promise<void> {
|
||||
descriptor.schema.parse(payload);
|
||||
this.broadcasts.push({ channel: descriptor.name, payload });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user