Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# SurrealDBFixture
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`SurrealDBFixture` is an integration test fixture that manages the full lifecycle of a SurrealDB v3 container using testcontainers. It implements the `ServiceFixture<SurrealDBConfig>` interface from `@suaveplan/testing-integration`, enabling consistent startup, health checking, and teardown as part of a `TestEnvironment` or standalone usage.
|
||||
|
||||
The fixture supports an env-bridge passthrough mode so developer workstations with live SurrealDB instances can skip container startup entirely — just set the three required environment variables and tests run against the real service without Docker overhead.
|
||||
|
||||
## Features
|
||||
|
||||
- **Env-bridge passthrough**: when `SURREALDB_URL`, `SURREALDB_USERNAME`, and `SURREALDB_PASSWORD` are all set and non-empty, container startup is bypassed and env values are returned directly.
|
||||
- **HTTP health check**: polls `GET /health` on SurrealDB's HTTP port (same port as WebSocket) to verify the service is ready before returning from `start()`.
|
||||
- **Random password per run**: generates a new `crypto.randomUUID()` password each time a container starts, preventing credential reuse across test suites.
|
||||
- **Injectable container factory**: the `containerFactory` option allows unit tests to swap in a fake container without starting Docker, achieving 100% Istanbul coverage without integration dependencies.
|
||||
- **Configurable namespace and database**: override defaults via options to isolate test suites at the logical database level.
|
||||
- **Idempotent stop**: calling `stop()` on an already-stopped or passthrough fixture is safe and does not throw.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```typescript
|
||||
import { SurrealDBFixture } from "@suaveplan/testing-integration-surrealdb";
|
||||
|
||||
const fixture = new SurrealDBFixture();
|
||||
const config = await fixture.start();
|
||||
|
||||
// config.url → "ws://localhost:<randomPort>"
|
||||
// config.username → "root"
|
||||
// config.password → auto-generated UUID
|
||||
// config.namespace → "test"
|
||||
// config.database → "test"
|
||||
|
||||
await fixture.stop();
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```typescript
|
||||
import { SurrealDBFixture } from "@suaveplan/testing-integration-surrealdb";
|
||||
import Surreal from "surrealdb";
|
||||
|
||||
const fixture = new SurrealDBFixture({
|
||||
image: "surrealdb/surrealdb:v3.0.4",
|
||||
namespace: "myapp",
|
||||
database: "integration",
|
||||
});
|
||||
|
||||
const config = await fixture.start();
|
||||
const db = new Surreal();
|
||||
await db.connect(config.url);
|
||||
await db.use({ namespace: config.namespace, database: config.database });
|
||||
await db.signin({ username: config.username, password: config.password });
|
||||
|
||||
// run tests…
|
||||
|
||||
await db.close();
|
||||
await fixture.stop();
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `class SurrealDBFixture`
|
||||
|
||||
Implements `ServiceFixture<SurrealDBConfig>`.
|
||||
|
||||
#### `constructor(options?: SurrealDBFixtureOptions)`
|
||||
|
||||
Creates a new fixture instance. All options are optional.
|
||||
|
||||
#### `name: string`
|
||||
|
||||
Always `"surrealdb"`. Used by `TestEnvironment` as the registry key.
|
||||
|
||||
#### `start(): Promise<SurrealDBConfig>`
|
||||
|
||||
Starts the service. Returns the runtime configuration on success. If all three env vars are set, returns passthrough config immediately. Otherwise starts a testcontainers container and waits for the HTTP health endpoint.
|
||||
|
||||
#### `stop(): Promise<void>`
|
||||
|
||||
Stops the container. No-op in passthrough mode or when `start()` was never called.
|
||||
|
||||
#### `healthCheck(): Promise<boolean>`
|
||||
|
||||
Returns `true` when `GET http://localhost:<port>/health` returns an OK response. Returns `false` if no container is active or the request fails.
|
||||
|
||||
### `interface SurrealDBConfig`
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `url` | `string` | WebSocket URL: `ws://localhost:<port>` |
|
||||
| `namespace` | `string` | SurrealDB namespace |
|
||||
| `database` | `string` | SurrealDB database name |
|
||||
| `username` | `string` | Auth username (always `root` in container mode) |
|
||||
| `password` | `string` | Auth password (random UUID in container mode) |
|
||||
|
||||
### `interface SurrealDBFixtureOptions`
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `image?` | `string` | Docker image override. Defaults to `surrealdb/surrealdb:v3.0.4`. |
|
||||
| `namespace?` | `string` | Namespace override. Defaults to `"test"`. |
|
||||
| `database?` | `string` | Database override. Defaults to `"test"`. |
|
||||
| `containerFactory?` | `(image: string) => GenericContainer` | Injectable factory for unit testing. When provided, replaces the real `GenericContainer` constructor. |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- **Why HTTP health over WebSocket**: the `/health` HTTP endpoint is simpler to poll and does not require a SurrealDB client package in this fixture. WebSocket handshakes are stateful and require protocol negotiation; plain HTTP is sufficient for readiness signalling.
|
||||
- **Why random password per run**: reusing a static password across test runs creates a security surface for tests running in CI with shared Docker networks. UUID-generation via `crypto.randomUUID()` (the Web Crypto API, universally available in modern Bun and Node.js) is both fast and cryptographically random.
|
||||
- **Dynamic import of testcontainers**: `GenericContainer` is dynamically imported inside `start()` to keep the module side-effect-free and to allow the `containerFactory` injection path to bypass the import entirely for unit tests that provide their own factory.
|
||||
- **Port mapping**: testcontainers allocates an ephemeral host port for each `withExposedPorts()` declaration. `getMappedPort(8000)` retrieves the actual host port after the container starts.
|
||||
Reference in New Issue
Block a user