| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
End-to-end test matrix for the Lakekeeper web consoles. One command spins up a full Lakekeeper stack, serves the app, drives real user journeys in a browser, and produces a visual pass/fail dashboard — across both apps, every auth mode, and multiple browsers.
New here? Read Quick start, run just test-one console authn, then open the dashboard. The rest of this doc explains the matrix, the modes, and the gotchas.
Every cell is a full stack brought up from scratch, the app served, and the journeys run end to end:
| app | noauth | authn | authz (OpenFGA) | cedar |
|---|---|---|---|---|
| console | ✅ | ✅ | ✅ | — |
| console-plus | ✅ | ✅ | ✅ | ✅ |
…and each combo runs on chromium (full suite), plus firefox (full parity) and webkit (smoke) as a third dimension. Cedar is premium-only, so it only appears for console-plus.
The modes (this is the whole point — Lakekeeper behaves very differently):
| mode | authN | authZ | notes |
|---|---|---|---|
| noauth | off | off | anonymous; anyone can do anything |
| authn | on | off | must log in; no permission gate |
| authz | on | OpenFGA | relationship-based grants (roles, per-object grants) |
| cedar | on | Cedar | policy-file based; premium only; no roles |
Each spec is a realistic user flow, not a unit test (see specs/):
| spec | what it proves |
|---|---|
| bootstrap/ | first-run server bootstrap (the stepper) |
| auth/login, auth/logout, auth/noauth-access | the auth lifecycle per mode |
| flows/warehouse-lifecycle | create warehouse → see it in the tree → open it → add a namespace (one journey per storage backend) |
| flows/loqe | the in-browser DuckDB-WASM engine: initializes, then creates + queries an Iceberg table end to end (writes parquet to S3 from the browser, reads 1 back) |
| flows/role | role CRUD (authz/cedar) |
| perms/access-control | permission enforcement: a non-admin (anna) is denied reading a table until an admin (peter) grants her — via the Permissions UI (OpenFGA) or a policy edit (Cedar) |
| storage/cors | the storage-CORS gate: a real LoQE SELECT * works on :3001 (the bucket's allowed origin) but is blocked on :3002 — with screenshots/video of the in-app error |
| smoke/route-smoke | major routes render (the cross-browser smoke subset, tagged @smoke) |
Component unit tests (Vitest, in the component repos) run once per matrix and show up on the dashboard too — see Unit tests.
<workspace>/ console-e2e/ ← you are here console/ ← OSS app console-plus/ ← premium app console-components/ ← shared component library lakekeeper/ ← for the Keycloak realm + (optional) policies
cp .env.example .env # non-secret config (paths, ports, images)
cp .env.secret.example .env.secret # secrets (Cedar license, cloud creds)Edit both. .env and .env.secret are git-ignored — never commit them. See Configuration.
just test-setup # npm install + playwright browser download (chromium)
npx playwright install firefox webkit # only if you want the cross-browser dimsjust test-one console authn # one combo (~3 min) — best first run
just test-matrix # the whole matrix (~35 min) — the release gate
just test-dashboard # open the visual matrix in a browserThat's it. just --list shows every recipe.
All recipes are namespaced test-:
| command | what it does |
|---|---|
| just test-setup | install deps + chromium |
| just test-one <app> <mode> | one combo, e.g. just test-one console-plus cedar |
| just test-chrome <app> <mode> | one combo, chromium only (skips firefox/webkit — fast iteration) |
| just test-app <app> | one app, all its modes |
| just test-mode <mode> | one mode, both apps |
| just test-matrix | the full matrix (both apps × all modes × browsers) |
| just test-matrix-chrome | the full matrix, chromium only |
| just test-matrix-docker | docker-image matrix — the pushed lakekeeper-plus image's embedded UI, all modes, silo-only (details) |
| just test-docker <mode> | one mode against the pushed docker image |
| just test-unit | component-repo Vitest unit tests (standalone) |
| just test-coverage | e2e code coverage on the chromium combos (see Coverage) |
| just test-dashboard | build + serve the matrix dashboard |
| just test-catalog | list every defined test case (planning view, no run) |
| just test-report | open the merged Playwright report (traces/video/screenshots) |
| just test-report-combo <app> <mode> | open one combo's report |
| just test-up <mode> [app] | bring the stack up and leave it running (for test-ui) |
| just test-ui [app] [mode] | Playwright UI to browse/run tests (needs test-up first) |
| just test-history | list archived runs (timestamped, kept until you delete them) |
| just test-history-keep <n> | prune to the newest N archives |
| just test-down | tear the stack down |
The normal matrix serves each app from a local npm dev server (testing your working-tree source). just test-matrix-docker instead tests the console that ships inside a pushed lakekeeper-plus image — the embedded UI it serves at :8181/ui, same origin as its API. This validates the release artifact end-to-end, not local source.
just test-matrix-docker # all modes against the pushed image just test-docker authn # one mode
The auto-detected LAN-IP endpoint is verified on macOS/Windows (VM-based runtimes). On native Linux / CI the container→host-IP hairpin may need an explicit S3_LOCAL_ENDPOINT override.
Two files, both git-ignored:
.env — non-secret: image tags, host paths to the sibling repos, APP_PORT, test usernames. Key values:
.env.secret — secrets: the Cedar license key (premium image), and cloud storage credentials (AWS/R2/ADLS/…). Storage backends are skip-if-absent: a backend only runs when its creds are present. ⚠️ Use throwaway, least-privilege keys — never a prod key.
The warehouse + LoQE journeys run per enabled backend (see specs/_data/storage-backends.ts):
LK_BIN=/path/to/lakekeeper-plus runs the catalog as a native binary instead of the compose container:
LK_BIN=~/Biz/lakekeeper-enterprise/target/release/lakekeeper-plus \
SERVED_UI=1 just test-docker authnWhy it exists: a macOS build cannot go into a Linux image, so testing an embedded-UI change would otherwise mean a cross-compile first. SERVED_UI only talks to the backend over HTTP, so a native binary serves the embedded console just as well.
The mode files address services by compose name (postgres:5432, openfga:8081, host.docker.internal), which mean nothing on the host, so run.mjs rewrites each to its published host port — which is why postgres and openfga publish ports at all (on non-default numbers, to coexist with a dev stack). Reachable from both the browser and the lakekeeper container via the host LAN IP (auto-detected by run.mjs to solve the split-horizon problem). Create+verify only (no deep browser flows by default).
Component-repo Vitest tests (e.g. console-components/src/plugins/authToken.test.ts, which guards the token-hydration fix) are browser-independent, so run.mjs runs them once per matrix and shows the result on the dashboard. Run standalone with just test-unit. Disable in a matrix run with NO_UNIT=1.
just test-coverage collects V8 code coverage during the chromium combos (coverage is chromium-only) and maps it back to source via sourcemaps, producing a report per combo under coverage/. It builds console-components with sourcemaps first so coverage maps to real source. (Component-library mapping additionally needs the source-alias — see troubleshooting.) E2E coverage is broad/integration-level; for line coverage of the library use the Vitest unit tests.
docker on this setup is a shell alias to podman (invisible to Node's spawn), and a standalone docker-compose binary targets the wrong socket. run.mjs drives podman compose so it wires podman's own socket. Override with COMPOSE_BIN / COMPOSE_SUBCMD for a real docker install.
The in-browser DuckDB-WASM engine reads/writes Iceberg data straight from the browser to S3. That only works when (a) the app origin is :3001 and the bucket's CORS allows it, and (b) for AWS, the warehouse is STS-enabled (plain access-key creds write to the bucket root and 404). The catalog API is CORS-*, so the tree loads on any origin — but data reads need bucket CORS. The storage/cors test demonstrates :3001 works / :3002 is blocked.
Local Silo must be reachable from both the browser (host) and the lakekeeper container, which see different hostnames. run.mjs auto-detects the host LAN IP and uses it as the single endpoint so the SigV4 signature matches on both sides.
If the app flashes a "Lakekeeper Unreachable / Check status" page, lakekeeper is usually not down — it's a token-hydration race (an early request goes out before the token is ready). The helpers recover from it (_utils/app.ts). It traces back to a real console-components bug worth fixing (the request interceptor should not attach Bearer undefined).
run.mjs frees :3001/:3002 and waits for release before each combo (--strictPort means a half-released port would otherwise fail the server with "address already in use"). If a run dies mid-combo, just test-down cleans up.
LoQE is pinned to DuckDB-WASM 1.4.x; 1.5.x regressed Iceberg writes.
Match the scope to the change:
run.mjs orchestrator (the matrix loop) docker-compose.yml the Lakekeeper stack modes/*.env per-mode backend + VITE_* config cedar/policies.cedar self-contained Cedar base policy (test mutates it) playwright.config.ts dynamic per app/mode/browser dashboard.mjs builds DASHBOARD.html catalog.mjs builds TEST-CATALOG reporters/current.mjs live "now-running test" marker for the dashboard specs/ _data/ storage backends _fixtures/ auth + coverage fixtures _utils/ login, warehouse, loqe, permissions, cedar, app helpers <area>/*.spec.ts the journeys
A run clears every stored result first, so the dashboard never shows "IN PROGRESS" beside columns from an earlier run. Pass --keep-results (or KEEP_RESULTS=1) to preserve combos the run will not touch — the case where the npm matrix and the docker matrix are meant to sit side by side.
| Back | FazBrowse Home | New Git URL |