From ceeeb4fc0d066944373316b99692b853a4614474 Mon Sep 17 00:00:00 2001 From: Rajat Saxena Date: Mon, 2 Nov 2026 23:01:04 +0530 Subject: [PATCH 1/3] test(automation): don't let the sequence journey tests depend on today's date Enrollment stamps a contact's entry with the faked clock, but the seeded sequence and emails got updated_at from Postgres's real now(). Once the hard-coded start (2026-11-02T09:00Z) passed, the early-send check saw the sequence as changed after entry and skipped its report, so 'reports an email scheduled before its delay' started failing. Seed those rows at the faked time instead. Co-Authored-By: Claude --- .../api/src/automation/sequence-journey.test.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) 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()}`, From 1a4fe35c5f684b6f637b86537a39f17cfa8b2853 Mon Sep 17 00:00:00 2001 From: Rajat Saxena Date: Mon, 2 Nov 2026 23:13:56 +0530 Subject: [PATCH 2/3] test(mcp): stop the server and parity tests failing the run in the background Both mocked the database as {} and then imported the MCP server, which starts Better Auth. Its OAuth plugin seeds resources in the background with db.select, so each file left an unhandled 'db.select is not a function' and the API test job exited 1 even with every test passing. Use the test database instead, as the other API tests do. Co-Authored-By: Claude --- apps/api/src/mcp/parity.test.ts | 7 ++++++- apps/api/src/mcp/server.test.ts | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/api/src/mcp/parity.test.ts b/apps/api/src/mcp/parity.test.ts index c922d27..1aab3f0 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. +mock.module("../db/client", async () => { + const { makeTestDb } = await import("../test/db.js"); + return { db: await makeTestDb() }; +}); 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..d61702b 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. +mock.module("../db/client", async () => { + const { makeTestDb } = await import("../test/db.js"); + return { db: await makeTestDb() }; +}); const { sendLitMcpTools } = await import("./server"); const { authorizeMcpOperation, listMcpOperationScopes, MCP_SCOPES } = await import( From b1db67e6c2ebbabd0eca419d7e991b3a708fa91b Mon Sep 17 00:00:00 2001 From: Rajat Saxena Date: Mon, 2 Nov 2026 23:48:09 +0530 Subject: [PATCH 3/3] test(mcp): build the test database before mocking it The async mock factory hung the conformance job, where parity.test.ts shares a process with platform-conformance.test.ts. Build the database first and mock it with a plain synchronous factory. Co-Authored-By: Claude --- apps/api/src/mcp/parity.test.ts | 10 +++++----- apps/api/src/mcp/server.test.ts | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/api/src/mcp/parity.test.ts b/apps/api/src/mcp/parity.test.ts index 1aab3f0..8caaaa4 100644 --- a/apps/api/src/mcp/parity.test.ts +++ b/apps/api/src/mcp/parity.test.ts @@ -3,11 +3,11 @@ import { validateParityManifest } from "@codelitdev/mcp-server-kit"; import { contract, mcpParityManifest } from "@sendlit/api-contract"; // The real test database: importing the server starts Better Auth, whose OAuth -// plugin queries it in the background. -mock.module("../db/client", async () => { - const { makeTestDb } = await import("../test/db.js"); - return { db: await makeTestDb() }; -}); +// 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 d61702b..313e283 100644 --- a/apps/api/src/mcp/server.test.ts +++ b/apps/api/src/mcp/server.test.ts @@ -3,11 +3,11 @@ import { mcpParityManifest } from "@sendlit/api-contract"; import { z } from "zod"; // The real test database: importing the server starts Better Auth, whose OAuth -// plugin queries it in the background. -mock.module("../db/client", async () => { - const { makeTestDb } = await import("../test/db.js"); - return { db: await makeTestDb() }; -}); +// 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(