Files
suaveplan/openspec/archive/2026-05-02-surrealdb-integration-tests/tasks.md
2026-05-27 23:29:53 +01:00

90 lines
7.7 KiB
Markdown

# Tasks — surrealdb-integration-tests
## 1. Wiring scaffolding
- [x] 1.1 Add `@suaveplan/testing-integration` and `@suaveplan/testing-integration-surrealdb` as `devDependencies` (workspace:^) of `@suaveplan/database/surrealdb`. Verify peer-dep `testcontainers` resolves at the root.
- [x] 1.2 Create `packages/database/surrealdb/tests/integration/` directory.
- [x] 1.3 Create `packages/database/surrealdb/vitest.integration.config.ts`:
- Reuses `createTestConfig()` from `@suaveplan/testing/config` (pool: forks, polyfills loaded).
- Registers `SurrealDBFixture` via `createIntegrationSetup({ surrealdb: new SurrealDBFixture() })`.
- `test.globalSetup` points at the returned `globalSetup` path.
- `test.include` scoped to `tests/integration/**/*.integration.test.ts` only.
- `test.exclude` excludes `src/**` and `tests/*.test.ts` (unit suite stays untouched).
- [x] 1.4 Add `"test:integration": "vitest run --config vitest.integration.config.ts"` to `packages/database/surrealdb/package.json` scripts.
- [x] 1.5 Add `test:integration` to `turbo.json` pipeline at the repo root: `dependsOn: ["^build"]`, `outputs: []`, `cache: false` (real-services tests are not cacheable).
## 2. Shared integration test utilities
- [x] 2.1 Create `tests/integration/helpers/connect.ts`:
- Exports `connectAdapter(inject)` that calls `skipIfUnavailable("surrealdb", inject)`, reads the injected `SurrealDBConfig`, instantiates `SurrealAdapter`, calls `connect()` + `use({ namespace, database })` + `signin({ username, password })`, and returns `{ adapter, config }`.
- Each test wraps its work in a try/finally that calls `adapter.close()` so a failed assertion never leaks a WS.
- [x] 2.2 Create `tests/integration/helpers/random-ns.ts`:
- Exports `randomNamespace()` returning `test_${crypto.randomUUID().replace(/-/g, "_")}` for per-test isolation against a shared SurrealDB container. Avoids cross-test bleed without container churn.
## 3. Adapter integration tests
- [x] 3.1 `tests/integration/surreal-adapter.integration.test.ts`:
- `connect → use → signin → query "SELECT 1 AS n" → close` returns `[{ n: 1 }]`.
- Parameterised query (`"SELECT $val AS v"`, `{ val: "abc" }`) round-trips the param, proving passthrough is intact and not silently dropped (companion to the `db.create()` drop-content bug).
- `execute("DEFINE TABLE t SCHEMAFULL")` followed by `query("INFO FOR DB")` confirms the DDL took effect on the live engine.
- `transaction(tx => …)` commits when the callback resolves; rollback occurs when it throws (verified by reading the row back outside the transaction).
- Calling any data method before `connect()` throws `DB.NOT_CONNECTED`.
- [x] 3.2 `tests/integration/connection.integration.test.ts`:
- Pointing the adapter at `ws://127.0.0.1:1` (an unbound port) surfaces an error matching `error?.code === "ConnectionRefused" || error?.message?.includes("Unable to connect")`. This is the exact branch the project-memory `surrealdb-create-content-drop`/connection-refused note documents.
- The error is wrapped as `DB.CONNECTION_FAILED` via `@suaveplan/error`.
## 4. Lifecycle integration tests
- [x] 4.1 `tests/integration/singleton.integration.test.ts`:
- `getSingleton("a", factory, config, _, registry)` returns the same connected `DatabaseAdapter` instance on the second call within the same `registry` Map.
- `closeSingleton("a", _, registry)` closes the WS — verified by attempting `adapter.query()` on the previously-returned reference and observing `DB.NOT_CONNECTED`.
- `closeAllSingletons(_, registry)` closes registered singletons in reverse insertion order (assert ordering via close-spies wrapping the adapter).
- Two different `registry` maps stay isolated (passing the explicit Map per the public API).
- [x] 4.2 `tests/integration/version-detector.integration.test.ts`:
- Detector returns a non-empty version string from the live `INFO FOR ROOT` (or equivalent); parsed major matches `3` for the pinned `surrealdb:v3.0.4` image.
- [x] 4.3 `tests/integration/init.integration.test.ts`:
- Initialise a fresh randomised namespace + database; insert a row via the documented `INSERT INTO` workaround (NOT `db.create()`), assert the row reads back unchanged. This is the regression test for the content-drop bug from feedback memory.
- [x] 4.4 `tests/integration/discovery.integration.test.ts`:
- Define two tables with explicit fields, run schema discovery, assert returned shape lists both tables and every field with the expected type.
## 5. Skip / docker-down behaviour
- [x] 5.1 Each integration test's first line is `if (skipIfUnavailable("surrealdb", inject)) return;` so a fully-untouched developer machine (no docker, no env-bridge vars) sees `SKIPPED` instead of a hang or a failure.
- [x] 5.2 Manual verification: with the test stack down, `bun run test:integration --filter=@suaveplan/database/surrealdb` exits 0 with every test reporting skipped.
- [x] 5.3 With docker up (`docker compose -f docker/docker-compose.test.yml up -d`) and `SURREALDB_URL=ws://localhost:7004 SURREALDB_USERNAME=root SURREALDB_PASSWORD=root` exported, the suite runs against the compose container via env-bridge (no testcontainers spin-up).
- [x] 5.4 Without env-bridge vars, the suite spins up its own ephemeral container via testcontainers and tears it down on teardown.
## 6. CI integration
- [x] 6.1 Add a CI job step that runs before `test:integration`: `docker compose -f docker/docker-compose.test.yml up -d --wait` (relies on the existing healthchecks).
- [x] 6.2 Export the env-bridge variables in CI so testcontainers passthrough is taken (faster, single shared instance per job).
- [x] 6.3 Add a final `docker compose -f docker/docker-compose.test.yml down -v` step in `if: always()` to guarantee teardown.
- [x] 6.4 Confirm `bunx turbo test:coverage --filter=@suaveplan/database/surrealdb` is unchanged: integration tests are not counted toward Istanbul coverage of `src/`.
## 7. Documentation
- [x] 7.1 Add an "Integration tests" section to `packages/database/surrealdb/README.md` covering: how to run locally with docker up, how the env-bridge passthrough works, what skipping looks like.
- [x] 7.2 Co-located `.md` siblings for any new helper modules in `tests/integration/helpers/` per the doc-coverage rule.
## 8. OpenSpec gate
- [x] 8.1 Run `openspec validate surrealdb-integration-tests --strict`; resolve any errors.
- [x] 8.2 On ship: fold `specs/database-surrealdb-integration/spec.md` into `openspec/specs/database-surrealdb-integration/spec.md` and move the change folder to `openspec/archive/<yyyy-mm-dd>-surrealdb-integration-tests/`.
---
## Audit Note (2026-05-02)
**Status**: DEFERRED.
State at audit:
- The bulk of the implementation has landed: `packages/database/surrealdb/tests/integration/` contains `surreal-adapter.integration.test.ts`, `connection.integration.test.ts`, `singleton.integration.test.ts`, `version-detector.integration.test.ts`, `init.integration.test.ts`, `discovery.integration.test.ts`, `global-setup.ts`, `integration-setup.ts`, plus a `helpers/` dir.
- `vitest.integration.config.ts` exists; `package.json` carries the `test:integration` script and the two `@suaveplan/testing-integration*` devDependencies.
- Unit-suite remains green (`bunx turbo test --filter=@suaveplan/surrealdb` → 167 tests across 10 files).
Outstanding to ship:
1. **Task 1.5** — wire `test:integration` into `turbo.json` (`dependsOn: ["^build"]`, `outputs: []`, `cache: false`). Currently absent.
2. **Task 6** — add the CI job step (`docker compose up -d --wait`, env-bridge export, `down -v` on `if: always()`).
3. **Task 7.1** — add an "Integration tests" section to `packages/database/surrealdb/README.md` (current README has none).
4. **Task 8** — `openspec validate surrealdb-integration-tests --strict`, then fold spec deltas + archive.