4.9 KiB
ADDED Requirements
Requirement: Layer 0 dep-graph isolation
The @suaveplan/testing-integration-mongodb package's dependencies MUST be exactly @suaveplan/testing-integration (workspace:^) and testcontainers (catalog:integration). No other @suaveplan/* runtime dep is permitted. devDependencies MAY include @suaveplan/testing for the package's own tests.
Scenario: Runtime closure clean
- WHEN
bunx turbo ls --filter=@suaveplan/testing-integration-mongodb...is run - THEN the only
@suaveplan/*package in the runtime closure is@suaveplan/testing-integration
Requirement: Image-pinning policy
The default image MUST be mongo:7.0. The constants/index.ts file MUST carry a # TODO: replace with sha256:<digest> comment until the digest is recorded.
Scenario: Pinned tag
- WHEN the constants file is read
- THEN the image string equals
mongo:7.0AND a sha256 TODO line is present
Requirement: Env-bridge passthrough
The fixture MUST consult MONGODB_URL and MONGODB_DATABASE. When both are present and non-empty, start() MUST skip container creation and return a handle whose config points at the live MongoDB.
Scenario: Live MongoDB present
- WHEN both env vars are set
- THEN
start()returns without invokingcontainerFactoryAND the returned config'surlequalsMONGODB_URL
Scenario: Partial env triggers container
- WHEN
MONGODB_URLis set butMONGODB_DATABASEis empty - THEN
start()falls back to container mode
Requirement: Healthcheck
The fixture MUST run mongosh --eval "db.runCommand('ping')" in-container via the injectable execFn and treat exit code 0 with stdout containing ok as ready. The default healthTimeoutMs MUST be 60000. Callers MAY override.
Scenario: Healthcheck succeeds
- WHEN the in-container
mongoshping returns exit code 0 with{ ok: 1 }stdout - THEN
start()resolves
Scenario: Healthcheck times out
- WHEN the ping never succeeds within
healthTimeoutMs - THEN
start()rejects with codeINTEGRATION.MONGODB.HEALTHCHECK_TIMEOUT
Requirement: Replica-set initialisation
When replicaSet: true is supplied, the fixture MUST start mongod with --replSet rs0 and run rs.initiate() via execFn after the ping healthcheck passes. The fixture MUST NOT resolve start() until rs.status().ok === 1.
Scenario: Replica-set ready
- WHEN
start({ database: 'app', replicaSet: true })resolves - THEN a subsequent
rs.status()call reportsok: 1AND a multi-document transaction succeeds against the returnedurl
Requirement: Authentication mode
When authentication: { username, password } is supplied, the fixture MUST start mongod with --auth, create the supplied user via execFn against the admin database, and embed the credentials in the returned url (mongodb://user:pass@host:port/database).
Scenario: Auth rejects bad credentials
- WHEN the fixture starts in auth mode and a client connects with an incorrect password
- THEN the connection fails with a MongoDB authentication error
Requirement: Config shape
The exported MongoDbConfig interface MUST include database, optional replicaSet?: boolean, optional authentication?: { username: string; password: string }, and the resolved url. A sibling mongodb-fixture.schemas.ts MUST export a Zod MongoDbConfigSchema that validates the same shape.
Scenario: Schema parity
- WHEN
MongoDbConfigSchema.safeParseis run against aMongoDbConfigvalue - THEN valid configs parse OK AND missing required fields fail with
ZodError
Requirement: Error-code prefix
All errors thrown from the fixture MUST carry a code matching ^INTEGRATION\.MONGODB\.[A-Z_]+$.
Scenario: Coded error
- WHEN any fixture method throws
- THEN
codestarts withINTEGRATION.MONGODB.
Requirement: Injectable fakes
The fixture constructor MUST accept containerFactory?: () => GenericContainer and execFn?: (cmd: string[]) => Promise<{ stdout: string; stderr: string; exitCode: number }>. Unit tests MUST be able to drive 100% Istanbul branch coverage without Docker.
Scenario: Fake injection
- WHEN the fixture is constructed with both fakes
- THEN real Docker is never invoked during the test
Requirement: Plugin scenarios
The fixture MUST support, end-to-end against a real container, the following flows in its smoke test:
Scenario: Plain mode write/read round-trip
- WHEN the fixture is started in plain mode and an
insertOnefollowed by afindOneis performed - THEN the inserted document is read back unchanged
Scenario: Replica-set transaction round-trip
- WHEN the fixture is started with
replicaSet: trueand a multi-document transaction is committed - THEN all inserts are visible after
commitTransaction()AND none are visible ifabortTransaction()is called instead