# HarborForge.Test Integration / end-to-end test harness for the HarborForge platform. It spins up the full stack (MySQL, AbstractWizard, HarborForge.Backend, HarborForge.Frontend) in Docker and runs the backend and frontend test suites against it. Part of the [HarborForge](../README.md) platform. ## Layout ``` HarborForge.Test/ ├── run-test.sh # Quick frontend E2E run (no rebuild) ├── run-test-frontend.sh # Full frontend E2E run (rebuild + optional port expose) ├── cleanup.sh # Tear down containers / wizard config volume ├── docker-compose-frontend.yml # Internal-only test stack ├── docker-compose-frontend-expose.yml# Same stack with ports bound to 127.0.0.1 ├── .env.TEST # Default service ports ├── HarborForge.Backend.Test/ # git submodule — backend pytest suite └── HarborForge.Frontend.Test/ # git submodule — frontend Playwright suite ``` The two test suites are git submodules (see `.gitmodules`). After cloning, initialize them: ```bash git submodule update --init --recursive ``` ## What It Tests ### Backend — `HarborForge.Backend.Test` (pytest) A standalone pytest suite that imports the backend code from `../HarborForge.Backend/` via `tests/conftest.py` and runs against an in-memory SQLite database for fast, isolated unit/integration tests. Configured by `pyproject.toml` (`testpaths = ["tests"]`, verbose, short tracebacks). Coverage spans auth/JWT, users, projects, milestones, tasks, comments, roles/permissions, the milestone and task state machines (`test_milestone_actions.py`, `test_task_transitions.py`), proposals (`test_propose.py`), the monitor endpoint, and miscellaneous endpoints (notifications, activity log, API keys, dashboard). Run it standalone: ```bash python3 -m venv venv source venv/bin/activate pip install -r HarborForge.Backend.Test/requirements.txt cd HarborForge.Backend.Test && pytest # or: pytest -v, pytest tests/test_auth.py ``` See `HarborForge.Backend.Test/README.md` for the full test breakdown. ### Frontend — `HarborForge.Frontend.Test` (Playwright) A Playwright (`@playwright/test`) end-to-end suite that drives the running frontend through a browser. Specs in `tests/` cover the setup wizard, projects editor, milestones, tasks, role editor and proposals (`wizard.spec.ts`, `project-editor.spec.ts`, `milestone.spec.ts`, `task.spec.ts`, `role-editor.spec.ts`, `propose.spec.ts`, `proposal-essential.spec.ts`). Its Docker image runs a helper proxy (`server/proxy.mjs`) alongside `npx playwright test`. > Note: the frontend's own Vitest unit tests live in the > `HarborForge.Frontend` repo; this harness exercises the frontend through > Playwright against the full Docker stack. ## Docker Test Stack `docker-compose-frontend.yml` defines five services on a private `test-network` bridge — `mysql` (MySQL 8, tmpfs storage), `wizard` (AbstractWizard), `backend` (HarborForge.Backend), `frontend` (HarborForge.Frontend), and `test` (the Playwright runner image built from `HarborForge.Frontend.Test/`). Service ports default from `.env.TEST` (`WIZARD_PORT=8080`, `MYSQL_PORT=3306`, `BACKEND_PORT=8000`, `FRONTEND_PORT=3000`). - `docker-compose-frontend.yml` — services are reachable only on the internal network (wizard alone is bound to `127.0.0.1`). - `docker-compose-frontend-expose.yml` — same stack, but mysql, wizard, backend and frontend ports are also bound to `127.0.0.1` for debugging. ## Running the Tests ### Quick run (no rebuild) ```bash ./run-test.sh ``` Brings the stack up from `docker-compose-frontend.yml`, waits (up to ~60s) for the frontend to answer HTTP 200, runs the `test` service once, then tears everything down with `down -v`. ### Full run (rebuild, optional port exposure) ```bash ./run-test-frontend.sh # rebuild all images, run, auto-cleanup ./run-test-frontend.sh --expose-port on # use the *-expose.yml file, keep services up ./run-test-frontend.sh --expose-port off # default: cleanup after the run ``` It loads `.env.TEST`, rebuilds the frontend (with build arg `VITE_API_BASE=http://backend:8000`), backend and test-runner images with `--no-cache`, starts the stack, waits for the frontend, then runs the `test` service with `WORKERS=1`. With `--expose-port on` it uses `docker-compose-frontend-expose.yml` and leaves the stack running for inspection. ### Cleanup ```bash ./cleanup.sh ``` Stops and removes containers/networks (keeps images) and drops the `harborforgetest_wizard_config` volume. The run scripts also call `docker compose ... down -v` themselves on completion (except when port exposure is on). ## CI Notes - Both run scripts use `set -e` and propagate the test container's exit code, so they are CI-friendly: a non-zero `TEST_EXIT_CODE` fails the job. - `run-test-frontend.sh` suppresses build/startup output unless a step fails, in which case it prints the tail of that step's log. - Builds use `--no-cache` and remove prior `harborforge-test-*:dev` images to guarantee a clean stack each run; MySQL uses `tmpfs` so no state persists between runs. - Ensure submodules are initialized (`git submodule update --init --recursive`) before invoking the scripts in CI.