chore: clean up repo structure

- Add node_modules/, test-results/, e2e-report/, .omp/ to .gitignore
- Remove throwaway debug scripts (debug-pw*.js, debug-login-dom.js)
- Remove empty mock-server/ directory
- Untrack harness artifact (.omp/plans/)
- Add missing project files to git (e2e tests, Dockerfiles, tooling configs)
This commit is contained in:
2026-07-12 23:42:54 +05:30
parent eb04a2597d
commit c6c5a04aca
25 changed files with 1400 additions and 1458 deletions

97
docs/PROGRESS.md Normal file
View File

@@ -0,0 +1,97 @@
# Progress: Playwright E2E Tests for luci-app-zt-gateway
## Date: 2026-06-26/2026-06-27
## Completed Fixes
### 1. `login()` Helper (`e2e/utils/auth.ts`)
- **Root cause**: LuCI login form lives inside `<section hidden>`; the visible form is rendered by JS after `ui.instantiateView('bootstrap.sysauth')`. The raw `#luci_username` exists in hidden DOM before the view is ready.
- **Fix**: After `page.goto('/cgi-bin/luci')`, wait for the spinner to disappear:
```ts
await page.waitForFunction(() => {
const view = document.querySelector('#view');
return view && !view.querySelector('.spinning');
}, { timeout: 30_000, polling: 500 });
await page.waitForSelector('#luci_username', { state: 'visible', timeout: 30_000 });
```
- **Post-login navigation**: LuCI with empty root password redirects to `/cgi-bin/luci/` (not `/cgi-bin/luci/admin/...`). Changed `waitForURL` to match `/cgi-bin/luci/`, then wait for the admin page spinner to disappear.
- **`resetToAmsterdam`**: Changed from `page.evaluate(fetch)` to `page.request.post('/ubus')` to avoid "Execution context destroyed" errors when the page navigates during test teardown.
### 2. `overview.js` Parenthesis Mismatch
- **Lines 67 & 208**: `_('UP (%sms').format(latencyMs)` had a missing closing parenthesis.
- **Fix**: Changed to `_('UP (%sms)').format(latencyMs)` in both locations.
### 3. Missing `luci-compat` Package
- **Symptom**: After clicking login, the page returned a 500 error: `module 'luci.ucodebridge' not found`.
- **Cause**: Modern OpenWrt snapshots moved `luci.ucodebridge` out of `luci-base` into a separate package `luci-compat`.
- **Fix**:
- Updated `Dockerfile.openwrt` to include `luci-compat`.
- Because `podman build` in this environment cannot fetch packages at build time (network is blocked inside the build container), a new image was produced by:
1. Running a temporary container with `--network host --entrypoint sh` from the existing image.
2. Installing `luci-compat` (and its dependencies) inside the temp container using `apk add`.
3. Committing the temp container to a new image tag.
4. Replacing the `localhost/zt-gateway-luci:dev` tag with the committed image.
### 4. Missing Volume Mounts for Menu & ACL JSONs
- **Symptom**: Navigating to `/cgi-bin/luci/admin/services/zt-gateway` returned 404: "No page is registered".
- **Fix**: Added `menu.d` and `acl.d` mounts to `docker-compose.yml`.
### 5. Stale ubus Socket on Container Restart
- **Fix**: Modified `docker/openwrt-luci-entrypoint.sh` to remove stale sockets and lock files before starting `ubusd`.
### 6. Network Setup (`docker/openwrt-luci-entrypoint.sh`)
- **Symptom**: `br-zt` had no IPv4 address because `ZTG_PING_IFACE=br-zt` caused the entrypoint to look for the IP on `br-zt` before it was created.
- **Fix**: Changed entrypoint to independently detect `SOURCE_IFACE` (the interface holding `10.99.12.x`) and move its IP to `BRIDGE` (`br-zt`), regardless of `ZTG_PING_IFACE`.
### 7. UCI Config Not Writable
- **Symptom**: `uci commit zt-gateway` failed with "I/O error". The backend could not persist `active_gateway` changes.
- **Root cause**: File-level bind mount (`./root/etc/config/zt-gateway:/etc/config/zt-gateway`) prevents atomic rename on btrfs-backed host filesystem.
- **Fix**: Changed compose to mount `./root/etc/config:/host-config:ro` and added entrypoint logic to copy `zt-gateway` config from `/host-config` into the container's writable overlay at startup.
### 8. UCI Config IPs Updated
- Updated `root/etc/config/zt-gateway` to use `10.99.12.x` (test network) instead of `10.11.12.x`.
### 9. Added State Reset to Test `beforeEach`
- `drain.spec.ts`, `switch.spec.ts`, and `health.spec.ts` now call `resetToAmsterdam(page)` in both `beforeEach` and `afterEach` to ensure each test starts from a clean state.
## Current Blocker: Extreme LuCI Cold-Load Latency
After installing `luci-compat`, login and page rendering work correctly, but **first-load times are extremely long** in fresh browser contexts:
| Step | Time (fresh context) | Notes |
|------|---------------------|-------|
| Login form render | ~11s | Wait for `bootstrap.sysauth` instantiation |
| Admin overview render | ~54s | `admin_status/index` view compilation |
| Admin overview (2nd try) | ~37s | Partial cache warm-up |
| ZT gateway page render | **>120s*** | `zt-gateway/overview` view never renders |
*The ZT gateway page spinner (`Loading view…`) persists beyond 120 seconds. Manual `ui.instantiateView('zt-gateway/overview')` returns instantly but does **not** replace the spinner—`#zt-gateway-root` is never created. There are **no JavaScript console errors** (`sessionid` and `token` are correctly set). The `ubus status` RPC returns correct data when called manually. Root cause of the silent render failure is **unknown**—possibly related to `luci-compat`'s Lua compatibility mode altering the `ui.instantiateView` pipeline, or a race condition in the module loader that only manifests on cold loads.
## Test Results
| Spec | Status | Notes |
|------|--------|-------|
| `login.spec.ts` | **PASS** (when run alone on warm container) | Full form submission + admin navigation works. |
| `overview.spec.ts` | **PASS** (when reached) | Table, radios, active marker assertions pass. |
| `switch.spec.ts` | **UNKNOWN** | Suite times out before reaching it reliably. |
| `drain.spec.ts` | **FAIL** | `beforeEach` times out during `login()` cold load. |
| `health.spec.ts` | **UNKNOWN** | Reaches test body but suite often times out first. |
## Infrastructure State
- **Running image**: `localhost/zt-gateway-luci:dev` (committed from temp container with `luci-compat`).
- **Container**: `openwrt-luci` (from compose, uses staging-dir volume mounts).
- **Networks**: `luci-app-zt-gateway_zt-exit-net` and `luci-app-zt-gateway_zt-gateway-lan` active.
- **br-zt**: Has `10.99.12.2/24`, routing works, ping to gateways succeeds.
## Remaining Work
1. **Diagnose ZT page cold-load hang**: Investigate why `ui.instantiateView('zt-gateway/overview')` silently fails to render on fresh browser contexts. Compare with a non-`luci-compat` image or test a vanilla LuCI page to isolate whether `luci-compat` is the cause.
2. **Evaluate test-timeout strategy**: Options:
- Increase `playwright.config.ts` timeout to 180s+ and accept 10+ minute suite runs.
- Implement a `globalSetup` that logs in once via browser to warm the server cache, then share `storageState` across tests.
- Revert `luci-compat` installation and find an alternative way to provide `luci.ucodebridge` (e.g., copy only the missing file into the image).
3. **Fix `drain.spec.ts` graceful drain panel**: Once login is stable, verify `zt-gateway-switch` in graceful mode actually creates `/var/run/zt-gateway-drain.pid`; if not, the test expectation may need to be relaxed for the containerized environment.
4. **Run full suite end-to-end** after the above blocker is resolved.
5. **Clean up debug scripts**: `debug-pw.js`, `debug-pw2.js`, `debug-pw3.js`, `debug-login-dom.js`.
6. **Rebuild image properly** once build-time network is restored so `luci-compat` is baked in without manual commits.