6.7 KiB
testing-integration-surrealdb
Purpose
SurrealDB v3.0.4 ServiceFixture for integration tests. Provides env-bridge passthrough (SURREALDB_URL, SURREALDB_USERNAME, SURREALDB_PASSWORD), HTTP health checking on /health, a random password per run, and an injectable container factory. Enables real SurrealDB integration tests without mocks. Depends on @suaveplan/testing-integration and testcontainers.
Requirements
Requirement: SurrealDBFixture implements ServiceFixture
The package SHALL export SurrealDBFixture with name === "surrealdb". SurrealDBConfig SHALL be { url: string; namespace: string; database: string; username: string; password: string }.
Scenario: name property is "surrealdb"
- WHEN an instance's
.nameis read - THEN the value is the literal
"surrealdb"
Verified by: src/fixture/surrealdb-fixture.test.ts::"name property returns surrealdb"
Requirement: Env-bridge passthrough mode (3 vars)
When SURREALDB_URL, SURREALDB_USERNAME, AND SURREALDB_PASSWORD are all set and non-empty, start() MUST return the config directly without starting a container. Namespace/database fall back to SURREALDB_DEFAULT_NAMESPACE/SURREALDB_DEFAULT_DATABASE unless overridden via options. In passthrough mode stop() MUST be a no-op and healthCheck() MUST return false (no container to probe).
Scenario: returns config from env vars
- WHEN all three env vars are set
- THEN
start()returns the config without invoking testcontainers
Scenario: stop is a no-op in passthrough mode
- WHEN the fixture started in passthrough mode and
stop()is called - THEN no container is touched
Scenario: healthCheck returns false in passthrough mode
- WHEN
healthCheck()is called after a passthrough start - THEN the result is
false
Verified by: src/fixture/surrealdb-fixture.test.ts::"passthrough mode: returns config from env vars" AND src/fixture/surrealdb-fixture.test.ts::"passthrough mode: stop is a no-op" AND src/fixture/surrealdb-fixture.test.ts::"passthrough mode: healthCheck returns false when no container"
Requirement: Container mode
When env vars are partially or unset, start() MUST start a SurrealDB v3 container via the injected containerFactory (or GenericContainer), pass start --auth --user <root> --pass <generated> as the command, expose SURREALDB_CONTAINER_PORT, and return { url: "ws://localhost:<port>", namespace, database, username: SURREALDB_DEFAULT_USERNAME, password: <generated> }. Image MUST be overridable. Namespace/database MUST be overridable via constructor options.
Scenario: container mode happy path returns correct config
- WHEN
start()completes container boot - THEN
result.url,namespace,database,username,passwordare populated
Scenario: stop calls container.stop()
- WHEN
stop()followsstart()in container mode - THEN the container's
stop()is invoked exactly once
Scenario: image override: factory called with custom image
- WHEN the fixture is constructed with
image: "x" - THEN the container factory is invoked with
"x"
Scenario: namespace and database overrides reflected in config
- WHEN the fixture is constructed with custom namespace/database
- THEN the returned config uses those overrides
Scenario: factory falls back to dynamic GenericContainer import
- WHEN no
containerFactoryis injected - THEN the fixture dynamically imports testcontainers and uses
GenericContainer
Scenario: start() stops container if getMappedPort throws
- WHEN
getMappedPort()throws after the container has booted - THEN
start()callscontainer.stop()and clears the reference before re-throwing
Verified by: src/fixture/surrealdb-fixture.test.ts::"container mode happy path: returns correct config" AND src/fixture/surrealdb-fixture.test.ts::"container mode: stop calls container.stop()" AND src/fixture/surrealdb-fixture.test.ts::"image override: factory called with custom image" AND src/fixture/surrealdb-fixture.test.ts::"namespace and database overrides reflected in config" AND src/fixture/surrealdb-fixture.test.ts::"resolveContainerFactory: returns factory from dynamic import when no containerFactory" AND src/fixture/surrealdb-fixture.test.ts::"start(): stops container and clears reference when getMappedPort throws"
Requirement: HTTP /health probe
In container mode, healthCheck() MUST GET http://localhost:<mappedPort>/health via the injected fetchFn (default globalThis.fetch) and return res.ok. Network errors MUST be swallowed and return false. Without a started container, healthCheck() MUST return false.
Scenario: returns true when fetchFn returns ok
- WHEN the injected fetch returns
{ ok: true } - THEN
healthCheck()resolves totrue
Scenario: returns false when fetchFn throws
- WHEN the injected fetch throws
- THEN
healthCheck()resolves tofalse
Scenario: returns false when no container
- WHEN
healthCheck()is called beforestart() - THEN the result is
false
Verified by: src/fixture/surrealdb-fixture.test.ts::"container mode: healthCheck returns true when fetchFn returns ok" AND src/fixture/surrealdb-fixture.test.ts::"container mode: healthCheck returns false when fetchFn throws" AND src/fixture/surrealdb-fixture.test.ts::"healthCheck returns false when no container"
Requirement: Random per-run password
In container mode, start() MUST generate the SurrealDB root password via crypto.randomUUID() and use it as both the container start arg and the returned config field. Password reuse across runs MUST NOT occur.
Scenario: generated password matches UUID format
- WHEN
start()runs in container mode - THEN
result.passwordmatches the UUID v4 regex
Verified by: src/fixture/surrealdb-fixture.test.ts::"generated password matches UUID format"
Requirement: stop() is idempotent
stop() MUST be safe to call when no container has been started.
Scenario: stop without start is a no-op
- WHEN
stop()is called on a freshly-constructed fixture - THEN no error is thrown
Verified by: src/fixture/surrealdb-fixture.test.ts::"stop when no container is a no-op"
Requirement: testing-integration is a peer dependency
The package's package.json MUST list @suaveplan/testing-integration and testcontainers in peerDependencies, NOT in dependencies.
Scenario: variant does not bundle the core or testcontainers
- WHEN the published
package.jsonis inspected - THEN
dependenciesdoes not contain either symbol
Verified by: src/fixture/surrealdb-fixture.test.ts::"name property returns surrealdb"