Compare commits

..

38 Commits

Author SHA1 Message Date
fa8c646a5b docs: refresh README — accuracy pass + HarborForge platform context
Verified against current code; fixed stale/inaccurate sections and
documented previously-undocumented features/flags/endpoints. Added a
"Part of the HarborForge platform" reference and role/port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 17:50:02 +01:00
zhi
c96d012fef chore: update backend/frontend test submodule pointers to main head 2026-04-05 22:18:01 +00:00
h z
3f09573631 Merge pull request 'HarborForge.Test: update Frontend.Test submodule ref' (#5) from pr/dev-2026-03-29-frontend-test-submodule-20260405 into main
Reviewed-on: #5
2026-04-05 22:12:10 +00:00
zhi
3cd807566a TEST-FE-PR-001: update Frontend.Test submodule ref 2026-04-05 20:49:09 +00:00
zhi
ef8a4ae994 BE-PR-010: update submodule ref for Backend.Test 2026-03-30 12:50:03 +00:00
zhi
4c54503a81 Update HarborForge.Backend.Test submodule ref 2026-03-30 11:46:26 +00:00
zhi
62d339b58c BE-PR-001: Update submodule ref for Backend.Test 2026-03-29 15:35:54 +00:00
zhi
23cad37e03 test: simplify frontend test runner and rely on image default command
- remove --test-real-plugin option
- stop overriding test container CMD
- let Frontend.Test Dockerfile own proxy startup and playwright launch
2026-03-21 10:10:59 +00:00
zhi
779fb7b387 test: update frontend test defaults and propose suite 2026-03-20 11:38:12 +00:00
zhi
48c54c2f32 test: exclude real-plugin frontend test by default
Only run real-plugin.spec.ts when --test-real-plugin is explicitly provided.
2026-03-20 11:26:14 +00:00
zhi
f5294f5290 chore: update backend test submodule pointer 2026-03-20 09:47:51 +00:00
zhi
11d0865fd3 chore: update Frontend.Test with fixed real-plugin test 2026-03-20 05:08:44 +00:00
zhi
14f4fb8d16 chore: update Frontend.Test with real-plugin.spec.ts 2026-03-19 22:25:28 +00:00
zhi
cc2d4aea5c test: add real plugin integration test and --test-real-plugin option
- Add tests/real-plugin.spec.ts for end-to-end plugin testing
- Add --test-real-plugin flag to run-test-frontend.sh
- Test verifies: server registration, API key generation, heartbeat,
  data persistence, invalid key rejection, key revocation
2026-03-19 22:07:54 +00:00
zhi
5a45a72dcf chore: update Backend.Test submodule with comprehensive test suite
134 backend API tests added as independent project
2026-03-19 12:44:29 +00:00
zhi
ba3909ec68 chore: update Frontend.Test to master (includes task type fix) 2026-03-19 12:25:04 +00:00
805dc2fe32 Merge pull request 'chore: run frontend tests with modal-editor updates' (#4) from feat/modal-edit-permissions-20260316 into master
Reviewed-on: #4
2026-03-16 19:44:45 +00:00
zhi
81fe00bfb8 chore: update frontend test submodule for modal editors 2026-03-16 18:13:54 +00:00
zhi
4707f0614c chore: run frontend tests against dev-mode ui 2026-03-16 16:32:26 +00:00
zhi
c76c25fb5b chore: update frontend test submodule 2026-03-16 13:22:28 +00:00
zhi
1bb11ca92b chore: update Frontend.Test submodule (Issue→Task rename) 2026-03-16 07:48:18 +00:00
zhi
4844b63c16 chore: update Frontend.Test submodule (add task.spec.ts) 2026-03-16 07:26:48 +00:00
zhi
8b1edf53f0 chore: update Frontend.Test submodule (test isolation fix) 2026-03-16 06:32:45 +00:00
zhi
3aaffd2e67 chore: update Frontend.Test submodule (fix milestone test flakiness) 2026-03-16 06:17:48 +00:00
zhi
62ca6bd32b test: use local proxy endpoints for e2e 2026-03-15 22:40:17 +00:00
zhi
15859b9f28 test: use localhost wizard/backend urls 2026-03-15 21:57:39 +00:00
zhi
d3c5f6df8c chore: update test submodule pointers 2026-03-15 16:36:24 +00:00
a4620b9604 Merge pull request 'chore: update backend test submodule' (#3) from chore/remove-backend-test-submodule into master
Reviewed-on: #3
2026-03-15 16:33:14 +00:00
b0d6a0bdd7 Merge branch 'master' into chore/remove-backend-test-submodule 2026-03-15 16:33:02 +00:00
zhi
ebdac827c1 chore: update backend test submodule 2026-03-15 16:30:00 +00:00
2424ec33e0 Merge pull request 'test: rebuild backend/test runner and wait for mysql' (#2) from chore/test-runner-rebuild into master
Reviewed-on: #2
2026-03-15 16:23:45 +00:00
zhi
1047110de5 test: rebuild backend/test runner and wait for mysql 2026-03-15 15:56:03 +00:00
95a6354fc3 Merge pull request 'feature/role-permission-system' (#1) from feature/role-permission-system into master
Reviewed-on: #1
2026-03-15 13:50:28 +00:00
524a4a5b46 Update submodule to latest test files 2026-03-15 13:40:50 +00:00
cf4b9f406b fix: run tests with 1 worker to avoid race conditions 2026-03-15 13:36:32 +00:00
3591ef2c84 fix: add --no-cache to ensure frontend rebuilds with correct API base 2026-03-15 12:57:40 +00:00
4c45a57649 fix: always rebuild frontend with correct VITE_API_BASE 2026-03-15 12:48:12 +00:00
Zhi
1524891b2f chore: remove credentials from submodule urls 2026-03-14 13:21:11 +00:00
7 changed files with 195 additions and 19 deletions

4
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "HarborForge.Backend.Test"] [submodule "HarborForge.Backend.Test"]
path = HarborForge.Backend.Test path = HarborForge.Backend.Test
url = https://zhi:rT5Wjw24mV4all38fIoNQfl2@git.hangman-lab.top/zhi/HarborForge.Backend.Test.git url = https://git.hangman-lab.top/zhi/HarborForge.Backend.Test.git
[submodule "HarborForge.Frontend.Test"] [submodule "HarborForge.Frontend.Test"]
path = HarborForge.Frontend.Test path = HarborForge.Frontend.Test
url = https://zhi:rT5Wjw24mV4all38fIoNQfl2@git.hangman-lab.top/zhi/HarborForge.Frontend.Test.git url = https://git.hangman-lab.top/zhi/HarborForge.Frontend.Test.git

135
README.md
View File

@@ -1 +1,136 @@
# HarborForge.Test # 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.

View File

@@ -74,6 +74,9 @@ services:
restart: "no" restart: "no"
environment: environment:
VITE_API_BASE_URL: http://backend:${BACKEND_PORT:-8000} VITE_API_BASE_URL: http://backend:${BACKEND_PORT:-8000}
VITE_WIZARD_PORT: ${WIZARD_PORT:-8080}
FRONTEND_DEV_MODE: ${FRONTEND_DEV_MODE:-1}
NODE_ENV: development
ports: ports:
- "127.0.0.1:${FRONTEND_PORT:-3000}:${FRONTEND_PORT:-3000}" - "127.0.0.1:${FRONTEND_PORT:-3000}:${FRONTEND_PORT:-3000}"
depends_on: depends_on:
@@ -91,13 +94,16 @@ services:
restart: "no" restart: "no"
environment: environment:
# Use internal service name for test to reach frontend # Use internal service name for test to reach frontend
BASE_URL: http://frontend:${FRONTEND_PORT:-3000} BASE_URL: http://127.0.0.1:${FRONTEND_PORT:-3000}
FRONTEND_URL: http://frontend:${FRONTEND_PORT:-3000} FRONTEND_URL: http://127.0.0.1:${FRONTEND_PORT:-3000}
WEB_SERVER_URL: http://frontend:${FRONTEND_PORT:-3000} WEB_SERVER_URL: http://127.0.0.1:${FRONTEND_PORT:-3000}
WIZARD_URL: http://wizard:${WIZARD_PORT:-8080}/wizard WIZARD_URL: http://127.0.0.1:${WIZARD_PORT:-8080}/wizard
WIZARD_API_URL: http://wizard:${WIZARD_PORT:-8080} WIZARD_API_URL: http://127.0.0.1:${WIZARD_PORT:-8080}
WIZARD_HOST: wizard WIZARD_HOST: wizard
WIZARD_PORT: ${WIZARD_PORT:-8080} WIZARD_PORT: ${WIZARD_PORT:-8080}
BACKEND_URL: http://127.0.0.1:${BACKEND_PORT:-8000}
BACKEND_HOST: backend
FRONTEND_HOST: frontend
CHROME_DEBUGGING_PORT: 9222 CHROME_DEBUGGING_PORT: 9222
networks: networks:
- test-network - test-network

View File

@@ -54,6 +54,9 @@ services:
SECRET_KEY: ${SECRET_KEY:-change_me_in_production} SECRET_KEY: ${SECRET_KEY:-change_me_in_production}
LOG_LEVEL: ${LOG_LEVEL:-INFO} LOG_LEVEL: ${LOG_LEVEL:-INFO}
DATABASE_URL: mysql+pymysql://harborforge:harborforge_pass@mysql:${MYSQL_PORT:-3306}/harborforge DATABASE_URL: mysql+pymysql://harborforge:harborforge_pass@mysql:${MYSQL_PORT:-3306}/harborforge
depends_on:
mysql:
condition: service_healthy
networks: networks:
- test-network - test-network
@@ -69,6 +72,9 @@ services:
environment: environment:
# Use internal service name # Use internal service name
VITE_API_BASE_URL: http://backend:${BACKEND_PORT:-8000} VITE_API_BASE_URL: http://backend:${BACKEND_PORT:-8000}
VITE_WIZARD_PORT: ${WIZARD_PORT:-8080}
FRONTEND_DEV_MODE: ${FRONTEND_DEV_MODE:-1}
NODE_ENV: development
networks: networks:
- test-network - test-network

View File

@@ -1,10 +1,8 @@
#!/bin/bash #!/bin/bash
# Run frontend test with optional port exposure # Run frontend test with optional port exposure
# Usage: ./run-test-frontend.sh [--expose-port {on|off}] # Usage: ./run-test-frontend.sh [--expose-port {on|off}]
# Default: off # Default:
# # --expose-port off: Auto cleanup after test
# --expose-port on: Keep services running after test (manual cleanup required)
# --expose-port off: Auto cleanup after test (default)
set -e set -e
@@ -54,13 +52,44 @@ fi
echo "📦 Using compose file: $COMPOSE_FILE" echo "📦 Using compose file: $COMPOSE_FILE"
run_quiet() {
local label="$1"
shift
local log_file
log_file=$(mktemp)
if "$@" >"$log_file" 2>&1; then
rm -f "$log_file"
return 0
fi
echo "${label} failed"
echo "--- ${label} log ---"
tail -n 200 "$log_file"
rm -f "$log_file"
return 1
}
# Clean any previous containers first # Clean any previous containers first
echo "🧹 Cleaning up previous containers..." echo "🧹 Cleaning up previous containers..."
docker compose -f "$COMPOSE_FILE" down -v 2>/dev/null || true docker compose -f "$COMPOSE_FILE" down -v >/dev/null 2>&1 || true
# Build frontend with correct API base URL (force no cache, remove image first)
echo "🔨 Building frontend..."
docker rmi harborforge-test-frontend:dev >/dev/null 2>&1 || true
run_quiet "frontend build" docker compose -f "$COMPOSE_FILE" build --no-cache --build-arg VITE_API_BASE=http://backend:8000 frontend
# Build backend (force no cache, remove image first)
echo "🔨 Building backend..."
docker rmi harborforge-test-backend:dev >/dev/null 2>&1 || true
run_quiet "backend build" docker compose -f "$COMPOSE_FILE" build --no-cache backend
# Build test runner (force no cache, remove image first)
echo "🔨 Building test runner..."
docker rmi harborforge-test-runner:dev >/dev/null 2>&1 || true
run_quiet "test runner build" docker compose -f "$COMPOSE_FILE" build --no-cache test
# Start services # Start services
echo "📦 Starting services..." echo "📦 Starting services..."
docker compose -f "$COMPOSE_FILE" up -d run_quiet "service startup" docker compose -f "$COMPOSE_FILE" up -d
# Wait for frontend to be ready # Wait for frontend to be ready
echo "⏳ Waiting for services..." echo "⏳ Waiting for services..."
@@ -81,9 +110,9 @@ fi
echo "✅ Services ready!" echo "✅ Services ready!"
# Run test # Run test using the image default CMD so proxy startup stays inside Frontend.Test Dockerfile
echo "🧪 Running test..." echo "🧪 Running test..."
docker compose -f "$COMPOSE_FILE" run --rm test docker compose -f "$COMPOSE_FILE" run --rm -e WORKERS=1 test
TEST_EXIT_CODE=$? TEST_EXIT_CODE=$?
# Cleanup decision based on expose-port # Cleanup decision based on expose-port