- tests/n8n/PARITY.md: parity table (health_check ported) + 2 recipe-specific functional tests with rationale + data-integrity section pointing to Phase-1d/1e lifecycle overlays. - tests/n8n/functional/test_health_check.py: parity port of recipe-info/n8n/tests/health_check.py — SOURCE comment. - tests/n8n/functional/test_rest_settings.py: NEW recipe-specific — polls /rest/settings until response is application/json (not the 'n8n is starting up' SPA placeholder); asserts known n8n public-settings keys (userManagement/defaultLocale/authCookie) in the 'data' envelope. Proves the editor SPA's primary API contract is intact. - tests/n8n/functional/test_login_state.py: NEW recipe-specific — polls /rest/login until response is JSON; proves the user-management/auth subsystem initialized on top of the public-settings layer. - tests/n8n/test_install.py: install overlay's Playwright now polls page.goto until status==200 (n8n's / route can return 404 briefly while the SPA route registers on top of /healthz=200). Bounded poll, no bare sleep, raise on persistent failure — same robustness pattern as Phase-1e exec_in_app. Cold-verifiable on cc-ci (log /root/ccci-q1-n8n-r3.log): RECIPE=n8n cc-ci-run runner/run_recipe_ci.py all 5 stages PASS, deploy-count=1, head_ref=63dd3e0f==chaos-version=63dd3e0f, version 3.1.0+2.9.4 -> 3.2.0+2.20.6 (HC1 non-vacuous), 5 lifecycle assertions + 3 custom-stage assertions all PASS. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
44 lines
3.3 KiB
Markdown
44 lines
3.3 KiB
Markdown
# Parity — n8n
|
|
|
|
Phase-2 P2 mapping table: every `references/recipe-maintainer/recipe-info/n8n/tests/*.py` has a
|
|
comparable cc-ci test under `tests/n8n/functional/`, asserting the **same thing** (not a renamed
|
|
file). The Adversary cold-verifies parity by reading the source `recipe-info/<file>` and the cc-ci
|
|
file side-by-side.
|
|
|
|
| recipe-maintainer file | cc-ci file | what's verified | status |
|
|
|---|---|---|---|
|
|
| `recipe-info/n8n/tests/health_check.py` | `tests/n8n/functional/test_health_check.py` | The app is reachable over HTTPS and returns a successful response (the original asserted HTTP 200 against a persistent `n8n.<suffix>` host). The cc-ci port preserves the assertion shape — HTTP 200 from the served root — and adapts to the ephemeral per-run domain via the `live_app` fixture. | **ported** |
|
|
|
|
## Recipe-specific tests (Phase-2 P3, ≥2 beyond parity)
|
|
|
|
n8n's characteristic behavior is **a working REST API on top of a working workflow engine**. /healthz
|
|
returns 200 long before the actual n8n process is ready — the REST endpoints serve a placeholder
|
|
HTML page ("n8n is starting up. Please wait") with status 200 during early boot. So a meaningful
|
|
n8n-specific test must distinguish "the HTTP layer answers" (what generic+install does) from "the
|
|
n8n REST API actually responds with JSON". Two new functional tests:
|
|
|
|
| cc-ci file | what's verified | rationale |
|
|
|---|---|---|
|
|
| `tests/n8n/functional/test_rest_settings.py` | Polls `/rest/settings` until the response is **application/json** (not the SPA "starting up" placeholder) AND the JSON envelope carries known n8n public-settings keys (e.g. `endpointWebhook`, `versionCli`, `n8nMetadata`, `instanceId`). | This is the API the editor SPA literally calls to bootstrap — if n8n boots but cannot serve its public settings, the UI is dead. Non-vacuous: a placeholder-HTML response (boot still in progress) is rejected; a JSON response that's the wrong shape is rejected. |
|
|
| `tests/n8n/functional/test_login_state.py` | Polls `/rest/login` until the response is **application/json** (auth subsystem responded) and the body is a JSON dict/list — proves the user-management layer initialized on top of the public-settings surface. | Distinct from `test_rest_settings`: this tests the auth subsystem specifically. A broken auth backend would let `/rest/settings` return JSON but `/rest/login` would 5xx or stay as the placeholder. |
|
|
|
|
Both tests run in the **custom** tier against the same `live_app` shared deployment as the
|
|
lifecycle overlays — no extra deploy, no extra teardown.
|
|
|
|
## Backup data-integrity (P4)
|
|
|
|
Already exercised by the lifecycle overlays from Phase 1d/1e:
|
|
`tests/n8n/test_backup.py` + `test_restore.py` + `ops.py` (`pre_backup` seeds `"original"` into
|
|
`/home/node/.n8n/ci-marker.txt`; `pre_restore` mutates to `"mutated"`; restore must return the
|
|
volume to `"original"`). Read via `lifecycle.exec_in_app` since n8n state isn't HTTP-served.
|
|
|
|
## Playwright (P6)
|
|
|
|
n8n's UI is the editor SPA — already exercised inline by `tests/n8n/test_install.py::test_serving_and_editor` (lifecycle install overlay), which loads the live editor via Chromium and asserts the
|
|
HTML carries the n8n shell. Adequate for P6 — the editor renders is the canonical browser flow.
|
|
|
|
## Non-ports
|
|
|
|
None — recipe-maintainer's n8n `tests/` directory contains only `health_check.py`, which is fully
|
|
ported above.
|