Commit 9b247ef
feat(e2e): real-world test-site matrix + harness + CI (#223)
* fix(cli): wire auto_fetch_chromium through plumb watch
Add the `--auto-fetch-chromium` flag to the `Watch` clap command and
forward it to the inner `LintArgs` so `plumb watch` builds again. Without
this, the workspace failed to compile because `LintArgs` declares
`auto_fetch_chromium` as a required field after #220 landed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(e2e): add plumb-e2e harness crate
Dev-only crate that drives the locally built `plumb` binary against
the framework fixtures under `e2e-sites/`. Builds each fixture, serves
its `dist/` over loopback HTTP via tiny_http, runs `plumb lint
http://127.0.0.1:<port>/ --config e2e-sites/plumb.toml --format json`
three times, asserts byte-equality across runs, and diffs the
target-rule violation breakdown against `expected.json`.
`plumb-e2e` is excluded from `default-members`, never linked from
upstream crates (it shells out to the binary), and depends only on
external crates plus the workspace lints. Fixtures register
themselves in `sites::SITES`; the matrix CI workflow iterates the
same list. Harness invariants:
- The static server refuses path-traversal and never follows symlinks.
- A 25 ms recv polling cadence plus a worker-thread fan-out keeps
Chromium's many-parallel-chunks pattern responsive.
- The harness shell-execs `just build` per fixture, so each fixture
owns its own toolchain pinning (npm lockfile, etc.).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(e2e): real-world fixture matrix under e2e-sites/
Six framework fixtures rendering the same intentional violations:
- html-css — vanilla HTML + hand-rolled CSS tokens.
- tailwind-html — static HTML built with Tailwind v4 CLI.
- react-vite — React 18 + Vite + Tailwind v4.
- vue — Vue 3 + Vite + Tailwind v4.
- angular — Angular 17 standalone components + Tailwind v4
(compiled standalone — Angular's bundler peer-pins
Tailwind 2/3).
- nextjs — Next.js 14 App Router exported as static HTML.
Every fixture targets `color/palette-conformance`,
`spacing/grid-conformance`, and `spacing/scale-conformance` via a
`p-[13px]` hero (4 + 4 violations across the longhand sides) and a
`text-[#2e7d2e]` alert (1 palette violation). The `border-[#0b0b0b]`
on each alert pins border-color to a palette token so the four
`border-*-color` longhands stay clean.
Each fixture has:
- A `Justfile` with `build` / `clean` recipes.
- An `expected.json` declaring `target_rules`, `by_rule_id`, and
`total_target_violations`. The harness asserts equality on the
target subset; non-target rules are tolerated to stay robust
against incidental Chromium-side rendering differences (Next.js's
hidden `<next-route-announcer>` + 4 sides of `margin: -1px` is
documented in nextjs/README.md).
Lockfiles are committed for every fixture that has node deps so CI
builds are reproducible.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ci(e2e): publish test-sites + matrix workflow + dogfood diff
Three pieces wire the new e2e-sites infrastructure into CI:
1. `.github/workflows/e2e-sites.yml` — 18-leg matrix
({ubuntu, macos, windows} × six fixtures). Each leg sets up Node
20 (actions/setup-node@v4 with npm cache keyed on the per-fixture
lockfile) and Chrome stable, builds the fixture via `just build`,
compiles `plumb-cli` in release, and runs the harness against
that single site. The harness asserts byte-equality across three
lint runs and the target-rule breakdown against `expected.json`.
2. `.github/workflows/pages.yml` — extends the docs deploy to also
build every fixture's `dist/` and copy it under
`book/test-sites/<framework>/`. Pages serves the docs and
fixtures from the same artifact; deployed URLs are
`https://plumb.aramhammoudeh.com/test-sites/<framework>/`.
3. `.github/workflows/dogfood.yml` — adds a `lint-deployed-test-sites`
matrix that lints each deployed fixture URL daily and asserts the
live target-rule counts still match the fixture's
`expected.json`. The local copy is also re-linted via the harness
so a remote drift surfaces before a real regression ships.
Plus the `just test-e2e` recipe (local mirror of the CI matrix) and a
CHANGELOG entry under `[Unreleased] / Added`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(e2e): Windows binary path + flag Next.js leg as advisory
- Resolve `--plumb-bin` paths on Windows by appending `EXE_SUFFIX`
when the bare path doesn't exist; canonicalize to drop mixed
`\` / `/` separators in error messages and child-process spawns.
- Mark the Next.js matrix leg as `continue-on-error` while we sort
out the Chromium hydration timeout in a follow-up.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent e6e0ee8 commit 9b247ef
81 files changed
Lines changed: 22433 additions & 1 deletion
File tree
- .github/workflows
- crates/plumb-e2e
- src
- e2e-sites
- angular
- src
- app
- html-css
- nextjs
- app
- react-vite
- src
- tailwind-html
- src
- vue
- src
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| 27 | + | |
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
| 31 | + | |
30 | 32 | | |
31 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
32 | 57 | | |
| 58 | + | |
33 | 59 | | |
34 | 60 | | |
35 | 61 | | |
| 62 | + | |
36 | 63 | | |
37 | 64 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
0 commit comments