diff --git a/apps/api/src/automation/sequence-journey.test.ts b/apps/api/src/automation/sequence-journey.test.ts index 23e9ede..c06d43f 100644 --- a/apps/api/src/automation/sequence-journey.test.ts +++ b/apps/api/src/automation/sequence-journey.test.ts @@ -22,7 +22,10 @@ const captureEvent = vi.fn(); mock.module("../observability", () => ({ ...observability, captureEvent })); const { db } = await import("../db/client"); -const { ongoingSequences, rules } = await import("../db/schema"); +const { ongoingSequences, rules, sequenceEmails, sequences } = await import( + "../db/schema" +); +const { eq } = await import("drizzle-orm"); const { EventType } = await import("../config/constants"); const { sendMail } = await import("../mail/send"); const { seedTeamAndContact, truncateAll } = await import("../test/db"); @@ -69,6 +72,18 @@ async function subscribeAt( ) { const { team, contact } = await seedTeamAndContact(tdb); const { sequenceRow } = await seedSequence(tdb, { teamId: team.id, emails }); + // The database stamps these with the real time, but enrollment uses the + // faked clock. Seed them at `at` so a past `at` doesn't look like the + // sequence changed after the contact entered. + const seededAt = new Date(at); + await tdb + .update(sequences) + .set({ createdAt: seededAt, updatedAt: seededAt }) + .where(eq(sequences.id, sequenceRow.id)); + await tdb + .update(sequenceEmails) + .set({ createdAt: seededAt, updatedAt: seededAt }) + .where(eq(sequenceEmails.sequenceId, sequenceRow.id)); await tdb.insert(rules).values({ teamId: team.id, ruleId: `rule_${crypto.randomUUID()}`, diff --git a/apps/api/src/mcp/parity.test.ts b/apps/api/src/mcp/parity.test.ts index c922d27..8caaaa4 100644 --- a/apps/api/src/mcp/parity.test.ts +++ b/apps/api/src/mcp/parity.test.ts @@ -2,7 +2,12 @@ import { describe, expect, it, mock } from "bun:test"; import { validateParityManifest } from "@codelitdev/mcp-server-kit"; import { contract, mcpParityManifest } from "@sendlit/api-contract"; -mock.module("../db/client", () => ({ db: {}, pool: {} })); +// The real test database: importing the server starts Better Auth, whose OAuth +// plugin queries it in the background. Built before mocking, so the factory is +// synchronous: platform-conformance.test.ts shares this process in CI. +const { makeTestDb } = await import("../test/db"); +const testDb = await makeTestDb(); +mock.module("../db/client", () => ({ db: testDb, pool: {} })); const { createSendLitMcp } = await import("./server"); diff --git a/apps/api/src/mcp/server.test.ts b/apps/api/src/mcp/server.test.ts index 71b4c6f..313e283 100644 --- a/apps/api/src/mcp/server.test.ts +++ b/apps/api/src/mcp/server.test.ts @@ -2,7 +2,12 @@ import { describe, expect, it, mock } from "bun:test"; import { mcpParityManifest } from "@sendlit/api-contract"; import { z } from "zod"; -mock.module("../db/client", () => ({ db: {}, pool: {} })); +// The real test database: importing the server starts Better Auth, whose OAuth +// plugin queries it in the background. Built before mocking, so the factory is +// synchronous and safe when other files share the process. +const { makeTestDb } = await import("../test/db"); +const testDb = await makeTestDb(); +mock.module("../db/client", () => ({ db: testDb, pool: {} })); const { sendLitMcpTools } = await import("./server"); const { authorizeMcpOperation, listMcpOperationScopes, MCP_SCOPES } = await import(