init: project skeleton with reference files and CLAUDE.md
This commit is contained in:
commit
d24d0c3e70
11 changed files with 2121 additions and 0 deletions
113
src_ref/server/onboarding.test.ts
Normal file
113
src_ref/server/onboarding.test.ts
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
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);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue