@schalkneethling/calavera-skill-frontend-testing 0.2.0-next.3 → 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
|
@@ -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:**
|
|
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(`
|
|
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
|
|
483
|
-
- text /Total:
|
|
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
|
-
//
|
|
84
|
-
await page.
|
|
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 #
|
|
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 #
|
|
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 "
|
|
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/${
|
|
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
|
-
|
|
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
|
```
|