# Integration Tests Dockerized integration tests for the tbd server. ## Quick Start Run the full test suite (builds the app, starts it, runs tests): ```bash cd integration-test docker-compose up --abort-on-container-exit ``` ## Manual Run (app already running) If your tbd app is running locally on port 3000: ```bash cd integration-test docker run --rm -v "$(pwd)/integration_test.bb:/integration_test.bb:ro" babashka/babashka:latest bb /integration_test.bb http://host.docker.internal:3000 ``` Or run directly on a host with babashka installed: ```bash cd integration-test bb integration_test.bb http://localhost:3000 ``` Or from the repo root, via the script: ```bash script/integration-test ``` ### Options | Flag | Default | Description | |------|---------|--------------| | `[base-url]` (positional) | `http://localhost:3000` | Server to test against | | `--watch` | off | Re-run the suite on a timer instead of exiting after one run | | `--interval ` | `5000` | Delay between runs in watch mode | Example — watch a local server every 2 seconds: ```bash bb integration-test/integration_test.bb http://localhost:3000 --watch --interval 2000 ``` ## What's Tested | # | Test | Checks | |---|------|--------| | 1 | `GET /` returns 200 | HTTP status code | | 2 | `Content-Type` header | `text/html` | | 3 | Response body | The HTML shell: mount point and `/js/main.js` script tag | | 4 | `GET /js/main.js` | 200, JavaScript, non-empty, contains the UI's `/api/add` call | | 5 | `HEAD /` works | HTTP 200 | | 6 | `GET /api/ping` | 200, body `pong` | | 7 | `GET /swagger.json` | 200, JSON, references `/api/ping` | | 8 | `GET /api-docs` | 200, `text/html` | | 9 | `GET /api/add?x=2&y=3` | 200, EDN `{:result 5}` | | 10 | `GET /api/add` with bad params | 400 for a missing or non-numeric param | | 11 | `GET /auth/login` | 302 to Gitea's authorize URL with the client id and a state; `HttpOnly` cookie | | 12 | `GET /auth/callback` with no login in progress | 400 | | 13 | `GET /auth/me` without a session | 401 | | 14 | `POST /nrepl` without a session | 401, even with an invalid body | The app container gets dummy Gitea settings from `docker-compose.yml`, so tests 11-14 cover the unauthenticated surface only; completing a login needs a real Gitea (the unit tests stub one). Test 4 needs the compiled UI, which the Docker image includes (`script/integration-test` builds it). Against a locally running server, run `script/ui-build` first. ## Line Coverage Line coverage is measured with [Cloverage](https://github.com/cloverage/cloverage) for the unit tests, the integration tests, and both combined. From the repo root: | Task | What it does | Output | |------|--------------|--------| | `script/unit-coverage` | Runs `test/` under Cloverage | `target/coverage/unit/` | | `script/integration-coverage` | Runs the integration suite against a Cloverage-instrumented `tbd-app` container | `target/coverage/integration/` | | `script/coverage-report` | Merges the two `lcov.info` files, prints a per-file table | `target/coverage/merged/` | | `script/coverage` | All three, in order (the full suite with a joint report) | all of the above | Each directory contains an `index.html` (open it in a browser) and an `lcov.info`. In the merged report a line counts as covered if either suite hit it; the HTML shows per-line hit counts per suite (`u:` unit, `i:` integration). How the integration numbers are collected: `docker-compose.coverage.yml` starts the app via `tbd.integration.coverage`, which lets Cloverage instrument `src/` and then serves real traffic until it receives SIGTERM. `script/integration-coverage` stops the container (`docker compose stop`) so the report gets written, then copies it out with `docker compose cp`. Plain `script/integration-test` / `script/test` are unchanged and run the uninstrumented app.