ci: wire integration tests into the CI E2E job
The five \`*.integration.test.ts\` files in apps/journal (explore, follow,
demo-bot, notifications, notifications-fanout — 31 tests total) were
gated behind \`EXPLORE_INTEGRATION=1\` / \`FOLLOW_INTEGRATION=1\` /
\`DEMO_BOT_INTEGRATION=1\` / \`NOTIFICATIONS_INTEGRATION=1\`. The unit-test
job doesn't have Postgres, so they correctly skipped there — but no
CI job set the env vars, so they were effectively dead code.
Added a step in the E2E job (which already has Postgres + schema
pushed) that flips all four gates and runs the integration files
serially (\`--no-file-parallelism\` — they share the schema and trip FK
constraints if run in parallel; ~2.5s sequential anyway).
Wiring them up surfaced two real issues, both fixed here:
1. **\`createRoute\` silently dropped \`input.visibility\`** — every
caller passing \`visibility: \"public\"\` (including the demo-bot)
was getting the column's \`private\` default. Spread now mirrors
\`createActivity\`'s pattern. Demo-bot routes have actually been
private in production all this time — they were rendering on the
home feed only via the \`activity_published\` fan-out from the
*activity*, not as visible *routes*.
2. **The demo-bot test's fetch stub was incomplete** — it stubbed
\`.text()\` but the planner-session preflight calls \`.json()\`. The
stub now branches on URL: \`/api/sessions\` returns
\`{ sessionId: 'test-session' }\` JSON, the BRouter call returns the
stub GPX text.
Full repo: pnpm typecheck, pnpm lint, pnpm test all green
(177 unit-test pass + 31 integration pass = 208 total, no skips).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1263372eef
commit
ded70a5404
3 changed files with 37 additions and 1 deletions
|
|
@ -82,9 +82,26 @@ describe.skipIf(!runIntegration)("demo-bot integration", () => {
|
|||
});
|
||||
|
||||
it("generateOneWalk inserts a public synthetic route + activity", async () => {
|
||||
// createPlannerSession() calls resp.json() (returns { sessionId });
|
||||
// requestBrouterGpx() then calls resp.text() (returns the GPX body).
|
||||
// Stub both so the chain completes without a real Planner running.
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
vi.fn().mockResolvedValue({ ok: true, status: 200, text: async () => STUB_GPX }),
|
||||
vi.fn().mockImplementation((input: string | URL) => {
|
||||
const url = typeof input === "string" ? input : input.toString();
|
||||
if (url.endsWith("/api/sessions")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
status: 200,
|
||||
json: async () => ({ sessionId: "test-session" }),
|
||||
});
|
||||
}
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => STUB_GPX,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
const ownerId = await ensureDemoUser();
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ export async function createRoute(ownerId: string, input: RouteInput) {
|
|||
elevationGain,
|
||||
elevationLoss,
|
||||
dayBreaks,
|
||||
...(input.visibility ? { visibility: input.visibility } : {}),
|
||||
...(input.synthetic ? { synthetic: true } : {}),
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue