From f4995d987dea7c8854f5080129f2582115928cdc Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Tue, 12 May 2026 19:54:29 +0000 Subject: [PATCH 1/3] fix: correct test mock paths from "./db" to "../db" Fixes incorrect vi.mock paths that were causing tests to fail. The mock path should match the import path in the route files. This addresses the authProvider test mock path issue on PR #2. Co-Authored-By: Paperclip --- apps/api/src/__tests__/auth.test.ts | 2 +- apps/api/src/__tests__/authProvider.test.ts | 2 +- apps/api/src/__tests__/clients.test.ts | 2 +- apps/api/src/__tests__/confirmation.test.ts | 2 +- apps/api/src/__tests__/impersonation.test.ts | 2 +- apps/api/src/__tests__/petPhotos.test.ts | 2 +- apps/api/src/__tests__/portal.test.ts | 2 +- apps/api/src/__tests__/rbac.test.ts | 2 +- apps/api/src/__tests__/search.test.ts | 2 +- apps/api/src/__tests__/setup.test.ts | 2 +- apps/api/src/__tests__/waitlist.test.ts | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/api/src/__tests__/auth.test.ts b/apps/api/src/__tests__/auth.test.ts index f48a775..5446a3e 100644 --- a/apps/api/src/__tests__/auth.test.ts +++ b/apps/api/src/__tests__/auth.test.ts @@ -5,7 +5,7 @@ let dbSelectResult: unknown[] = []; const mockEq = vi.fn((_col: unknown, _val: unknown) => ({ col: _col, val: _val })); const mockDecryptSecret = vi.fn((s: string) => `decrypted:${s}`); -vi.mock("./db", () => { +vi.mock("../db", () => { const authProviderConfig = new Proxy( { _name: "auth_provider_config" }, { diff --git a/apps/api/src/__tests__/authProvider.test.ts b/apps/api/src/__tests__/authProvider.test.ts index 7debf5e..4a7ae90 100644 --- a/apps/api/src/__tests__/authProvider.test.ts +++ b/apps/api/src/__tests__/authProvider.test.ts @@ -38,7 +38,7 @@ const mockGroomer: MockStaff = { id: "staff-3", role: "groomer", isSuperUser: fa // ─── Mock db module ─────────────────────────────────────────────────────────── -vi.mock("./db", () => { +vi.mock("../db", () => { const authProviderConfig = new Proxy( { _name: "auth_provider_config" }, { diff --git a/apps/api/src/__tests__/clients.test.ts b/apps/api/src/__tests__/clients.test.ts index 0c8b77e..9635ec6 100644 --- a/apps/api/src/__tests__/clients.test.ts +++ b/apps/api/src/__tests__/clients.test.ts @@ -40,7 +40,7 @@ function resetMock() { deletedId = null; } -vi.mock("./db", () => { +vi.mock("../db", () => { function makeChainable(data: unknown[]): unknown { const arr = [...data]; const chain = new Proxy(arr, { diff --git a/apps/api/src/__tests__/confirmation.test.ts b/apps/api/src/__tests__/confirmation.test.ts index 22d6f78..a3d4b4f 100644 --- a/apps/api/src/__tests__/confirmation.test.ts +++ b/apps/api/src/__tests__/confirmation.test.ts @@ -39,7 +39,7 @@ function resetMock() { lastUpdate = {}; } -vi.mock("./db", () => { +vi.mock("../db", () => { const appointments = new Proxy( { _name: "appointments" }, { get: (t, p) => (p === "_name" ? "appointments" : { table: "appointments", column: p }) } diff --git a/apps/api/src/__tests__/impersonation.test.ts b/apps/api/src/__tests__/impersonation.test.ts index 20e82c9..ff4b03a 100644 --- a/apps/api/src/__tests__/impersonation.test.ts +++ b/apps/api/src/__tests__/impersonation.test.ts @@ -76,7 +76,7 @@ function makeChainableResult(data: unknown[]): unknown { }); } -vi.mock("./db", () => { +vi.mock("../db", () => { function makeTable(name: string) { return new Proxy( { _name: name }, diff --git a/apps/api/src/__tests__/petPhotos.test.ts b/apps/api/src/__tests__/petPhotos.test.ts index fba8a54..86f7caf 100644 --- a/apps/api/src/__tests__/petPhotos.test.ts +++ b/apps/api/src/__tests__/petPhotos.test.ts @@ -40,7 +40,7 @@ function resetDb() { // ─── Module mocks ───────────────────────────────────────────────────────────── -vi.mock("./db", () => { +vi.mock("../db", () => { const pets = new Proxy( { _name: "pets" }, { get(t, p) { return p === "_name" ? "pets" : {}; } } diff --git a/apps/api/src/__tests__/portal.test.ts b/apps/api/src/__tests__/portal.test.ts index dd9bce7..2388943 100644 --- a/apps/api/src/__tests__/portal.test.ts +++ b/apps/api/src/__tests__/portal.test.ts @@ -47,7 +47,7 @@ function resetMock() { updatedValues = []; } -vi.mock("./db", () => { +vi.mock("../db", () => { function makeChainable(data: unknown[]): unknown { const arr = [...data]; const chain = new Proxy(arr, { diff --git a/apps/api/src/__tests__/rbac.test.ts b/apps/api/src/__tests__/rbac.test.ts index 31943fb..dc3d7de 100644 --- a/apps/api/src/__tests__/rbac.test.ts +++ b/apps/api/src/__tests__/rbac.test.ts @@ -46,7 +46,7 @@ const GROOMER: StaffRow = { let staffLookupResult: StaffRow | null = null; let managerFallbackResult: StaffRow | null = MANAGER; -vi.mock("./db", () => { +vi.mock("../db", () => { const staff = new Proxy( { _name: "staff" }, { diff --git a/apps/api/src/__tests__/search.test.ts b/apps/api/src/__tests__/search.test.ts index 16cf083..ea70632 100644 --- a/apps/api/src/__tests__/search.test.ts +++ b/apps/api/src/__tests__/search.test.ts @@ -23,7 +23,7 @@ const PET_ROW = { let clientResults: typeof ACTIVE_CLIENT[] = []; let petResults: typeof PET_ROW[] = []; -vi.mock("./db", () => { +vi.mock("../db", () => { // Proxy objects for table/column references — values don't matter for tests const tableProxy = (name: string) => new Proxy( diff --git a/apps/api/src/__tests__/setup.test.ts b/apps/api/src/__tests__/setup.test.ts index 3250e9a..a7650df 100644 --- a/apps/api/src/__tests__/setup.test.ts +++ b/apps/api/src/__tests__/setup.test.ts @@ -39,7 +39,7 @@ function clearAuthEnv() { // ─── Mock db module ─────────────────────────────────────────────────────────── -vi.mock("./db", () => { +vi.mock("../db", () => { const authProviderConfig = new Proxy( { _name: "auth_provider_config" }, { diff --git a/apps/api/src/__tests__/waitlist.test.ts b/apps/api/src/__tests__/waitlist.test.ts index 7b85019..46badb5 100644 --- a/apps/api/src/__tests__/waitlist.test.ts +++ b/apps/api/src/__tests__/waitlist.test.ts @@ -49,7 +49,7 @@ function resetMock() { updatedValues = []; } -vi.mock("./db", () => { +vi.mock("../db", () => { function makeChainable(data: unknown[]): unknown { const arr = [...data]; const chain = new Proxy(arr, { -- 2.52.0 From 244888792482e0119d63585df7c3994ca543c10c Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Tue, 12 May 2026 21:13:55 +0000 Subject: [PATCH 2/3] fix: regenerate pnpm-lock.yaml to sync with package.json - Adds missing drizzle-kit, drizzle-orm, postgres dependencies - Addresses CI failures from Lint & Typecheck and Test jobs - Resolves QA feedback from Lint Roller on PR #5 --- pnpm-lock.yaml | 55 ++++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a17944..9857624 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,12 +16,6 @@ importers: '@aws-sdk/s3-request-presigner': specifier: ^3.800.0 version: 3.1041.0 - '@groombook/db': - specifier: workspace:* - version: link:../../packages/db - '@groombook/types': - specifier: workspace:* - version: link:../../packages/types '@hono/node-server': specifier: ^1.13.7 version: 1.19.14(hono@4.12.16) @@ -30,7 +24,10 @@ importers: version: 0.7.6(hono@4.12.16)(zod@4.4.2) better-auth: specifier: ^1.5.6 - version: 1.6.9(vitest@3.2.4(@types/node@22.19.17)(tsx@4.21.0)) + version: 1.6.9(drizzle-kit@0.30.6)(drizzle-orm@0.38.4(kysely@0.28.16)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.17)(tsx@4.21.0)) + drizzle-orm: + specifier: ^0.38.4 + version: 0.38.4(kysely@0.28.16)(postgres@3.4.9) hono: specifier: ^4.6.17 version: 4.12.16 @@ -40,6 +37,9 @@ importers: nodemailer: specifier: ^6.9.16 version: 6.10.1 + postgres: + specifier: ^3.4.5 + version: 3.4.9 stripe: specifier: ^22.0.0 version: 22.1.0(@types/node@22.19.17) @@ -62,6 +62,9 @@ importers: '@vitest/coverage-v8': specifier: ^3.2.4 version: 3.2.4(vitest@3.2.4(@types/node@22.19.17)(tsx@4.21.0)) + drizzle-kit: + specifier: ^0.30.4 + version: 0.30.6 eslint: specifier: ^9.18.0 version: 9.39.4 @@ -78,34 +81,6 @@ importers: specifier: ^3.2.4 version: 3.2.4(@types/node@22.19.17)(tsx@4.21.0) - packages/db: - dependencies: - drizzle-orm: - specifier: ^0.38.4 - version: 0.38.4(kysely@0.28.16)(postgres@3.4.9) - postgres: - specifier: ^3.4.5 - version: 3.4.9 - devDependencies: - '@types/node': - specifier: ^22.10.7 - version: 22.19.17 - drizzle-kit: - specifier: ^0.30.4 - version: 0.30.6 - tsx: - specifier: ^4.19.0 - version: 4.21.0 - typescript: - specifier: ^5.7.3 - version: 5.9.3 - - packages/types: - devDependencies: - typescript: - specifier: ^5.7.3 - version: 5.9.3 - packages: '@ampproject/remapping@2.3.0': @@ -2932,10 +2907,12 @@ snapshots: nanostores: 1.3.0 zod: 4.4.2 - '@better-auth/drizzle-adapter@1.6.9(@better-auth/core@1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.4.0)': + '@better-auth/drizzle-adapter@1.6.9(@better-auth/core@1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(drizzle-orm@0.38.4(kysely@0.28.16)(postgres@3.4.9))': dependencies: '@better-auth/core': 1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0) '@better-auth/utils': 0.4.0 + optionalDependencies: + drizzle-orm: 0.38.4(kysely@0.28.16)(postgres@3.4.9) '@better-auth/kysely-adapter@1.6.9(@better-auth/core@1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(kysely@0.28.16)': dependencies: @@ -3925,10 +3902,10 @@ snapshots: balanced-match@4.0.4: {} - better-auth@1.6.9(vitest@3.2.4(@types/node@22.19.17)(tsx@4.21.0)): + better-auth@1.6.9(drizzle-kit@0.30.6)(drizzle-orm@0.38.4(kysely@0.28.16)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.17)(tsx@4.21.0)): dependencies: '@better-auth/core': 1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0) - '@better-auth/drizzle-adapter': 1.6.9(@better-auth/core@1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.4.0) + '@better-auth/drizzle-adapter': 1.6.9(@better-auth/core@1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(drizzle-orm@0.38.4(kysely@0.28.16)(postgres@3.4.9)) '@better-auth/kysely-adapter': 1.6.9(@better-auth/core@1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(kysely@0.28.16) '@better-auth/memory-adapter': 1.6.9(@better-auth/core@1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.4.0) '@better-auth/mongo-adapter': 1.6.9(@better-auth/core@1.6.9(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.2))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.4.0) @@ -3945,6 +3922,8 @@ snapshots: nanostores: 1.3.0 zod: 4.4.2 optionalDependencies: + drizzle-kit: 0.30.6 + drizzle-orm: 0.38.4(kysely@0.28.16)(postgres@3.4.9) vitest: 3.2.4(@types/node@22.19.17)(tsx@4.21.0) transitivePeerDependencies: - '@cloudflare/workers-types' -- 2.52.0 From 1e70e01046ffffa2435b6f55fc10245c460ce1f8 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Tue, 12 May 2026 21:44:42 +0000 Subject: [PATCH 3/3] fix(api): add UAT Tester staff creation in seed script Adds dedicated SEED_UAT_TESTER_OIDC_SUB handling to create the uat-tester staff record with proper oidcSub mapping to Authentik user PK 237. Fixes GRO-1151 --- apps/api/src/db/seed.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/apps/api/src/db/seed.ts b/apps/api/src/db/seed.ts index 058b7c9..77f6709 100644 --- a/apps/api/src/db/seed.ts +++ b/apps/api/src/db/seed.ts @@ -459,6 +459,32 @@ async function seedKnownUsers() { } } + // ── Staff: UAT Tester (oidcSub from SEED_UAT_TESTER_OIDC_SUB env var) ── + const uatTesterOidcSub = process.env.SEED_UAT_TESTER_OIDC_SUB; + if (uatTesterOidcSub) { + const UAT_TESTER_STAFF_ID = "00000000-0000-0000-0000-000000000007"; + const [existingUatTester] = await db + .select() + .from(schema.staff) + .where(eq(schema.staff.email, "uat-tester@groombook.dev")) + .limit(1); + + if (existingUatTester) { + console.log(`✓ Staff 'UAT Tester' already exists — skipping`); + } else { + await db.insert(schema.staff).values({ + id: UAT_TESTER_STAFF_ID, + name: "UAT Tester", + email: "uat-tester@groombook.dev", + oidcSub: uatTesterOidcSub, + role: "groomer", + isSuperUser: false, + active: true, + }); + console.log(`✓ Created staff 'UAT Tester' (oidcSub: ${uatTesterOidcSub})`); + } + } + // ── Staff: UAT Groomer Personas (SEED_UAT_GROOMER_EMAILS + SEED_UAT_GROOMER_NAMES) ── const groomerEmails = process.env.SEED_UAT_GROOMER_EMAILS?.split(",").map((e) => e.trim()).filter(Boolean) ?? []; const groomerNames = process.env.SEED_UAT_GROOMER_NAMES?.split(",").map((n) => n.trim()).filter(Boolean) ?? []; -- 2.52.0