import { describe, it, expect } from "vitest"; import { z } from "zod"; import { t } from "@/trpc/init"; import { requireAuthenticated, protectedProcedure, } from "@/trpc/require-authenticated"; const echoRouter = t.router({ publicEcho: t.procedure .input(z.object({ value: z.string() }).strict()) .query(({ input }) => input.value), protectedEcho: protectedProcedure .input(z.object({ value: z.string() }).strict()) .mutation(({ input, ctx }) => ({ value: input.value, userId: (ctx as { user: { id: string } }).user.id, })), composedEcho: t.procedure .use(requireAuthenticated) .input(z.object({}).strict()) .mutation(() => "ok"), }); describe("requireAuthenticated middleware (B7)", () => { it("rejects anonymous callers with UNAUTHORIZED", async () => { const caller = echoRouter.createCaller({}); await expect(caller.protectedEcho({ value: "x" })).rejects.toMatchObject({ code: "UNAUTHORIZED", }); await expect(caller.composedEcho({})).rejects.toMatchObject({ code: "UNAUTHORIZED", }); }); it("passes through authenticated callers and exposes ctx.user", async () => { const caller = echoRouter.createCaller({ user: { id: "user-1", roles: [] }, }); await expect(caller.protectedEcho({ value: "x" })).resolves.toEqual({ value: "x", userId: "user-1", }); }); it("leaves public procedures untouched", async () => { const caller = echoRouter.createCaller({}); await expect(caller.publicEcho({ value: "hi" })).resolves.toBe("hi"); }); });