Files
2026-05-27 23:29:53 +01:00

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.4 AND 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 invoking containerFactory AND the returned config's url equals MYSQL_URL

Scenario: Partial env triggers container

  • WHEN MYSQL_URL is set but MYSQL_ROOT_PASSWORD is 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 ping returns exit code 0 with mysqld is alive
  • THEN start() resolves

Scenario: Healthcheck times out

  • WHEN the ping never succeeds within healthTimeoutMs
  • THEN start() rejects with code INTEGRATION.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' returns utf8mb4

Scenario: Charset override applied

  • WHEN the fixture is started with charset: 'utf8'
  • THEN SHOW VARIABLES LIKE 'character_set_server' returns utf8

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.safeParse is run against a MySqlConfig value
  • 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 code starts with INTEGRATION.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, and DROP TABLE statements run after start() resolves
  • THEN each statement succeeds AND INFORMATION_SCHEMA.TABLES reflects the change