snap-ally 0.0.2 β†’ 0.0.4

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # snap-ally <span aria-hidden="true">πŸ“Έβ™Ώ</span>
1
+ # snap-ally πŸ“Έβ™Ώ
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/snap-ally.svg)](https://www.npmjs.com/package/snap-ally)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -7,17 +7,13 @@ A powerful, developer-friendly Playwright reporter for **Accessibility testing**
7
7
 
8
8
  ---
9
9
 
10
- ## <span aria-hidden="true">πŸ“Ί</span> Demo
10
+ ## πŸ“Ί Demo
11
11
 
12
- <div align="center">
13
- <video src="video.webm" width="800" controls aria-label="Snap-Ally accessibility reporter demonstration video showing HTML reports and visual overlays">
14
- Your browser does not support the video tag. You can <a href="video.webm">download the video</a> to view it.
15
- </video>
16
- </div>
12
+ **[▢️ Watch the Demo Video](https://www.loom.com/share/853c04f1f76242a699e8f82e54733007)**
17
13
 
18
14
  ---
19
15
 
20
- ## <span aria-hidden="true">✨</span> Features
16
+ ## ✨ Features
21
17
 
22
18
  - **Beautiful HTML Reporting**: Comprehensive summary and detail pages.
23
19
  - **Visual Overlays**: Highlights violations directly on the page in screenshots.
@@ -28,7 +24,7 @@ A powerful, developer-friendly Playwright reporter for **Accessibility testing**
28
24
 
29
25
  ---
30
26
 
31
- ## <span aria-hidden="true">πŸš€</span> Installation
27
+ ## πŸš€ Installation
32
28
 
33
29
  ```bash
34
30
  npm install snap-ally --save-dev
@@ -36,30 +32,33 @@ npm install snap-ally --save-dev
36
32
 
37
33
  ---
38
34
 
39
- ## <span aria-hidden="true">πŸ› οΈ</span> Setup
35
+ ## πŸ› οΈ Setup
40
36
 
41
37
  Add `snap-ally` to your `playwright.config.ts`:
42
38
 
43
39
  ```typescript
44
- import { defineConfig } from '@playwright/test';
40
+ import { defineConfig } from "@playwright/test";
45
41
 
46
42
  export default defineConfig({
47
43
  reporter: [
48
- ['snap-ally', {
49
- outputFolder: 'a11y-report',
50
- // Optional: Visual Customization
51
- colors: {
52
- critical: '#dc2626',
53
- serious: '#ea580c',
54
- moderate: '#f59e0b',
55
- minor: '#0ea5e9',
44
+ [
45
+ "snap-ally",
46
+ {
47
+ outputFolder: "a11y-report",
48
+ // Optional: Visual Customization
49
+ colors: {
50
+ critical: "#dc2626",
51
+ serious: "#ea580c",
52
+ moderate: "#f59e0b",
53
+ minor: "#0ea5e9",
54
+ },
55
+ // Optional: Azure DevOps Integration
56
+ ado: {
57
+ organization: "your-org",
58
+ project: "your-project",
59
+ },
56
60
  },
57
- // Optional: Azure DevOps Integration
58
- ado: {
59
- organization: 'your-org',
60
- project: 'your-project'
61
- }
62
- }]
61
+ ],
63
62
  ],
64
63
  });
65
64
  ```
@@ -71,23 +70,24 @@ export default defineConfig({
71
70
  Import and use `scanA11y` within your Playwright tests:
72
71
 
73
72
  ```typescript
74
- import { test } from '@playwright/test';
75
- import { scanA11y } from 'snap-ally';
73
+ import { test } from "@playwright/test";
74
+ import { scanA11y } from "snap-ally";
75
+
76
+ test("verify page accessibility", async ({ page }, testInfo) => {
77
+ await page.goto("https://example.com");
76
78
 
77
- test('verify page accessibility', async ({ page }, testInfo) => {
78
- await page.goto('https://example.com');
79
-
80
79
  // Basic scan
81
80
  await scanA11y(page, testInfo);
82
81
 
83
82
  // Advanced scan with configuration
84
83
  await scanA11y(page, testInfo, {
84
+ verbose: true, // Log results to terminal
85
+ consoleLog: true, // Log results to browser console
86
+ pageKey: 'Homepage', // Custom name for the report file
87
+ tags: ['wcag2a', 'wcag2aa'],
85
88
  rules: {
86
- 'color-contrast': { enabled: false }, // Disable specific rule
87
- },
88
- tags: ['wcag2a', 'wcag2aa'], // Focus on specific WCAG levels
89
- verbose: true,
90
- pageKey: 'Homepage' // Custom name for the report file
89
+ 'color-contrast': { enabled: false },
90
+ }
91
91
  });
92
92
  });
93
93
  ```
@@ -98,20 +98,21 @@ test('verify page accessibility', async ({ page }, testInfo) => {
98
98
 
99
99
  ### Reporter Options (in `playwright.config.ts`)
100
100
 
101
- | Option | Type | Description |
102
- | --- | --- | --- |
103
- | `outputFolder` | `string` | Where to save the reports. Defaults to `steps-report`. |
104
- | `colors` | `object` | Customize severity colors (critical, serious, moderate, minor). |
105
- | `ado` | `object` | Azure DevOps configuration for deep linking. |
106
- | `ado.organization` | `string` | Your Azure DevOps organization name. |
107
- | `ado.project` | `string` | Your Azure DevOps project name. |
101
+ | Option | Type | Description |
102
+ | ------------------ | -------- | --------------------------------------------------------------- |
103
+ | `outputFolder` | `string` | Where to save the reports. Defaults to `steps-report`. |
104
+ | `colors` | `object` | Customize severity colors (critical, serious, moderate, minor). |
105
+ | `ado` | `object` | Azure DevOps configuration for deep linking. |
106
+ | `ado.organization` | `string` | Your Azure DevOps organization name. |
107
+ | `ado.project` | `string` | Your Azure DevOps project name. |
108
108
 
109
109
  ### `scanA11y` Options
110
110
 
111
111
  | Option | Type | Description |
112
112
  | --- | --- | --- |
113
113
  | `include` | `string` | CSS selector to limit the scan to a specific element. |
114
- | `verbose` | `boolean` | Log violations to the console. Defaults to `true`. |
114
+ | `verbose` | `boolean` | **Terminal Logs**: Print violations to terminal. Defaults to `true`. |
115
+ | `consoleLog` | `boolean` | **Browser Logs**: Print violations to browser console. Defaults to `true`. |
115
116
  | `rules` | `object` | Axe-core rule configuration. |
116
117
  | `tags` | `string[]` | List of Axe-core tags to run (e.g., `['wcag2aa']`). |
117
118
  | `pageKey` | `string` | Custom identifier for the report file name. |
@@ -16,6 +16,8 @@ export interface A11yScannerOptions {
16
16
  tags?: string[];
17
17
  /** Any other Axe-core options to pass to the builder. */
18
18
  axeOptions?: Record<string, unknown>;
19
+ /** Custom identifier for the report file name. */
20
+ pageKey?: string;
19
21
  }
20
22
  /**
21
23
  * Performs an accessibility audit using Axe and Lighthouse.
@@ -9,13 +9,38 @@ const playwright_1 = __importDefault(require("@axe-core/playwright"));
9
9
  const test_1 = require("@playwright/test");
10
10
  const A11yAuditOverlay_1 = require("./A11yAuditOverlay");
11
11
  const models_1 = require("./models");
12
+ /**
13
+ * Sanitizes a string to be safe for use in file paths and prevents path traversal attacks.
14
+ * Removes or replaces dangerous characters and path separators.
15
+ */
16
+ function sanitizePageKey(input) {
17
+ return input
18
+ // Remove protocol
19
+ .replace(/^https?:\/\//, '')
20
+ // Remove or replace path separators and dangerous characters
21
+ .replace(/[\/\\:*?"<>|]/g, '-')
22
+ // Remove any remaining path traversal attempts
23
+ .replace(/\.\./g, '')
24
+ // Replace multiple consecutive dashes with a single dash
25
+ .replace(/-+/g, '-')
26
+ // Remove leading/trailing dashes
27
+ .replace(/^-+|-+$/g, '')
28
+ // Convert to lowercase for consistency
29
+ .toLowerCase()
30
+ // Limit length to prevent filesystem issues
31
+ .substring(0, 200);
32
+ }
12
33
  /**
13
34
  * Performs an accessibility audit using Axe and Lighthouse.
14
35
  */
15
36
  async function scanA11y(page, testInfo, options = {}) {
16
- var _a;
17
- const verbose = (_a = options.verbose) !== null && _a !== void 0 ? _a : true;
18
- const overlay = new A11yAuditOverlay_1.A11yAuditOverlay(page, page.url());
37
+ var _a, _b;
38
+ const showTerminal = (_a = options.verbose) !== null && _a !== void 0 ? _a : true;
39
+ const showBrowser = (_b = options.consoleLog) !== null && _b !== void 0 ? _b : true;
40
+ // Sanitize pageKey to prevent path traversal attacks
41
+ const rawPageKey = options.pageKey || page.url();
42
+ const pageKey = sanitizePageKey(rawPageKey);
43
+ const overlay = new A11yAuditOverlay_1.A11yAuditOverlay(page, pageKey);
19
44
  // Configure Axe
20
45
  let axeBuilder = new playwright_1.default({ page });
21
46
  const target = options.include || options.box;
@@ -39,11 +64,22 @@ async function scanA11y(page, testInfo, options = {}) {
39
64
  }
40
65
  const axeResults = await axeBuilder.analyze();
41
66
  const violationCount = axeResults.violations.length;
42
- if (verbose && violationCount > 0) {
43
- console.log(`\n[A11yScanner] Violations found: ${violationCount}`);
44
- axeResults.violations.forEach((v, i) => {
45
- console.log(` ${i + 1}. ${v.id} [${v.impact}] - ${v.help}`);
46
- });
67
+ if ((showTerminal || showBrowser) && violationCount > 0) {
68
+ const mainMsg = `[A11yScanner] Violations found: ${violationCount}`;
69
+ // Prepare all detail messages
70
+ const detailMessages = axeResults.violations.map((v, i) => ` ${i + 1}. ${v.id} [${v.impact}] - ${v.help}`);
71
+ // Log to terminal
72
+ if (showTerminal) {
73
+ console.log(`\n${mainMsg}`);
74
+ detailMessages.forEach(msg => console.log(msg));
75
+ }
76
+ // Batch log to Browser Console in a single evaluate call
77
+ if (showBrowser) {
78
+ await page.evaluate(([mainMsg, details]) => {
79
+ console.log(`%c ${mainMsg}`, 'color: #ea580c; font-weight: bold; font-size: 12px;');
80
+ details.forEach((msg) => console.log(msg));
81
+ }, [mainMsg, detailMessages]);
82
+ }
47
83
  }
48
84
  // Fail the test if violations found (softly)
49
85
  test_1.expect.soft(violationCount, `Accessibility audit failed with ${violationCount} violations.`).toBe(0);
@@ -106,7 +142,7 @@ async function scanA11y(page, testInfo, options = {}) {
106
142
  }
107
143
  // Prepare data for the reporter
108
144
  const reportData = {
109
- pageKey: page.url(),
145
+ pageKey,
110
146
  accessibilityScore: 0, // No longer used, derivation from Lighthouse removed
111
147
  errors,
112
148
  video: 'a11y-scan-video.webm', // Reference name for reporter
@@ -33,6 +33,7 @@ declare class SnapAllyReporter implements Reporter {
33
33
  private renderer;
34
34
  private options;
35
35
  private projectRoot;
36
+ printsToStdio(): boolean;
36
37
  private executionSummary;
37
38
  private tasks;
38
39
  constructor(options?: AccessibilityReporterOptions);
@@ -44,6 +44,9 @@ const fs = __importStar(require("fs"));
44
44
  * Generates an execution summary and detailed reports per test.
45
45
  */
46
46
  class SnapAllyReporter {
47
+ printsToStdio() {
48
+ return false;
49
+ }
47
50
  constructor(options = {}) {
48
51
  this.testIndex = 0;
49
52
  this.assetsManager = new A11yReportAssets_1.A11yReportAssets();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snap-ally",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "A custom Playwright reporter for Accessibility testing using Axe, with HTML reporting and Azure DevOps integration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",