4.5 KiB
ADDED Requirements
Requirement: Layer 0 dep-graph isolation
The @suaveplan/testing-integration-mysql 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-mysql...is run - THEN the only
@suaveplan/*package in the runtime closure is@suaveplan/testing-integration
Requirement: Image-pinning policy
The default image MUST be mysql:8.4. 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
mysql:8.4AND a sha256 TODO line is present
Requirement: Env-bridge passthrough
The fixture MUST consult MYSQL_URL, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD, and MYSQL_ROOT_PASSWORD. When all five are present and non-empty, start() MUST skip container creation and return a handle whose config points at the live MySQL.
Scenario: Live MySQL present
- WHEN all five env vars are set
- THEN
start()returns without invokingcontainerFactoryAND the returned config'surlequalsMYSQL_URL
Scenario: Partial env triggers container
- WHEN
MYSQL_URLis set butMYSQL_ROOT_PASSWORDis empty - THEN
start()falls back to container mode
Requirement: Healthcheck
The fixture MUST run mysqladmin ping -h localhost -p$MYSQL_ROOT_PASSWORD in-container via the injectable execFn and treat exit code 0 with stdout containing mysqld is alive as ready. The default healthTimeoutMs MUST be 90000 (initial DB init can be slow on cold image pulls). Callers MAY override.
Scenario: Healthcheck succeeds
- WHEN in-container
mysqladmin pingreturns exit code 0 withmysqld is alive - THEN
start()resolves
Scenario: Healthcheck times out
- WHEN the ping never succeeds within
healthTimeoutMs - THEN
start()rejects with codeINTEGRATION.MYSQL.HEALTHCHECK_TIMEOUT
Requirement: Charset and collation overrides
The fixture MUST default to charset: 'utf8mb4' and collation: 'utf8mb4_0900_ai_ci' and MUST pass --character-set-server=<charset> and --collation-server=<collation> to mysqld when overrides are supplied via config.
Scenario: UTF-8mb4 default
- WHEN the fixture is started with no charset override
- THEN
SHOW VARIABLES LIKE 'character_set_server'returnsutf8mb4
Scenario: Charset override applied
- WHEN the fixture is started with
charset: 'utf8' - THEN
SHOW VARIABLES LIKE 'character_set_server'returnsutf8
Requirement: Config shape
The exported MySqlConfig interface MUST include database, user, password, rootPassword, optional charset?: string, optional collation?: string, and the resolved url. A sibling mysql-fixture.schemas.ts MUST export a Zod MySqlConfigSchema that validates the same shape.
Scenario: Schema parity
- WHEN
MySqlConfigSchema.safeParseis run against aMySqlConfigvalue - 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\.MYSQL\.[A-Z_]+$.
Scenario: Coded error
- WHEN any fixture method throws
- THEN
codestarts withINTEGRATION.MYSQL.
Requirement: Injectable fakes
The fixture constructor MUST accept containerFactory?: () => GenericContainer and execFn?: (cmd: string[]) => Promise<{ stdout: string; stderr: string; exitCode: number }>. Unit tests MUST 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: Transaction round-trip
- WHEN a transaction inserts rows and commits
- THEN the rows are visible to a subsequent connection AND a rolled-back transaction's rows are not visible
Scenario: DDL post-start
- WHEN
CREATE TABLE,ALTER TABLE ADD COLUMN, andDROP TABLEstatements run afterstart()resolves - THEN each statement succeeds AND
INFORMATION_SCHEMA.TABLESreflects the change