Initial Commit
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
## 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
|
||||
Reference in New Issue
Block a user