Files
GearBox/.planning/phases/14-postgresql-migration/14-06-PLAN.md

10 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
14-postgresql-migration 06 execute 3
14-01
14-03
14-04
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
true
DB-02
DB-03
truths artifacts key_links
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
path provides contains
tests/services/item.service.test.ts Async item service tests await createTestDb
path provides contains
tests/routes/items.test.ts Async item route tests await createTestDb
path provides contains
tests/mcp/tools.test.ts Async MCP tools tests await createTestDb
from to via pattern
tests/**/*.test.ts tests/helpers/db.ts import { createTestDb } createTestDb
from to via pattern
tests/services/*.test.ts src/server/services/*.ts import service functions 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.

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.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:

// 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:

// 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:

// 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:

// 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:

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:

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" <acceptance_criteria> - 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 </acceptance_criteria> 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:
// Common route test pattern:
function createTestApp() {
  const db = createTestDb();
  // ... create Hono app with db injected
  return { app, db };
}

This must become:

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:

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:

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" <acceptance_criteria> - 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) </acceptance_criteria> 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)

<success_criteria> 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. </success_criteria>

After completion, create `.planning/phases/14-postgresql-migration/14-06-SUMMARY.md`