Skip to content

Commit 7403447

Browse files
committed
test: move the real-Postgres suites to e2e/
The end-to-end suites and their harness move from tests/ to the root e2e/ directory, with the database harness and HTTP stub merged into e2e/helpers.ts, to match the repo test layout. bun run test now runs src/ only and the new test:e2e script runs e2e/; CI runs both.
1 parent e62f7db commit 7403447

17 files changed

Lines changed: 79 additions & 69 deletions

‎.github/workflows/ci.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
- run: bun install --frozen-lockfile
2929
- run: bun run typecheck
3030
- run: bun run test
31+
- run: bun run test:e2e
3132
node:
3233
runs-on: ubuntu-latest
3334
strategy:

‎CONTRIBUTING.md‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ Postgres. See `IMPLEMENTATION.md` for how the pieces fit together.
2222
## Running the tests
2323

2424
```bash
25-
bun run typecheck && bun run test
25+
bun run typecheck && bun run test && bun run test:e2e
2626
```
2727

28-
- `bun run test` runs the unit suite in `src/` and the end-to-end suite in
29-
`tests/`. The end-to-end tests drive the mounted routes and migrations
28+
- `bun run test` runs the unit suite in `src/`; `bun run test:e2e` runs the
29+
end-to-end suite in `e2e/`. The end-to-end tests drive the mounted routes and migrations
3030
against a real pgvector Postgres: set `TEST_DATABASE_URL` to a server the
3131
tests can create and drop databases on (for `docker compose up -d`,
3232
`postgres://memory:memory-dev-password@localhost:5434/memory`). Each suite
@@ -68,3 +68,10 @@ numbered file, because a guarded `ADD CONSTRAINT` keeps the old definition.
6868
Contributions require agreeing to the project's CLA — see `CLA.md`. The CLA
6969
bot will comment on your first PR with instructions if you haven't signed
7070
yet.
71+
72+
## Commit messages
73+
74+
Commit subjects and PR titles follow [Conventional Commits](https://www.conventionalcommits.org): `feat`, `fix`, `refactor`, `test`, `docs`, `build`, `ci`, `perf`, and `chore(release): x.y.z` for releases.
75+
Add `!` only for public API breaks: removed or renamed exports, changed signatures, newly required params. Peer and dependency range changes are `build(deps):` with no `!`.
76+
Keep subjects imperative, lowercase after the colon, 72 characters or less, and free of ticket IDs.
77+
Every PR links its issue with a `Closes <issue id>` line in the PR body.

‎docs/RETENTION.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ creator (`created_by_principal_id` — the document's first version for
6464
independent of any share grant. A peer who can search a shared document gets
6565
403 on `forget`/`purge`/`retention-class` for it. See
6666
`src/services/retention-ownership.ts` and the ownership tests in
67-
`tests/grants.test.ts` / `tests/caller-resolver.test.ts`.
67+
`e2e/grants.test.ts` / `e2e/caller-resolver.test.ts`.
6868

6969
**`sweepEphemeral` stays off the HTTP surface.** It is a maintenance sweep —
7070
"deprecate every ephemeral version past its TTL for this tenant" — not
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
seedPrincipal,
1313
testDatabaseUrl,
1414
type TestDb,
15-
} from "./lib/db-harness.ts";
15+
} from "./helpers.ts";
1616

1717
describe.skipIf(testDatabaseUrl() === undefined)("add and search", () => {
1818
let db: TestDb;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
seedPrincipal,
1616
testDatabaseUrl,
1717
type TestDb,
18-
} from "./lib/db-harness.ts";
18+
} from "./helpers.ts";
1919

2020
// A machine caller (e.g. a workflow run) never passes the host's session
2121
// middleware; the host's callerResolver names its tenant and principal.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
seedPrincipal,
1313
testDatabaseUrl,
1414
type TestDb,
15-
} from "./lib/db-harness.ts";
15+
} from "./helpers.ts";
1616

1717
describe.skipIf(testDatabaseUrl() === undefined)("synthesized context rows", () => {
1818
let db: TestDb;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
seedPrincipal,
1313
testDatabaseUrl,
1414
type TestDb,
15-
} from "./lib/db-harness.ts";
15+
} from "./helpers.ts";
1616

1717
describe.skipIf(testDatabaseUrl() === undefined)("distill tick", () => {
1818
let db: TestDb;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
embedTexts,
77
probeEmbedDims,
88
} from "../src/core/embed-client.ts";
9-
import { startHttpStub } from "./lib/http-stub.ts";
9+
import { startHttpStub } from "./helpers.ts";
1010

1111
const stub = startHttpStub();
1212
afterAll(() => stub.stop());
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
seedPrincipal,
1313
testDatabaseUrl,
1414
type TestDb,
15-
} from "./lib/db-harness.ts";
15+
} from "./helpers.ts";
1616

1717
describe.skipIf(testDatabaseUrl() === undefined)("grants, forget and purge", () => {
1818
let db: TestDb;
Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Real-Postgres harness for the tests/ suite. Each suite gets a fresh
1+
// Real-Postgres harness for the e2e/ suites. Each suite gets a fresh
22
// database on the server named by TEST_DATABASE_URL (any pgvector Postgres
33
// whose user can create databases, such as compose.yml's), with Interchange's control-plane tables and the memory
44
// migrations applied; `close` drops it.
@@ -9,10 +9,10 @@ import { createRequireGrant, type TenantEnv } from "@intx/hub-api";
99
import { Hono } from "hono";
1010
import postgres from "postgres";
1111

12-
import { createMemory, type Memory } from "../../src/memory.ts";
13-
import type { MemoryConfig } from "../../src/mount-config.ts";
14-
import { runMemoryMigrations } from "../../src/migrations.ts";
15-
import { createMemoryRoutes } from "../../src/routes/mount.ts";
12+
import { createMemory, type Memory } from "../src/memory.ts";
13+
import type { MemoryConfig } from "../src/mount-config.ts";
14+
import { runMemoryMigrations } from "../src/migrations.ts";
15+
import { createMemoryRoutes } from "../src/routes/mount.ts";
1616

1717
const FTS_LANGUAGE = "english";
1818

@@ -49,7 +49,7 @@ export type TestDb = {
4949
export async function createEmptyDb(): Promise<TestDb> {
5050
const serverUrl = testDatabaseUrl();
5151
if (serverUrl === undefined) {
52-
throw new Error("TEST_DATABASE_URL is required for the tests/ suite");
52+
throw new Error("TEST_DATABASE_URL is required for the e2e/ suites");
5353
}
5454
const url = new URL(serverUrl);
5555
const database = `memory_test_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
@@ -205,3 +205,50 @@ export function createTestApp(opts: {
205205
);
206206
return app;
207207
}
208+
209+
// A local HTTP server standing in for an embed or rerank endpoint. Each test
210+
// sets `reply`; every request is recorded with its path, auth header and
211+
// JSON body (both clients only send JSON).
212+
213+
export type StubRequest = {
214+
path: string;
215+
authorization: string | null;
216+
body: unknown;
217+
};
218+
219+
export type HttpStub = {
220+
url: string;
221+
requests: StubRequest[];
222+
reply: (req: StubRequest) => Response | Promise<Response>;
223+
reset: () => void;
224+
stop: () => void;
225+
};
226+
227+
const unconfigured = () => new Response("no reply configured", { status: 500 });
228+
229+
export function startHttpStub(): HttpStub {
230+
const stub: HttpStub = {
231+
url: "",
232+
requests: [],
233+
reply: unconfigured,
234+
reset: () => {
235+
stub.requests.length = 0;
236+
stub.reply = unconfigured;
237+
},
238+
stop: () => server.stop(true),
239+
};
240+
const server = Bun.serve({
241+
port: 0,
242+
async fetch(req) {
243+
const recorded: StubRequest = {
244+
path: new URL(req.url).pathname,
245+
authorization: req.headers.get("authorization"),
246+
body: await req.json(),
247+
};
248+
stub.requests.push(recorded);
249+
return stub.reply(recorded);
250+
},
251+
});
252+
stub.url = server.url.href.replace(/\/$/, "");
253+
return stub;
254+
}

0 commit comments

Comments
 (0)