113 lines
3.3 KiB
TypeScript
113 lines
3.3 KiB
TypeScript
import { describe, expect, it, vi, beforeEach } from "vitest";
|
|
import { appRouter } from "./routers";
|
|
import type { TrpcContext } from "./_core/context";
|
|
|
|
// Mock DB helpers — must include ALL exports from server/db.ts
|
|
vi.mock("./db", () => ({
|
|
getDb: vi.fn().mockResolvedValue(null),
|
|
upsertUser: vi.fn(),
|
|
getUserByOpenId: vi.fn(),
|
|
getSubscription: vi.fn().mockResolvedValue({
|
|
id: 1,
|
|
userId: 1,
|
|
plan: "trial",
|
|
status: "trialing",
|
|
trialEndsAt: new Date(Date.now() + 30 * 86400000),
|
|
currentPeriodEnd: null,
|
|
stripeCustomerId: null,
|
|
stripeSubscriptionId: null,
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
}),
|
|
updateSubscription: vi.fn(),
|
|
isSubscriptionActive: vi.fn().mockResolvedValue(true),
|
|
getClinics: vi.fn().mockResolvedValue([]),
|
|
getClinicById: vi.fn().mockResolvedValue(null),
|
|
createClinic: vi.fn().mockResolvedValue({ insertId: 42 }),
|
|
updateClinic: vi.fn(),
|
|
rotateQrToken: vi.fn(),
|
|
getActiveQueue: vi.fn().mockResolvedValue([]),
|
|
getQueueEntry: vi.fn().mockResolvedValue(null),
|
|
getQueueEntryByToken: vi.fn().mockResolvedValue(null),
|
|
addToQueue: vi.fn().mockResolvedValue({ insertId: 1 }),
|
|
updateQueueEntry: vi.fn(),
|
|
reorderQueue: vi.fn(),
|
|
logAnalyticsEvent: vi.fn(),
|
|
getAnalytics: vi.fn().mockResolvedValue([]),
|
|
}));
|
|
|
|
function makeAuthCtx(overrides: Partial<TrpcContext> = {}): TrpcContext {
|
|
return {
|
|
user: {
|
|
id: 1,
|
|
openId: "test-user",
|
|
email: "doctor@test.fr",
|
|
name: "Dr. Test",
|
|
loginMethod: "manus",
|
|
role: "user",
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
lastSignedIn: new Date(),
|
|
},
|
|
req: { protocol: "https", headers: {} } as TrpcContext["req"],
|
|
res: { clearCookie: vi.fn() } as unknown as TrpcContext["res"],
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("clinic.create", () => {
|
|
it("creates a clinic and returns success with id", async () => {
|
|
const ctx = makeAuthCtx();
|
|
const caller = appRouter.createCaller(ctx);
|
|
|
|
const result = await caller.clinic.create({
|
|
name: "Cabinet Dr. Test",
|
|
avgConsultationMinutes: 15,
|
|
maxQueueSize: 30,
|
|
qrRotationMinutes: 60,
|
|
});
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(typeof result.id).toBe("number");
|
|
});
|
|
|
|
it("requires a name of at least 2 characters", async () => {
|
|
const ctx = makeAuthCtx();
|
|
const caller = appRouter.createCaller(ctx);
|
|
|
|
await expect(
|
|
caller.clinic.create({ name: "A" })
|
|
).rejects.toThrow();
|
|
});
|
|
});
|
|
|
|
describe("clinic.list", () => {
|
|
it("returns an array for authenticated user", async () => {
|
|
const ctx = makeAuthCtx();
|
|
const caller = appRouter.createCaller(ctx);
|
|
|
|
const result = await caller.clinic.list();
|
|
expect(Array.isArray(result)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("subscription.get", () => {
|
|
it("returns subscription for authenticated user", async () => {
|
|
const ctx = makeAuthCtx();
|
|
const caller = appRouter.createCaller(ctx);
|
|
|
|
const result = await caller.subscription.get();
|
|
expect(result).toBeDefined();
|
|
expect(result?.status).toBe("trialing");
|
|
});
|
|
});
|
|
|
|
describe("analytics.getAll", () => {
|
|
it("returns analytics data for authenticated user", async () => {
|
|
const ctx = makeAuthCtx();
|
|
const caller = appRouter.createCaller(ctx);
|
|
|
|
const result = await caller.analytics.getAll({ days: 7 });
|
|
expect(Array.isArray(result)).toBe(true);
|
|
});
|
|
});
|