// shared mock ของ @/db สำหรับ route/lib tests ที่ต้องจำลอง drizzle chain // (select().from().where().limit() / insert().values() / update().set().where()) // — ใช้ร่วมโดย vi.mock("@/db", async () => ({ db: createDbMock(state) })) // โดย state เก็บบน globalThis ของ test file (pattern เดียวกับ lib/staged-docs.ts) export type DbMockRow = { id: string; title: string; pdfUrl: string; externalId: string; typeId: string | null; }; export type DbMockState = { /** ค่า default ของ select ทุกครั้ง */ rows: DbMockRow[]; /** override รายครั้งของ select (index = ลำดับการเรียน — undefined = ใช้ rows) */ rowsBySelect: (DbMockRow[] | undefined)[]; selectCalls: number; insertAttempts: Array>; updates: Array<{ cond: unknown; patch: Record }>; /** โค้ด error ของ postgres ที่ insert จะโยน (เช่น "23505") — null = สำเร็จ */ insertErrCode: string | null; }; export function createDbMockState(): DbMockState { return { rows: [], rowsBySelect: [], selectCalls: 0, insertAttempts: [], updates: [], insertErrCode: null, }; } export function createDbMock(state: DbMockState) { return { select: () => ({ from: () => ({ where: () => ({ limit: async (): Promise => { const rows = state.rowsBySelect[state.selectCalls] ?? state.rows; state.selectCalls += 1; return rows.map((r) => ({ ...r })); }, }), }), }), insert: () => ({ values: async (v: Record): Promise => { state.insertAttempts.push(v); if (state.insertErrCode !== null) { throw Object.assign(new Error("db error (mock)"), { code: state.insertErrCode, }); } }, }), update: () => ({ set: (patch: Record) => ({ where: async (cond: unknown): Promise => { state.updates.push({ cond, patch }); }, }), }), }; } /** คืน state ที่ vi.mock factory สร้างไว้บน globalThis (factory รันก่อน import ของ test) */ export function dbMockStateFromGlobal(): DbMockState { const holder = globalThis as typeof globalThis & { __dbMockState?: DbMockState }; if (holder.__dbMockState === undefined) { throw new Error("db mock ยังไม่ถูกสร้าง — vi.mock ต้องรันก่อน"); } return holder.__dbMockState; }