Seven traps that stand between you and a scripted end-to-end real call (operator + customer, real media) against a vuer_oss / vuer_css stack. All of them were found the hard way on 2026-09-07 while building the harness that produced the measurement in janus-memory-leak-rca Part 8.
For Agents
Every one of these fails silently or misleadingly — a skeleton page, an unexplained reload, a zero-length
querySelectorAll, a compatibility check that answersunknown. None of them produce a useful error message. If a vuer browser automation “almost works”, it is almost certainly one of these seven.
1. These apps cannot be driven over plain HTTP — and curl will not tell you
Content-Security-Policy: upgrade-insecure-requests plus Secure cookies mean a real browser cannot use an http:// origin:
- The browser rewrites every subresource to
https://, hits the non-TLS nginx, and every stylesheet and script dies withERR_SSL_PROTOCOL_ERROR. - What you get back is a bare skeleton: the HTML arrives, so it looks served, but nothing is wired — no form handlers, no sockets.
_csrfandvuersidareSecure, so login could never have worked over http anyway.
curl ignores CSP, so curl-over-http ALWAYS looks fine
This is the genuine trap.
curl http://host/…returns 200 with sensible-looking HTML and you conclude the stack is healthy. It is not a valid smoke test for anything browser-driven. Put a TLS proxy in front of the stack before you point a browser at it.
2. The post-login redirect is built from config, not from the request
WebServerAuth.js:821:
https://${config.get('hosts.oss')}${redirectTo}⇒ if you run on a non-standard port, the port must be in hosts.oss. Setting the Host header, or merely reaching the box on :20443, is not enough — the redirect will send the browser to an origin that does not exist.
3. There is a server-side browser gate: GET /api/pre-check
The User-Agent decides whether the app will run at all:
| User-Agent | Verdict returned |
|---|---|
HeadlessChrome/… | unknown |
Chrome/120 | not_compatible |
Chrome/141 | compatible |
⇒ Playwright must use full chromium (channel: 'chromium', not the headless shell) and a realistic, current UA string. Both, not either.
4. The submit handler is attached only once /api/pre-check resolves
After goto, clicking submit too early falls through to a native GET form submit: the URL becomes ?_csrf=…&lastName=… and the page simply reloads. It reads as “the form didn’t do anything”.
⇒ wait for /api/pre-check to resolve before interacting with the form.
5. Operator and customer need SEPARATE browser contexts
Cookies are not port-scoped. Same hostname on two ports = one cookie jar, so a single context leaks the operator session onto the customer origin and the customer page comes up authenticated as the operator.
⇒ one browser.newContext() per participant, always.
6. [data-action="take-call"] lives inside a <template>
So querySelectorAll('[data-action="take-call"]').length === 0 means no customer row was rendered — it does not mean “the button is hidden”. Debug the waiting list, not the button.
7. The registration form’s firstName is letters-only
Pattern ^[a-zA-Z…]{2,25}$. Fixtures containing digits, hyphens or spaces fail client-side validation.
Bonus — the operator sees the customer but has no accept button
Not an environment problem: a role problem, and a real defect. Documented in janus-memory-leak-rca Part 9.
videoChat.receiveCall is granted only to the operator role in config/roles.json, but WebServerAuth.js:934 sets req.session.role = req.user.getMainRole(), and getMainRole() (server/db/model/user.js:187) returns the first entry of acl.roleList present in the user’s rights ⇒ admin for a multi-role user.
Fix: POST /api/role-switch with document.body.dataset.csrftoken — which is exactly what default.layout.js:48 does.
Related
- janus-memory-leak-rca — the measurement this harness was built to produce (Part 8), and the two side-defects it exposed (Part 9)
- fk-dev-deploy-smoke-runbook — deploying and smoke-testing a stack on fk-dev
- fk-dev-partner-branch-deploy-runbook — swapping fk-dev to another partner
- k6-e2e-harness-vuer-oss, playwright-to-k6-translation-recipe — the CI-side browser harness
- vuer_oss, vuer_css, vuer_docker
- FKITDEV-9239 — the Raiffeisen ticket this work sits under
- FaceKom Topics, FaceKom Activity Log