@schalkneethling/calavera-skill-frontend-testing 0.2.0 → 0.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schalkneethling/calavera-skill-frontend-testing",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Frontend testing artifact for Calavera.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -99,7 +99,7 @@ The distinction: acceptance tests should rarely change on refactor; implementati
99
99
 
100
100
  **ARIA snapshots** are particularly valuable for E2E tests. A single snapshot can replace multiple individual assertions while validating the accessibility tree structure.
101
101
 
102
- **DOM Environment for Unit Tests:** Prefer happy-dom over jsdom. It's faster, and its API limitations serve as a useful signal — if happy-dom doesn't support what you're testing, consider whether it belongs in an E2E test instead.
102
+ **DOM Environment for Unit Tests:** Use happy-dom for fast tests that need a small DOM surface. Use jsdom when component tests require broader DOM APIs. Use Playwright when behavior depends on a real browser, layout, navigation, or browser accessibility APIs. A missing happy-dom API alone does not make a test E2E-worthy; choose the environment that matches the behavior under test and the project's declared dependencies.
103
103
 
104
104
  ### Step 5: Write Tests Before/Alongside Code
105
105
 
@@ -230,7 +230,7 @@ test.describe("Login Page", () => {
230
230
  Use locators that reflect how users and assistive technologies find elements. API names differ:
231
231
 
232
232
  - **Playwright**: prefer `getByRole`, then `getByLabel`, `getByPlaceholder`, `getByText`,
233
- `getByAltText`, and finally `getByTestId`.
233
+ `getByAltText`, `getByTitle`, and finally `getByTestId`.
234
234
  - **Testing Library**: prefer `getByRole`, then `getByLabelText`, `getByPlaceholderText`,
235
235
  `getByText`, `getByAltText`, and finally `getByTestId`.
236
236
 
@@ -168,6 +168,7 @@ test("product page is accessible", async ({ page, makeAxeBuilder }) => {
168
168
 
169
169
  ```javascript
170
170
  const results = await new AxeBuilder({ page }).analyze();
171
+ const includeRawHtml = process.env.AXE_LOG_RAW_HTML === "1" && !process.env.CI;
171
172
 
172
173
  // Structure of a violation
173
174
  results.violations.forEach((violation) => {
@@ -177,12 +178,15 @@ results.violations.forEach((violation) => {
177
178
  console.log(`Help: ${violation.helpUrl}`);
178
179
 
179
180
  violation.nodes.forEach((node) => {
180
- console.log(` Element: ${node.html}`);
181
+ console.log(` Target: ${JSON.stringify(node.target)}`);
182
+ if (includeRawHtml) console.log(` Element HTML: ${node.html}`);
181
183
  console.log(` Fix: ${node.failureSummary}`);
182
184
  });
183
185
  });
184
186
  ```
185
187
 
188
+ Raw HTML can contain rendered user data or form values. Keep it disabled in CI and require an explicit local opt-in when it is needed for diagnosis.
189
+
186
190
  ### Impact Levels
187
191
 
188
192
  | Level | Description | Priority |
@@ -479,8 +479,8 @@ await expect(locator).toMatchAriaSnapshot(`
479
479
 
480
480
  // GOOD: Testing structure with flexible matching
481
481
  await expect(locator).toMatchAriaSnapshot(`
482
- - text /Order #\d+/
483
- - text /Total: \$[\d.]+/
482
+ - text /Order #\\d+/
483
+ - text /Total: \\$[\\d.]+/
484
484
  `);
485
485
  ```
486
486
 
@@ -511,7 +511,7 @@ Always review snapshot updates:
511
511
 
512
512
  ```bash
513
513
  # See what changed
514
- git diff **/*.aria.yml
514
+ git diff -- '**/*.aria.yml'
515
515
 
516
516
  # Verify changes are intentional before committing
517
517
  ```
@@ -80,8 +80,8 @@ Visual tests fail due to timing, rendering, or environment differences. Stabiliz
80
80
  test("page renders after loading", async ({ page }) => {
81
81
  await page.goto("/");
82
82
 
83
- // Wait for network to be idle
84
- await page.waitForLoadState("networkidle");
83
+ // The application sets this marker only after its data and UI are ready.
84
+ await expect(page.getByTestId("app-ready")).toBeVisible();
85
85
 
86
86
  // Wait for web fonts to load
87
87
  await page.evaluate(() => document.fonts.ready);
@@ -323,11 +323,12 @@ permissions:
323
323
 
324
324
  jobs:
325
325
  visual-tests:
326
+ runs-on: ubuntu-latest
326
327
  permissions:
327
328
  contents: read
328
329
  steps:
329
330
  - name: Checkout
330
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2 - re-resolve before use
331
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - re-resolve before use
331
332
  with:
332
333
  persist-credentials: false
333
334
 
@@ -347,32 +348,63 @@ jobs:
347
348
  For consistent baselines, generate in CI:
348
349
 
349
350
  ```yaml
351
+ on:
352
+ workflow_dispatch:
353
+
350
354
  permissions:
351
355
  contents: read
352
356
 
353
357
  jobs:
358
+ visual-tests:
359
+ runs-on: ubuntu-latest
360
+ permissions:
361
+ contents: read
362
+ steps:
363
+ - name: Checkout
364
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - re-resolve before use
365
+ with:
366
+ persist-credentials: false
367
+
368
+ - name: Run visual tests
369
+ run: npx playwright test --project=chromium
370
+
354
371
  update-baselines:
372
+ if: github.event_name == 'workflow_dispatch' && github.ref_name == github.event.repository.default_branch
373
+ runs-on: ubuntu-latest
355
374
  permissions:
356
375
  contents: write
357
376
  steps:
358
377
  - name: Checkout
359
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2 - re-resolve before use
378
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - re-resolve before use
360
379
  with:
380
+ ref: ${{ github.event.repository.default_branch }}
361
381
  persist-credentials: false
362
382
 
363
383
  - name: Update baselines
364
- run: npx playwright test --update-snapshots
384
+ run: npx playwright test --project=chromium --update-snapshots
365
385
 
366
386
  - name: Commit baselines
367
387
  env:
388
+ DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
368
389
  GITHUB_TOKEN: ${{ github.token }}
390
+ PLAYWRIGHT_SNAPSHOT_DIR: tests/visual.spec.ts-snapshots
369
391
  run: |
392
+ test "$GITHUB_REF_NAME" = "$DEFAULT_BRANCH"
370
393
  git config user.name "CI Bot"
371
394
  git config user.email "github-actions[bot]@users.noreply.github.com"
372
- git add "**/*.png"
395
+ git add -- "$PLAYWRIGHT_SNAPSHOT_DIR"
396
+ while IFS= read -r staged_file; do
397
+ case "$staged_file" in
398
+ "$PLAYWRIGHT_SNAPSHOT_DIR"/*) ;;
399
+ *)
400
+ echo "Unexpected staged file outside $PLAYWRIGHT_SNAPSHOT_DIR: $staged_file" >&2
401
+ exit 1
402
+ ;;
403
+ esac
404
+ done < <(git diff --cached --name-only)
373
405
  if ! git diff --cached --quiet; then
374
406
  git commit -m "Update visual baselines"
375
- git -c http.https://github.com/.extraheader="AUTHORIZATION: bearer $GITHUB_TOKEN" push origin HEAD:refs/heads/${GITHUB_REF_NAME}
407
+ git -c http.https://github.com/.extraheader="AUTHORIZATION: bearer $GITHUB_TOKEN" push origin "HEAD:refs/heads/${DEFAULT_BRANCH}"
376
408
  fi
377
409
  ```
378
410
 
@@ -485,7 +517,8 @@ await expect(page).toHaveScreenshot();
485
517
 
486
518
  // GOOD: Wait for stable state
487
519
  await page.goto("/");
488
- await page.waitForLoadState("networkidle");
520
+ // The application sets this marker only after its data and UI are ready.
521
+ await expect(page.getByTestId("app-ready")).toBeVisible();
489
522
  await page.evaluate(() => document.fonts.ready);
490
523
  await expect(page).toHaveScreenshot();
491
524
  ```