diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc072b65..e0de8924 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,7 @@ jobs: build: ${{ steps.filter.outputs.build }} bundle: ${{ steps.filter.outputs.bundle }} docker: ${{ steps.filter.outputs.docker }} + e2e: ${{ steps.filter.outputs.e2e }} steps: - uses: actions/checkout@v7 if: github.event_name == 'pull_request' @@ -69,6 +70,20 @@ jobs: - 'package.json' - 'package-lock.json' - '.github/workflows/**' + # #564: the browser suite is the ONLY gate that can see CSS layout, + # container queries, real focus/hover, and IndexedDB — happy-dom sees + # none of it. Anything that can move rendered geometry or the + # harnesses themselves belongs here. `src/styles.css` is inside + # `src/**` and is the single biggest reason this filter exists. + e2e: + - 'src/**' + - 'schemas/**' + - 'tests/e2e/**' + - 'playwright.config.js' + - 'build/**' + - 'package.json' + - 'package-lock.json' + - '.github/workflows/**' docker: - 'Dockerfile' - 'deploy/caddy/**' @@ -313,12 +328,29 @@ jobs: # cover each commit, while release tags validate the shipped image/artifact. # The harness imports /src directly over a python http.server (started by the # Playwright config's webServer), so no build step is needed. + # #564: until now this ran ONLY for tags, schedule and manual dispatch, so it + # reported `skipped` on every pull request and every push to `main` while the + # overall run still went green. A PR check that never runs is not a check: two + # `tile-open-workbench` specs had been failing on all three engines on `main` + # (#565) and nothing surfaced it until the workflow was dispatched by hand. + # + # Pull requests now get a **Chromium-only** run, path-gated on anything that + # can move rendered geometry — cheap enough to sit on every relevant PR, and + # both #565 failures reproduce on Chromium, so one engine would have caught + # them. Tags, nightly and manual dispatch keep the full three-engine matrix, + # because engine-specific breakage is real here (WebKit focus/IndexedDB + # behaviour especially) and that is what a release must clear. e2e: + needs: changes if: >- (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) || github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' + github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && needs.changes.outputs.e2e == 'true') runs-on: ubuntu-latest + env: + # One engine on PRs, all three everywhere else. + PR_ONLY_CHROMIUM: ${{ github.event_name == 'pull_request' }} steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 @@ -327,9 +359,19 @@ jobs: cache: npm - run: npm ci --no-audit --no-fund - name: Install Playwright browsers - run: npx playwright install --with-deps chromium firefox webkit - - name: E2E (Playwright — Chromium + Firefox + WebKit) - run: npm run test:e2e + run: | + if [ "$PR_ONLY_CHROMIUM" = "true" ]; then + npx playwright install --with-deps chromium + else + npx playwright install --with-deps chromium firefox webkit + fi + - name: E2E (Playwright) + run: | + if [ "$PR_ONLY_CHROMIUM" = "true" ]; then + npm run test:e2e -- --project=chromium + else + npm run test:e2e + fi - uses: actions/upload-artifact@v7 if: ${{ failure() }} with: diff --git a/tests/e2e/tile-open-workbench.spec.js b/tests/e2e/tile-open-workbench.spec.js index cf27778c..e046c5bd 100644 --- a/tests/e2e/tile-open-workbench.spec.js +++ b/tests/e2e/tile-open-workbench.spec.js @@ -325,6 +325,16 @@ test('a KPI tile in EDIT mode packs its two controls top-right, in reading order // attribute actually hides a button whose author-sheet `display: inline-flex` beats // the UA sheet's `[hidden] { display: none }`. test('widen doubles a grid tile\'s rendered width and height, then wraps', async ({ page }) => { + // #565: KNOWN BROKEN on chromium, firefox AND webkit, and already broken at + // f68861c — before the batch that enabled this suite on PRs (#564), so this + // is not fallout from that batch. Widen still grows the tile's WIDTH; its + // HEIGHT no longer changes (`expect(wide.height).toBeGreaterThan(208)` gets + // exactly 208). Quarantined with `test.fail()`, deliberately NOT `skip`/ + // `fixme`: the spec keeps running, so the day the underlying bug is fixed + // this reports "expected to fail, but passed" — which is the signal to + // delete this line, not to relax the assertions below. They encode #535's + // intended widen semantics and must not be rewritten to match the bug. + test.fail(); // Wide enough that the grid host clears `effectiveGridColumns`' 1160px tier and // renders all 12 columns. At the default 1280 viewport the sidebar leaves it in // the 6-column tier, where the fixture's span-8 tile is ALREADY full width and a @@ -367,6 +377,12 @@ test('widen doubles a grid tile\'s rendered width and height, then wraps', async // this particular TILE has no room to offer the shortcut. The menu row is unaffected // by either, so widen is never unreachable. test('a narrow tile drops the inline widen but keeps its menu row', async ({ page }) => { + // #565: KNOWN BROKEN on all three engines, same pre-existing regression as the + // widen spec above — the placement entry never appears at all + // (`items['t-sales']?.span` polls to `null`, not `2`). Same `test.fail()` + // quarantine and the same exit condition: when it starts passing, remove the + // line rather than weakening the poll. + test.fail(); await open(page, { width: 1600, height: 900 }); await openDashboard(page, 'sales', 'edit');