testaro 73.0.0 → 74.0.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/actSpecs.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /*
2
2
  © 2021–2024 CVS Health and/or one of its affiliates. All rights reserved.
3
- © 2025 Jonathan Robert Pool.
3
+ © 2026 Jeff Witt.
4
+ © 2025–2026 Jonathan Robert Pool.
4
5
 
5
6
  Licensed under the MIT License. See LICENSE file at the project root or
6
7
  https://opensource.org/license/mit/ for details.
@@ -121,6 +122,14 @@ exports.actSpecs = {
121
122
  what: [true, 'string', 'hasLength', 'substring of option text content']
122
123
  }
123
124
  ],
125
+ shoot: [
126
+ 'Save a full-page screenshot to <tmpdir>/testaro-shoot-<which>.png',
127
+ {
128
+ which: [true, 'string', 'hasLength', 'screenshot label, used in the filename'],
129
+ exclusion: [false, 'string', 'hasLength', 'CSS selector for an element to mask'],
130
+ what: [false, 'string', 'hasLength', 'comment']
131
+ }
132
+ ],
124
133
  state: [
125
134
  'Wait until the page reaches a load state',
126
135
  {
package/call.js CHANGED
@@ -22,13 +22,9 @@
22
22
 
23
23
  // IMPORTS
24
24
 
25
- // Module to keep secrets.
26
25
  require('dotenv').config();
27
- // Module to process files.
28
26
  const fs = require('fs/promises');
29
- // Function to process a testing request.
30
27
  const {doJob} = require('./run');
31
- // Function to watch for jobs.
32
28
  const {dirWatch} = require('./dirWatch');
33
29
  const {netWatch} = require('./netWatch');
34
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "73.0.0",
3
+ "version": "74.0.1",
4
4
  "description": "Run 1300 web accessibility tests from 10 tools and get a standardized report",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/procs/doActs.js CHANGED
@@ -20,6 +20,9 @@ const {getNonce, goTo, launch, wait} = require('./launch');
20
20
  const {tools} = require('./job');
21
21
  const {fork} = require('child_process');
22
22
  const {pruneCatalog} = require('./catalog');
23
+ // Function to take a full-page screenshot.
24
+ const {shoot} = require('./shoot');
25
+ // Module to handle file system operations.
23
26
  const {applyMultiplier} = require('./config');
24
27
  const fs = require('fs/promises');
25
28
  const path = require('path');
@@ -636,6 +639,14 @@ exports.doActs = async report => {
636
639
  act.result.success = false;
637
640
  });
638
641
  }
642
+ // Otherwise, if the act is a screenshot:
643
+ else if (type === 'shoot') {
644
+ const exclusion = act.exclusion ? page.locator(act.exclusion) : null;
645
+ const pngPath = await shoot(page, act.which, {exclusion});
646
+ act.result = pngPath
647
+ ? {success: true, path: pngPath}
648
+ : {success: false, prevented: true};
649
+ }
639
650
  // Otherwise, if the act is a move:
640
651
  else if (moves[type]) {
641
652
  const selector = typeof moves[type] === 'string' ? moves[type] : act.what;
package/procs/shoot.js CHANGED
@@ -1,4 +1,5 @@
1
1
  /*
2
+ © 2026 Jeff Witt.
2
3
  © 2025–2026 Jonathan Robert Pool.
3
4
  Licensed under the MIT License. See LICENSE file for details.
4
5
  */
@@ -6,6 +7,17 @@
6
7
  /*
7
8
  shoot
8
9
  Makes and saves as a PNG buffer file a full-page screenshot and returns the file path.
10
+
11
+ Call shape:
12
+ shoot(page, label, options?)
13
+ label: string|number used in the saved filename. Sanitized to
14
+ testaro-shoot-<safe>.png — characters outside [A-Za-z0-9._-]
15
+ collapse to '_', leading/trailing dots and underscores are
16
+ stripped, length is capped at 100, and an empty result becomes
17
+ 'unnamed'.
18
+ options: optional object:
19
+ exclusion: a Playwright Locator to mask in the screenshot.
20
+ dir: output directory (defaults to the OS temp dir).
9
21
  */
10
22
 
11
23
  // IMPORTS
@@ -18,6 +30,24 @@ const {PNG} = require('pngjs');
18
30
 
19
31
  // FUNCTIONS
20
32
 
33
+ /*
34
+ Coerces a label into a filesystem-safe string. Runs of any character outside
35
+ [A-Za-z0-9._-] collapse to one underscore; leading and trailing dots and
36
+ underscores are stripped (no hidden files, no traversal); capped at 100
37
+ characters; falls back to 'unnamed' if nothing usable remains.
38
+ */
39
+ const sanitizeLabel = (label) => {
40
+ const raw = String(label);
41
+ const cleaned = raw
42
+ .replace(/[^A-Za-z0-9._-]+/g, '_')
43
+ .replace(/^[._]+|[._]+$/g, '')
44
+ .slice(0, 100) || 'unnamed';
45
+ if (cleaned !== raw) {
46
+ console.log(`>> shoot: label sanitized from "${raw}" to "${cleaned}"`);
47
+ }
48
+ return cleaned;
49
+ };
50
+
21
51
  // Creates and returns a screenshot.
22
52
  const screenShot = async (page, exclusion = null) => {
23
53
  const options = {
@@ -35,9 +65,11 @@ const screenShot = async (page, exclusion = null) => {
35
65
  return '';
36
66
  });
37
67
  };
38
- exports.shoot = async (page, index, tmpDir) => {
68
+ exports.shoot = async (page, label, tmpDir, options = {}) => {
69
+ const exclusion = options.exclusion || null;
70
+ const dir = options.dir || tmpDir;
39
71
  // Make and get a screenshot as a buffer.
40
- let shot = await screenShot(page);
72
+ let shot = await screenShot(page, exclusion);
41
73
  // If it succeeded:
42
74
  if (shot.length) {
43
75
  // Get the screenshot as an object representation of a PNG image.
@@ -49,8 +81,8 @@ exports.shoot = async (page, index, tmpDir) => {
49
81
  if (global.gc) {
50
82
  global.gc();
51
83
  }
52
- const fileName = `testaro-shoot-${index}.png`;
53
- const pngPath = path.join(tmpDir, fileName);
84
+ const fileName = `testaro-shoot-${sanitizeLabel(label)}.png`;
85
+ const pngPath = path.join(dir, fileName);
54
86
  // Save the PNG buffer.
55
87
  await fs.writeFile(pngPath, pngBuffer);
56
88
  // Return the result.
@@ -0,0 +1,46 @@
1
+ {
2
+ "id": "240101T1300-shoot-example",
3
+ "what": "Demonstrate the shoot action: full-page screenshots interleaved with scripted steps",
4
+ "strict": true,
5
+ "timeLimit": 30,
6
+ "acts": [
7
+ {
8
+ "type": "launch",
9
+ "which": "chromium",
10
+ "url": "https://example.edu/",
11
+ "what": "Chromium browser"
12
+ },
13
+ {
14
+ "type": "shoot",
15
+ "which": "before",
16
+ "what": "Snapshot the landing page before any interaction"
17
+ },
18
+ {
19
+ "type": "shoot",
20
+ "which": "before-masked",
21
+ "exclusion": "header",
22
+ "what": "Same view with the page header masked out"
23
+ },
24
+ {
25
+ "type": "test",
26
+ "which": "testaro",
27
+ "withItems": false,
28
+ "stopOnFail": true,
29
+ "rules": [
30
+ "y",
31
+ "bulk"
32
+ ]
33
+ },
34
+ {
35
+ "type": "shoot",
36
+ "which": "after-tests",
37
+ "what": "Snapshot the page after Testaro tests have run"
38
+ }
39
+ ],
40
+ "sources": {},
41
+ "standard": "only",
42
+ "observe": false,
43
+ "sendReportTo": "http://localhost:3007/api",
44
+ "timeStamp": "240101T1300",
45
+ "creationTimeStamp": "240101T1300"
46
+ }
package/scratch/README.md DELETED
@@ -1,12 +0,0 @@
1
- # scratch
2
-
3
- This directory is used for temporary files produced during execution of jobs.
4
-
5
- ## License
6
-
7
- © 2021–2025 CVS Health and/or one of its affiliates. All rights reserved.
8
- © 2025–2026 Jonathan Robert Pool.
9
-
10
- Licensed under the [MIT License](https://opensource.org/license/mit/). See [LICENSE](../../LICENSE) file at the project root for details.
11
-
12
- SPDX-License-Identifier: MIT