pagean 10.1.5 → 11.0.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/README.md +132 -135
- package/bin/pagean.js +16 -21
- package/bin/pageanrc-lint.js +9 -9
- package/index.js +41 -19
- package/lib/config.js +29 -19
- package/lib/default-config.json +16 -16
- package/lib/external-file-utils.js +16 -10
- package/lib/link-utils.js +21 -23
- package/lib/logger.js +31 -8
- package/lib/report-template.handlebars +18 -1
- package/lib/reporter.js +8 -7
- package/lib/schema-errors.js +4 -5
- package/lib/sitemap.js +26 -21
- package/lib/test-utils.js +7 -9
- package/lib/tests.js +31 -22
- package/lib/utils.js +45 -0
- package/package.json +17 -15
- package/schemas/pageanrc.schema.json +1 -1
package/lib/tests.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* eslint-disable capitalized-comments -- "v8 ignore" statements for code
|
|
2
|
+
executed in browser are case sensitive. */
|
|
3
3
|
/**
|
|
4
4
|
* Pagean tests.
|
|
5
5
|
*
|
|
6
6
|
* @module tests
|
|
7
7
|
*/
|
|
8
|
-
const { HTMLHint } = require('htmlhint');
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
import { HTMLHint } from 'htmlhint';
|
|
10
|
+
|
|
11
|
+
import * as fileUtils from './external-file-utils.js';
|
|
12
|
+
import { pageanTest, testResultStates } from './test-utils.js';
|
|
13
|
+
import { isFailedResponse } from './link-utils.js';
|
|
13
14
|
|
|
14
15
|
const msPerSec = 1000;
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Tests the current page for the existence of a horizontal scroll bar.
|
|
18
19
|
*
|
|
19
|
-
* @param
|
|
20
|
+
* @param {object} context Test execution context.
|
|
21
|
+
* @returns {Promise<void>}
|
|
20
22
|
* @static
|
|
21
23
|
*/
|
|
22
24
|
const horizontalScrollbarTest = async (context) => {
|
|
@@ -24,13 +26,14 @@ const horizontalScrollbarTest = async (context) => {
|
|
|
24
26
|
'should not have a horizontal scrollbar',
|
|
25
27
|
// eslint-disable-next-line no-shadow -- less intuitive
|
|
26
28
|
async (context) => {
|
|
27
|
-
// istanbul ignore next: injects script causing puppeteer error, see #48
|
|
28
29
|
const scrollbar = await context.page.evaluate(() => {
|
|
30
|
+
/* v8 ignore start: executed in browser */
|
|
29
31
|
document.scrollingElement.scrollLeft = 1;
|
|
30
32
|
// The scrollLeft value may not end up exactly 1. But, any
|
|
31
33
|
// value greater than 0 indicates the presence of a horizontal
|
|
32
34
|
// scrollbar.
|
|
33
35
|
return document.scrollingElement.scrollLeft > 0;
|
|
36
|
+
/* v8 ignore stop */
|
|
34
37
|
});
|
|
35
38
|
return {
|
|
36
39
|
result:
|
|
@@ -104,7 +107,8 @@ const consoleErrorTest = (context) => {
|
|
|
104
107
|
/**
|
|
105
108
|
* Tests the current page for any HTML lint issues.
|
|
106
109
|
*
|
|
107
|
-
* @param
|
|
110
|
+
* @param {object} context Test execution context.
|
|
111
|
+
* @returns {Promise<void>}
|
|
108
112
|
* @static
|
|
109
113
|
*/
|
|
110
114
|
const renderedHtmlTest = async (context) => {
|
|
@@ -136,7 +140,8 @@ const renderedHtmlTest = async (context) => {
|
|
|
136
140
|
/**
|
|
137
141
|
* Tests the current page for load time.
|
|
138
142
|
*
|
|
139
|
-
* @param
|
|
143
|
+
* @param {object} context Test execution context.
|
|
144
|
+
* @returns {Promise<void>}
|
|
140
145
|
* @static
|
|
141
146
|
*/
|
|
142
147
|
// eslint-disable-next-line max-lines-per-function -- exceeded due to formatting
|
|
@@ -148,9 +153,9 @@ const pageLoadTimeTest = async (context) => {
|
|
|
148
153
|
async (context) => {
|
|
149
154
|
const { pageLoadTimeThreshold } = context.testSettings;
|
|
150
155
|
const name = `should load page within ${pageLoadTimeThreshold} sec`;
|
|
151
|
-
// istanbul ignore next: injects script causing puppeteer error, see #48
|
|
152
156
|
const performanceTiming = JSON.parse(
|
|
153
157
|
await context.page.evaluate(() =>
|
|
158
|
+
/* v8 ignore next: executed in browser */
|
|
154
159
|
JSON.stringify(window.performance)
|
|
155
160
|
)
|
|
156
161
|
);
|
|
@@ -179,7 +184,8 @@ const pageLoadTimeTest = async (context) => {
|
|
|
179
184
|
* Tests the current page for any external JavaScript files and
|
|
180
185
|
* downloads the files for further analysis.
|
|
181
186
|
*
|
|
182
|
-
* @param
|
|
187
|
+
* @param {object} context Test execution context.
|
|
188
|
+
* @returns {Promise<void>}
|
|
183
189
|
* @static
|
|
184
190
|
*/
|
|
185
191
|
// eslint-disable-next-line max-lines-per-function -- exceeded due to formatting
|
|
@@ -188,8 +194,8 @@ const externalScriptTest = async (context) => {
|
|
|
188
194
|
'should not have external scripts',
|
|
189
195
|
// eslint-disable-next-line no-shadow -- less intuitive
|
|
190
196
|
async (context) => {
|
|
191
|
-
// istanbul ignore next: injects script causing puppeteer error, see #48
|
|
192
197
|
const scripts = await context.page.evaluate(() =>
|
|
198
|
+
/* v8 ignore next: executed in browser */
|
|
193
199
|
[...document.querySelectorAll('script[src]')].map((s) => s.src)
|
|
194
200
|
);
|
|
195
201
|
|
|
@@ -221,7 +227,8 @@ const externalScriptTest = async (context) => {
|
|
|
221
227
|
/**
|
|
222
228
|
* Tests the current page for any broken links (external or within the page).
|
|
223
229
|
*
|
|
224
|
-
* @param
|
|
230
|
+
* @param {object} context Test execution context.
|
|
231
|
+
* @returns {Promise<void>}
|
|
225
232
|
* @static
|
|
226
233
|
*/
|
|
227
234
|
// eslint-disable-next-line max-lines-per-function -- exceeded due to formatting
|
|
@@ -230,8 +237,8 @@ const brokenLinkTest = async (context) => {
|
|
|
230
237
|
'should not have broken links',
|
|
231
238
|
// eslint-disable-next-line no-shadow -- less intuitive
|
|
232
239
|
async (context) => {
|
|
233
|
-
// istanbul ignore next: injects script causing puppeteer error, see #48
|
|
234
240
|
const links = await context.page.evaluate(() =>
|
|
241
|
+
/* v8 ignore next: executed in browser */
|
|
235
242
|
[...document.querySelectorAll('a[href]')].map((a) => a.href)
|
|
236
243
|
);
|
|
237
244
|
|
|
@@ -272,10 +279,12 @@ const brokenLinkTest = async (context) => {
|
|
|
272
279
|
);
|
|
273
280
|
};
|
|
274
281
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
+
export {
|
|
283
|
+
consoleErrorTest,
|
|
284
|
+
consoleOutputTest,
|
|
285
|
+
horizontalScrollbarTest,
|
|
286
|
+
pageLoadTimeTest,
|
|
287
|
+
renderedHtmlTest,
|
|
288
|
+
externalScriptTest,
|
|
289
|
+
brokenLinkTest
|
|
290
|
+
};
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Miscellaneous utilities.
|
|
3
|
+
*
|
|
4
|
+
* @module utils
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { readFile } from 'node:fs/promises';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The file containing the current module, using the CJS global name.
|
|
13
|
+
*
|
|
14
|
+
* @type {string}
|
|
15
|
+
*/
|
|
16
|
+
// eslint-disable-next-line no-underscore-dangle -- match CJS name
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The directory containing the current module, using the CJS global name.
|
|
21
|
+
*
|
|
22
|
+
* @type {string}
|
|
23
|
+
*/
|
|
24
|
+
// eslint-disable-next-line no-underscore-dangle -- match CJS name
|
|
25
|
+
const __dirname = dirname(__filename);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Reads a JSON file and returns the parsed data.
|
|
29
|
+
*
|
|
30
|
+
* @param {string} path The path to the JSON file to read.
|
|
31
|
+
* @returns {Promise<object>} The parsed JSON data.
|
|
32
|
+
*/
|
|
33
|
+
const readJson = async (path) => {
|
|
34
|
+
const data = await readFile(path, 'utf8');
|
|
35
|
+
return JSON.parse(data);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The package.json file for this project.
|
|
40
|
+
*
|
|
41
|
+
* @type {object}
|
|
42
|
+
*/
|
|
43
|
+
const pkg = await readJson(join(__dirname, '..', 'package.json'));
|
|
44
|
+
|
|
45
|
+
export { __dirname, __filename, readJson, pkg };
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pagean",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0",
|
|
4
4
|
"description": "Pagean is a web page analysis tool designed to automate tests requiring web pages to be loaded in a browser window (e.g. horizontal scrollbar, console errors)",
|
|
5
5
|
"bin": {
|
|
6
6
|
"pagean": "./bin/pagean.js",
|
|
7
7
|
"pageanrc-lint": "./bin/pageanrc-lint.js"
|
|
8
8
|
},
|
|
9
|
+
"type": "module",
|
|
9
10
|
"scripts": {
|
|
10
11
|
"hooks:pre-commit": "npm run lint && npm run prettier:check",
|
|
11
12
|
"hooks:pre-push": "npm audit --audit-level=high && npm test",
|
|
@@ -19,7 +20,8 @@
|
|
|
19
20
|
"start": "node ./bin/pagean.js",
|
|
20
21
|
"start:lint": "node ./bin/pageanrc-lint.js",
|
|
21
22
|
"start:lint-all": "npm run start:lint && npm run start:lint static-server.pageanrc.json && npm run start:lint ./lib/default-config.json",
|
|
22
|
-
"test": "
|
|
23
|
+
"test": "vitest run --coverage",
|
|
24
|
+
"test:no-coverage": "vitest run"
|
|
23
25
|
},
|
|
24
26
|
"repository": {
|
|
25
27
|
"type": "git",
|
|
@@ -37,7 +39,7 @@
|
|
|
37
39
|
"author": "Aaron Goldenthal <npm@aarongoldenthal.com>",
|
|
38
40
|
"license": "MIT",
|
|
39
41
|
"engines": {
|
|
40
|
-
"node": "^18.12.0 ||
|
|
42
|
+
"node": "^18.12.0 || ^20.9.0 || >=22.0.0"
|
|
41
43
|
},
|
|
42
44
|
"files": [
|
|
43
45
|
"index.js",
|
|
@@ -52,29 +54,29 @@
|
|
|
52
54
|
"homepage": "https://gitlab.com/gitlab-ci-utils/pagean",
|
|
53
55
|
"devDependencies": {
|
|
54
56
|
"@aarongoldenthal/eslint-config-standard": "^27.0.1",
|
|
55
|
-
"@aarongoldenthal/stylelint-config-standard": "^
|
|
56
|
-
"
|
|
57
|
+
"@aarongoldenthal/stylelint-config-standard": "^18.0.0",
|
|
58
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
59
|
+
"bin-tester": "^6.0.0",
|
|
57
60
|
"eslint": "^8.57.0",
|
|
58
|
-
"jest": "^29.7.0",
|
|
59
|
-
"jest-junit": "^16.0.0",
|
|
60
61
|
"markdownlint-cli2": "^0.13.0",
|
|
61
62
|
"prettier": "^3.2.5",
|
|
62
|
-
"strip-ansi": "^
|
|
63
|
-
"stylelint": "^16.
|
|
63
|
+
"strip-ansi": "^7.1.0",
|
|
64
|
+
"stylelint": "^16.5.0",
|
|
65
|
+
"vitest": "^1.6.0"
|
|
64
66
|
},
|
|
65
67
|
"dependencies": {
|
|
66
|
-
"ajv": "^8.
|
|
68
|
+
"ajv": "^8.13.0",
|
|
67
69
|
"ajv-errors": "^3.0.0",
|
|
68
70
|
"axios": "^1.6.8",
|
|
69
|
-
"ci-logger": "^
|
|
70
|
-
"commander": "^12.
|
|
71
|
+
"ci-logger": "^7.0.0",
|
|
72
|
+
"commander": "^12.1.0",
|
|
71
73
|
"cssesc": "^3.0.0",
|
|
72
74
|
"handlebars": "^4.7.8",
|
|
73
75
|
"htmlhint": "^1.1.4",
|
|
74
76
|
"kleur": "^4.1.5",
|
|
75
|
-
"normalize-url": "^
|
|
76
|
-
"protocolify": "^
|
|
77
|
-
"puppeteer": "^22.
|
|
77
|
+
"normalize-url": "^8.0.1",
|
|
78
|
+
"protocolify": "^4.0.0",
|
|
79
|
+
"puppeteer": "^22.9.0",
|
|
78
80
|
"xml2js": "^0.6.2"
|
|
79
81
|
}
|
|
80
82
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2019-09/schema#",
|
|
3
3
|
"$id": "https://gitlab.com/gitlab-ci-utils/pagean/-/raw/master/schemas/pageanrc.schema.json",
|
|
4
4
|
"title": "Pagean Configuration File Schema",
|
|
5
5
|
"description": "The JSON schema definition for pageanrc configuration files.",
|