docs(guide): SPA smoke tests use hiveops-e2e (Playwright)
CD - Develop (guide → bcos.dev) / build-and-deploy (push) Failing after 34m48s
CD - Develop (guide → bcos.dev) / build-and-deploy (push) Failing after 34m48s
"Deploy = smoke test" only told you to curl the endpoint. An SPA returns 200 + index.html for any path, so a curl proves nothing about a frontend feature — which is how dashboard#15 got called "verified" on the strength of a container healthcheck and a bundle grep. Documents hiveiq-src/hiveops-e2e and, more importantly, the trap in front of it: these SPAs cannot be driven by a plain browser. They need X-HiveIQ-Browser: true (nginx's browser gate 302s anything else to the marketing site) and Authorization: Bearer <jwt> (the SPAs carry no auth code; the Electron shell injects it). The headers must be injected at the network layer, not via Playwright's extraHTTPHeaders — those land in the CORS preflight, nginx rejects X-HiveIQ-Browser there, and every XHR fails. The app then renders and says "Failed to load...", which reads as a broken feature and is not. States plainly that coverage is one spec, so nobody assumes the suite has them covered. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -74,3 +74,41 @@ service-to-service calls now route through `hiveiq-nginx`** — live in **platfo
|
||||
## Deploy = smoke test
|
||||
"Deployed" is only true after a curl of the changed endpoint against the live URL returns 200 +
|
||||
a parseable body. A green/healthy container is not a smoke test.
|
||||
|
||||
### For an SPA, curl is not enough — use `hiveops-e2e` (Playwright)
|
||||
|
||||
An SPA returns `200` + `index.html` for **any** path, so a curl proves nothing about the feature —
|
||||
the behaviour lives in the JS bundle. Browser-level verification lives in
|
||||
**`hiveiq-src/hiveops-e2e`**:
|
||||
|
||||
```bash
|
||||
cd hiveops-e2e
|
||||
npm install && npx playwright install chromium # first run only
|
||||
npm run test:dev # against bcos.dev
|
||||
npm run report # HTML report
|
||||
```
|
||||
|
||||
Write the spec so it asserts an **outcome**, not that an element exists.
|
||||
`tests/dashboard-cash-stats.spec.ts` does not check that a total is displayed — it checks that every
|
||||
ATM's total **equals the sum of the cassette values rendered on its row**.
|
||||
|
||||
### ⛔ The two headers, or nothing works
|
||||
|
||||
The SPAs **cannot be driven by a plain browser**, by design. Reproducing what the Electron shell
|
||||
does is the entire job of `fixtures/auth.ts` — use its `appPage` fixture and it is handled for you:
|
||||
|
||||
1. **`X-HiveIQ-Browser: true`** — nginx's browser gate (`snippets/browser-gate.conf`) 302s every
|
||||
request without it to the public marketing site. (This is also why an uptime monitor that follows
|
||||
redirects reports these SPAs green forever.)
|
||||
2. **`Authorization: Bearer <jwt>`** — the SPAs contain **no auth code at all**; the Electron shell
|
||||
injects the token on every request (`hiveops-browser/src/main/main.js`, `onBeforeSendHeaders`).
|
||||
|
||||
**Do NOT put those headers in Playwright's `extraHTTPHeaders`.** Electron injects at the network
|
||||
layer, *after* the browser computes the CORS preflight, so the preflight never advertises them.
|
||||
`extraHTTPHeaders` **do** land in `Access-Control-Request-Headers`; nginx's CORS allowlist does not
|
||||
permit `X-HiveIQ-Browser`, so every XHR dies in preflight — the page renders and the app reports
|
||||
*"Failed to load…"*. **It looks exactly like a broken feature and it is not.** `fixtures/auth.ts`
|
||||
routes the SPA's API calls through Playwright's request context instead.
|
||||
|
||||
> **Coverage today is one spec** (Cash Stats). Everything else is unverified — add a spec when you
|
||||
> ship a feature, rather than assuming the suite covers you.
|
||||
|
||||
Reference in New Issue
Block a user