@reddoorla/maintenance 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/bin.js CHANGED
@@ -1674,6 +1674,7 @@ var a11yRoutes = [
1674
1674
  { path: "/dev/a11y-fixtures", name: "a11y fixtures" },
1675
1675
  { path: "/dev/animate-in", name: "animate-in demo" }
1676
1676
  ];
1677
+ var smokeRoutes = [{ path: "/", name: "home" }];
1677
1678
  var playwrightA11yConfig = defineConfig({
1678
1679
  testDir: "tests",
1679
1680
  testMatch: /.*\.spec\.ts$/,
@@ -1748,15 +1749,32 @@ import { mkdir, writeFile } from "node:fs/promises";
1748
1749
  import { dirname } from "node:path";
1749
1750
 
1750
1751
  const pages = ${JSON.stringify(a11yRoutes)};
1752
+ const smokePages = ${JSON.stringify(smokeRoutes)};
1751
1753
  const OUTPUT = process.env.REDDOOR_A11Y_OUTPUT;
1752
1754
 
1753
1755
  // Playwright's default per-test timeout is 30s. We loop through every
1754
1756
  // configured route in a single test, so the budget needs to scale.
1755
1757
  test.setTimeout(5 * 60_000);
1756
1758
 
1757
- test("a11y across configured routes", async ({ page }) => {
1759
+ test("a11y + hydration across configured routes", async ({ page }) => {
1758
1760
  const violations = [];
1761
+
1762
+ // Capture uncaught client-side exceptions across every route we visit. A page
1763
+ // that builds + SSRs cleanly can still throw on hydrate and blank itself
1764
+ // (data-dynamiq: a Svelte 4->5 run() referenced a $state declared after it) --
1765
+ // axe never sees that, so we listen for it directly and tag the route in scope.
1766
+ let currentRoute = "";
1767
+ page.on("pageerror", (err) => {
1768
+ violations.push({
1769
+ id: "client-error",
1770
+ impact: "critical",
1771
+ route: currentRoute,
1772
+ help: String(err && err.message ? err.message : err),
1773
+ });
1774
+ });
1775
+
1759
1776
  for (const { path, name } of pages) {
1777
+ currentRoute = name;
1760
1778
  await page.goto(path);
1761
1779
  // Snap CSS transitions/animations to their resting state before axe runs.
1762
1780
  // AnimateIn-style fixtures transition opacity 0->1; sampling mid-transition
@@ -1782,6 +1800,19 @@ test("a11y across configured routes", async ({ page }) => {
1782
1800
  });
1783
1801
  }
1784
1802
  }
1803
+
1804
+ // Hydration smoke check: load real routes (the homepage) and fail on any
1805
+ // uncaught client-side error. No axe here -- real routes carry pre-existing
1806
+ // a11y debt we don't gate on; we only assert they don't crash on hydrate.
1807
+ // HTTP/SSR errors don't fire 'pageerror', so a data-less CI homepage that
1808
+ // renders empty-but-valid won't false-fail -- only a real client crash does.
1809
+ for (const { path, name } of smokePages) {
1810
+ currentRoute = name;
1811
+ await page.goto(path);
1812
+ // Let hydration + first effects run so a TDZ/ReferenceError surfaces.
1813
+ await page.waitForTimeout(2000);
1814
+ }
1815
+
1785
1816
  const byImpact = {};
1786
1817
  for (const v of violations) {
1787
1818
  byImpact[v.impact] = (byImpact[v.impact] ?? 0) + 1;
@@ -1850,7 +1881,7 @@ async function a11yAudit(ctx) {
1850
1881
  const hasSerious = (artifact.byImpact.serious ?? 0) > 0 || (artifact.byImpact.critical ?? 0) > 0;
1851
1882
  const hasAny = artifact.totalViolations > 0;
1852
1883
  const status = hasSerious ? "fail" : hasAny ? "warn" : "pass";
1853
- const summary = status === "pass" ? `a11y: 0 violations across ${a11yRoutes.length} routes` : `a11y: ${artifact.totalViolations} violations`;
1884
+ const summary = status === "pass" ? `a11y: 0 violations across ${a11yRoutes.length} routes (+${smokeRoutes.length} hydration smoke)` : `a11y: ${artifact.totalViolations} violations`;
1854
1885
  return {
1855
1886
  audit: "a11y",
1856
1887
  site: label,