--- phase: 14-postgresql-migration plan: 06 type: execute wave: 3 depends_on: [14-01, 14-03, 14-04] files_modified: - tests/services/item.service.test.ts - tests/services/category.service.test.ts - tests/services/thread.service.test.ts - tests/services/setup.service.test.ts - tests/services/auth.service.test.ts - tests/services/oauth.service.test.ts - tests/services/csv.service.test.ts - tests/services/image.service.test.ts - tests/services/totals.test.ts - tests/routes/items.test.ts - tests/routes/categories.test.ts - tests/routes/threads.test.ts - tests/routes/setups.test.ts - tests/routes/auth.test.ts - tests/routes/oauth.test.ts - tests/routes/images.test.ts - tests/routes/params.test.ts - tests/mcp/tools.test.ts autonomous: true requirements: [DB-02, DB-03] must_haves: truths: - "All 18 test files use async createTestDb() in beforeEach" - "All test assertions await async service/route calls" - "bun test tests/ passes with zero failures" - "No test file imports from bun:sqlite or drizzle-orm/bun-sqlite" artifacts: - path: "tests/services/item.service.test.ts" provides: "Async item service tests" contains: "await createTestDb" - path: "tests/routes/items.test.ts" provides: "Async item route tests" contains: "await createTestDb" - path: "tests/mcp/tools.test.ts" provides: "Async MCP tools tests" contains: "await createTestDb" key_links: - from: "tests/**/*.test.ts" to: "tests/helpers/db.ts" via: "import { createTestDb }" pattern: "createTestDb" - from: "tests/services/*.test.ts" to: "src/server/services/*.ts" via: "import service functions" pattern: "from.*services/" --- Convert all 18 test files to async: await createTestDb(), await all service/route calls, await all assertions involving DB operations. Run the full test suite to confirm everything passes on PGlite. Purpose: This is the final verification that the entire stack works on PostgreSQL. Tests must pass on PGlite (DB-03) and confirm async operations work correctly (DB-02). Output: All tests green. Full `bun test tests/` passes. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/14-postgresql-migration/14-CONTEXT.md @.planning/phases/14-postgresql-migration/14-RESEARCH.md @.planning/phases/14-postgresql-migration/14-01-SUMMARY.md @.planning/phases/14-postgresql-migration/14-03-SUMMARY.md @tests/helpers/db.ts Conversion rules for ALL test files: 1. `beforeEach(() => { db = createTestDb(); })` -> `beforeEach(async () => { db = await createTestDb(); })` 2. Every service call in tests: add `await` (they are now async) 3. Every direct DB call in tests (inserts for setup, selects for assertions): add `await`, remove `.all()/.get()/.run()` 4. Route tests: if using `app.request()`, those are already async. But ensure the test app factory is also async. 5. If `type Db = typeof prodDb` causes type mismatch with PGlite db, use `as any` cast Task 1: Convert all 9 service test files to async tests/services/item.service.test.ts, tests/services/category.service.test.ts, tests/services/thread.service.test.ts, tests/services/setup.service.test.ts, tests/services/auth.service.test.ts, tests/services/oauth.service.test.ts, tests/services/csv.service.test.ts, tests/services/image.service.test.ts, tests/services/totals.test.ts tests/services/item.service.test.ts, tests/services/category.service.test.ts, tests/services/thread.service.test.ts, tests/services/setup.service.test.ts, tests/services/auth.service.test.ts, tests/services/oauth.service.test.ts, tests/services/csv.service.test.ts, tests/services/image.service.test.ts, tests/services/totals.test.ts For EACH of the 9 service test files, apply these changes: **1. Make beforeEach async:** ```typescript // BEFORE: let db: any; beforeEach(() => { db = createTestDb(); }); // AFTER: let db: any; beforeEach(async () => { db = await createTestDb(); }); ``` **2. Add `await` to every service function call in test bodies:** ```typescript // BEFORE: const items = getAllItems(db); const item = createItem(db, { name: "Test", categoryId: 1 }); // AFTER: const items = await getAllItems(db); const item = await createItem(db, { name: "Test", categoryId: 1 }); ``` **3. Add `await` to direct DB calls used for test setup/assertions:** ```typescript // BEFORE: db.insert(schema.items).values({ ... }).run(); const [cat] = db.select().from(schema.categories).all(); // AFTER: await db.insert(schema.items).values({ ... }); const [cat] = await db.select().from(schema.categories); ``` **4. Make test callbacks async if not already:** ```typescript // BEFORE: it("should return all items", () => { // AFTER: it("should return all items", async () => { ``` **5. Handle Db type compatibility:** If TypeScript complains about passing PGlite db to service functions that expect `PostgresJsDatabase`, use `as any` on the db variable: ```typescript let db: any; // Use any to accommodate PGlite/postgres-js type difference ``` **6. OAuth tests -- boolean conversion:** If any OAuth test checks `used === 0` or `used === 1`, change to `used === false` or `used === true`. After converting each file, run it individually: ```bash bun test tests/services/item.service.test.ts ``` Fix any issues before moving to the next file. bun test tests/services/ 2>&1; [ $? -eq 0 ] && echo "PASS" || echo "FAIL" - Every service test file has `beforeEach(async () => { db = await createTestDb(); })` - Every test callback (`it(...)`) that calls service functions or DB is `async` - No test file contains `.all()`, `.get()`, or `.run()` on db objects - No test file imports from `bun:sqlite` or `drizzle-orm/bun-sqlite` - `bun test tests/services/` exits 0 with all tests passing All 9 service test files converted to async and passing on PGlite. Task 2: Convert all route tests + MCP test to async, run full suite tests/routes/items.test.ts, tests/routes/categories.test.ts, tests/routes/threads.test.ts, tests/routes/setups.test.ts, tests/routes/auth.test.ts, tests/routes/oauth.test.ts, tests/routes/images.test.ts, tests/routes/params.test.ts, tests/mcp/tools.test.ts tests/routes/items.test.ts, tests/routes/categories.test.ts, tests/routes/threads.test.ts, tests/routes/setups.test.ts, tests/routes/auth.test.ts, tests/routes/oauth.test.ts, tests/routes/images.test.ts, tests/routes/params.test.ts, tests/mcp/tools.test.ts Route tests typically create a test app with a test database injected. The pattern is usually: ```typescript // Common route test pattern: function createTestApp() { const db = createTestDb(); // ... create Hono app with db injected return { app, db }; } ``` This must become: ```typescript async function createTestApp() { const db = await createTestDb(); // ... create Hono app with db injected return { app, db }; } ``` **For each of the 8 route test files + 1 MCP test file:** 1. Make the test app factory `async` and `await createTestDb()` 2. Make `beforeEach` async if it calls the factory 3. Route tests use `app.request()` which returns a Promise -- these should already be awaited. Verify each test awaits the response. 4. If any test does direct DB calls for setup/assertions, apply same async conversion as service tests 5. Make all test callbacks async **MCP test (tests/mcp/tools.test.ts):** - Same pattern: async createTestDb, await all MCP tool calls - MCP tools internally call services which are now async **After all files converted, run the FULL test suite:** ```bash bun test tests/ ``` This is the gate check. ALL tests must pass. If any test fails: 1. Read the error message carefully 2. Common issues: missing `await`, `.get()` not removed, type mismatch 3. Fix and re-run **Also verify no SQLite references remain anywhere in test files:** ```bash grep -rn "bun:sqlite\|drizzle-orm/bun-sqlite\|\.all()\|\.get()\|\.run()" tests/ ``` Should return NO matches (except possibly string literals in test descriptions). bun test tests/ 2>&1; [ $? -eq 0 ] && echo "PASS" || echo "FAIL" - Every route test file has async `createTestApp` or async `beforeEach` with `await createTestDb()` - Every test callback is `async` - tests/mcp/tools.test.ts uses `await createTestDb()` - `grep -rn "bun:sqlite\|drizzle-orm/bun-sqlite" tests/` returns NO matches - `bun test tests/` exits 0 with ALL tests passing (zero failures) All 18 test files pass on PGlite. Full test suite green. No SQLite test infrastructure remains. - `bun test tests/` -- ALL tests pass (exit code 0) - `grep -rn "bun:sqlite\|drizzle-orm/bun-sqlite" tests/` -- NO matches - `grep -rn "\.all()\b" tests/ | grep -v "describe\|it(" ` -- NO matches on DB calls (may appear in test descriptions) All 18 test files converted to async PGlite. Full test suite (`bun test tests/`) passes with zero failures. No SQLite test infrastructure remains anywhere in the tests/ directory. After completion, create `.planning/phases/14-postgresql-migration/14-06-SUMMARY.md`