diff --git a/README.md b/README.md index 43536e8..c2f83bc 100644 --- a/README.md +++ b/README.md @@ -112,9 +112,13 @@ All recipes are namespaced `test-`: | --- | --- | | `just test-setup` | install deps + chromium | | `just test-one ` | one combo, e.g. `just test-one console-plus cedar` | +| `just test-chrome ` | one combo, **chromium only** (skips firefox/webkit — fast iteration) | | `just test-app ` | one app, all its modes | | `just test-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, seaweedfs-only ([details](#testing-the-shipped-docker-image)) | +| `just test-docker ` | 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](#coverage)) | | `just test-dashboard` | build + serve the matrix dashboard | @@ -133,8 +137,10 @@ All recipes are namespaced `test-`: - **`just test-dashboard`** → `DASHBOARD.html`: every test × every app·mode·browser with the latest pass/fail. Frozen header + frozen first column, scrollable. While a - run is active it shows an **in-progress** banner with the **live test name**. It - *accumulates* across runs (a partial run only updates its own columns). + run is active it shows an **in-progress** banner with the **live test name**. Each + run **resets** the matrix to just that run's combos (every `just test-*` clears the + previous run's results at start); past runs stay browsable via the **archived-run + dropdown** at the top of the page. - **`just test-report`** → the merged Playwright report: traces, video, and a screenshot of every step (e.g. the CORS test's `:3001` result vs `:3002` error box). - **`just test-catalog`** → `TEST-CATALOG.md`/`.html`: what test cases exist, ordered @@ -144,6 +150,34 @@ All recipes are namespaced `test-`: --- +## Testing the shipped Docker image + +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. + +- **Image**: `LK_IMAGE_DOCKER` in `.env` (pinned tag; arm64 for Apple-Silicon podman). +- **No npm server**: `SERVED_UI=1` points Playwright's `baseURL` at `:8181`; the pre-built + image is configured via `LAKEKEEPER__UI__*` (no `VITE_*`). Needs the license key. +- **SeaweedFS only, fully local (no AWS)**: cloud backends are disabled; the local + SeaweedFS warehouse vends short-lived creds via **STS** so the in-browser LoQE + write/read round-trip works. `S3_LOCAL_DEEP=1` turns on the deep flows (LoQE + + access-control) for it; wildcard bucket CORS makes the `:3002` CORS-negative test moot. +- **Split-horizon**: the warehouse endpoint is the **host LAN IP** (`run.mjs` auto-detects + it) so it resolves from *both* the lakekeeper container and the host browser. + +``` +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. + +--- + ## Configuration Two files, both git-ignored: diff --git a/package-lock.json b/package-lock.json index 63e1f7c..23022f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,10 @@ }, "devDependencies": { "@playwright/test": "^1.49.0", + "@types/node": "^22.10.0", "dotenv": "^16.4.5", - "monocart-reporter": "^2.12.1" + "monocart-reporter": "^2.12.1", + "typescript": "^5.6.3" } }, "node_modules/@playwright/test": { @@ -33,6 +35,16 @@ "node": ">=18" } }, + "node_modules/@types/node": { + "version": "22.20.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz", + "integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -760,6 +772,27 @@ "url": "https://opencollective.com/express" } }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 40053e8..f5fa585 100644 --- a/package.json +++ b/package.json @@ -26,11 +26,14 @@ "scripts": { "matrix": "node run.mjs", "test": "playwright test", - "report": "playwright show-report" + "report": "playwright show-report", + "typecheck": "tsc --noEmit -p tsconfig.json" }, "devDependencies": { "@playwright/test": "^1.49.0", + "@types/node": "^22.10.0", "dotenv": "^16.4.5", - "monocart-reporter": "^2.12.1" + "monocart-reporter": "^2.12.1", + "typescript": "^5.6.3" } } diff --git a/playwright.config.ts b/playwright.config.ts index ed609b7..d728d83 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig, devices, type ReporterDescription } from '@playwright/test'; import * as dotenv from 'dotenv'; import * as fs from 'fs'; import * as path from 'path'; @@ -74,7 +74,7 @@ export default defineConfig({ // Maps browser coverage back to console-components/console source via sourcemaps // (console-components must be built with --sourcemap; see `just test-coverage`). ...(process.env.E2E_COVERAGE === '1' && browser === 'chromium' - ? [ + ? ([ [ 'monocart-reporter', { @@ -92,7 +92,7 @@ export default defineConfig({ }, }, ], - ] + ] as ReporterDescription[]) : []), ], // chromium: run all specs tagged for the active mode (e.g. @authz). firefox/webkit: diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3f8604c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + // Type-checking config for the E2E specs + Playwright config. Playwright runs the + // specs via its own esbuild transform (no emit needed here); this exists so + // `tsc --noEmit` can statically catch broken specs in CI. skipLibCheck keeps it + // focused on our code, not third-party .d.ts noise. + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": ["node"], + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["specs/**/*.ts", "playwright.config.ts"] +}