Exclude integration tests from default pnpm test; opt-in via test:integration

The Redis-publisher integration test uses testcontainers to spin up a real
Redis. On the Gitea CI runner, `container.start()` hangs (likely image-pull
delay or restricted Docker access), and the 60s beforeAll timeout fails the
suite even though both tests ultimately would skip. The skip-on-error path
only fires when start() throws, not when it times out.

Fix: separate unit tests (default) from integration tests (opt-in). The
default `pnpm test` now runs only `test/**/*.test.ts` excluding
`*.integration.test.ts`. A new `pnpm test:integration` script runs them
via `vitest.integration.config.ts` with generous hook/test timeouts for
container startup.

CI runs `pnpm test` and is unaffected by Docker availability. Integration
tests can be run locally or in a future CI job that explicitly provisions
Docker.
This commit is contained in:
2026-04-30 17:38:34 +02:00
parent 33c3fa0c8e
commit 155f034f61
4 changed files with 41 additions and 1 deletions
+12 -1
View File
@@ -51,13 +51,24 @@ See `.env.example` for all variables with descriptions and defaults. The only re
--- ---
## Tests
- `pnpm test` — unit tests only. Fast (~2s), no external dependencies. **This is what CI runs.**
- `pnpm test:integration` — integration tests that need Docker (testcontainers spins up a real Redis). **Opt-in.** Run locally before changes to the Redis publisher, or in a separate CI job with Docker access.
Integration tests live in `test/**/*.integration.test.ts` and are excluded from the default run by `vitest.config.ts`.
---
## CI behavior ## CI behavior
Gitea Actions workflow is at `.gitea/workflows/build.yml`. Gitea Actions workflow is at `.gitea/workflows/build.yml`.
- **Push to `main`** (only when `src/`, `test/`, build config, Dockerfile, or the workflow file itself changes): runs `typecheck`, `lint`, `test`, then builds and pushes the Docker image tagged `:main`. Auto-deploys to stage if a Portainer webhook is configured. - **Push to `main`** (only when `src/`, `test/`, build config, Dockerfile, or the workflow file itself changes): runs `typecheck`, `lint`, `test` (unit tests only), then builds and pushes the Docker image tagged `:main`. Auto-deploys to stage if a Portainer webhook is configured.
- **Manual trigger** (`workflow_dispatch`): same flow, run on demand. - **Manual trigger** (`workflow_dispatch`): same flow, run on demand.
Integration tests are not run in CI — they need Docker access on the runner, which we don't currently configure. Run them locally as needed.
The workflow uses `secrets.REGISTRY_USERNAME` and `secrets.REGISTRY_PASSWORD` for the Gitea registry login — these must be configured in the repo's (or org's) Actions secrets. The workflow uses `secrets.REGISTRY_USERNAME` and `secrets.REGISTRY_PASSWORD` for the Gitea registry login — these must be configured in the repo's (or org's) Actions secrets.
--- ---
+1
View File
@@ -12,6 +12,7 @@
"start": "node dist/main.js", "start": "node dist/main.js",
"test": "vitest run", "test": "vitest run",
"test:watch": "vitest", "test:watch": "vitest",
"test:integration": "vitest run --config vitest.integration.config.ts",
"lint": "eslint .", "lint": "eslint .",
"format": "prettier --write .", "format": "prettier --write .",
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit"
+4
View File
@@ -3,6 +3,10 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({ export default defineConfig({
test: { test: {
include: ['test/**/*.test.ts'], include: ['test/**/*.test.ts'],
// Integration tests need external services (Docker, real Redis). They are
// opt-in via `pnpm test:integration` (see vitest.integration.config.ts).
// Excluding them here keeps `pnpm test` fast and CI-safe.
exclude: ['**/node_modules/**', 'test/**/*.integration.test.ts'],
environment: 'node', environment: 'node',
coverage: { coverage: {
provider: 'v8', provider: 'v8',
+24
View File
@@ -0,0 +1,24 @@
import { defineConfig } from 'vitest/config';
/**
* Vitest config for integration tests that depend on external services
* (Docker, real Redis, etc.). Run via `pnpm test:integration`. Requires
* a working Docker daemon — `testcontainers` will spin up the services
* it needs, then tear them down.
*
* NOT run in default CI. Run locally before changes that touch the
* Redis publisher, or run in a separate CI job that has Docker access.
*/
export default defineConfig({
test: {
include: ['test/**/*.integration.test.ts'],
environment: 'node',
// Container startup can be slow on first run (image pull, ryuk
// container, etc). Allow generous hook + test timeouts.
hookTimeout: 120_000,
testTimeout: 60_000,
},
resolve: {
extensions: ['.ts', '.js'],
},
});