pa11y-ci-reporter-runner 0.7.1 → 1.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 +39 -24
- package/index.js +49 -3
- package/lib/pa11yci-machine.js +10 -0
- package/lib/pa11yci-service.js +184 -65
- package/lib/runner-states.js +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Pa11y CI Reporter Runner
|
|
2
2
|
|
|
3
|
-
Pa11y CI Reporter Runner is designed to facilitate testing of [Pa11y CI reporters](https://github.com/pa11y/pa11y-ci#write-a-custom-reporter). Given a Pa11y CI JSON results file and optional configuration it simulates the Pa11y CI calls to the reporter, including proper transformation of results and configuration data. Functionally, it's an emulation of the Pa11y CI side of the reporter interface with
|
|
3
|
+
Pa11y CI Reporter Runner is designed to facilitate testing of [Pa11y CI reporters](https://github.com/pa11y/pa11y-ci#write-a-custom-reporter). Given a Pa11y CI JSON results file and optional configuration it simulates the Pa11y CI calls to the reporter, including proper transformation of results and configuration data. Functionally, it's an emulation of the Pa11y CI side of the reporter interface with explicit control over execution of each step.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -42,15 +42,26 @@ flowchart LR;
|
|
|
42
42
|
|
|
43
43
|
When calling reporter functions, the runner transforms the Pa11y CI results and configuration data to provide the appropriate arguments. For example, the `results` function is called with the results as returned from Pa11y (slightly different than those returned from Pa11y CI) and the consolidated configuration for the analysis of that URL.
|
|
44
44
|
|
|
45
|
+
The runner state can be obtained via the following runner functions:
|
|
46
|
+
|
|
47
|
+
- `getCurrentState()`: The current state of the runner.
|
|
48
|
+
- `getNextState()`: The next state of the runner (i.e. the state that will be obtained by calling the `runNext()` function).
|
|
49
|
+
|
|
50
|
+
Both functions return an object with the following properties:
|
|
51
|
+
|
|
52
|
+
- `state`: The current runner state (any state value shown above)
|
|
53
|
+
- `url`: The current URL for any state with an applicable URL (`beginUrl` and `urlResults`), otherwise `undefined`.
|
|
54
|
+
|
|
45
55
|
### Runner Execution
|
|
46
56
|
|
|
47
|
-
The reporter runner has
|
|
57
|
+
The reporter runner has five control functions:
|
|
48
58
|
|
|
49
59
|
- `runAll()`: Simulates Pa11y CI running the analysis from the provided JSON results file from the current state through the end, calling all associated reporter functions.
|
|
50
60
|
- `runNext()`: Simulates Pa11y CI running through the next state from the provided JSON results file, calling the associated reporter function as noted above.
|
|
51
61
|
- `runUntil(targetState, targetUrl)`: Simulates Pa11y CI running the analysis from the provided JSON results file from the current state through the specified state/URL, calling the associated reporter functions as noted above. An error will be thrown if the end of the results are reached and the target was not found. This function takes the following arguments:
|
|
52
|
-
- `targetState`: The target state of the runner (any state above except `init`).
|
|
62
|
+
- `targetState`: The target state of the runner (any state above except `init`, or any valid value of the `RunnerStates` enum).
|
|
53
63
|
- `targetUrl`: An optional target URL. If no URL is specified, the runner will stop at the first instance of the target state.
|
|
64
|
+
- `runUntilNext(targetState, targetUrl)`: Provides the same functionality as `runUntil`, but execution ends at the state prior to the target state/URL, so that the target will execute if `runNext()` is subsequently called.
|
|
54
65
|
- `reset()`: Resets the runner to the `init` state. This can be sent from any state.
|
|
55
66
|
|
|
56
67
|
These command are all asynchronous and must be completed before another is sent, otherwise an error will be thrown. In addition, once a run has been completed and the runner is in the `afterAll` state it must be `reset` before accepting any run command.
|
|
@@ -66,36 +77,40 @@ const resultsFileName = "pa11yci-results.json";
|
|
|
66
77
|
const reporterName = "../test-reporter.js";
|
|
67
78
|
const reporterOptions = { "isSomething": true };
|
|
68
79
|
const config = {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
},
|
|
72
|
-
urls: [
|
|
73
|
-
"http://localhost:8080/page1-with-errors.html",
|
|
74
|
-
"http://localhost:8080/page1-no-errors.html",
|
|
75
|
-
{
|
|
76
|
-
url: "https://pa11y.org/timed-out.html",
|
|
77
|
-
timeout: 50,
|
|
80
|
+
defaults: {
|
|
81
|
+
timeout: 30000,
|
|
78
82
|
},
|
|
79
|
-
|
|
83
|
+
urls: [
|
|
84
|
+
"http://localhost:8080/page1-with-errors.html",
|
|
85
|
+
"http://localhost:8080/page1-no-errors.html",
|
|
86
|
+
{
|
|
87
|
+
url: "https://pa11y.org/timed-out.html",
|
|
88
|
+
timeout: 50,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
80
91
|
};
|
|
81
92
|
|
|
82
93
|
test('test all reporter functions', async () => {
|
|
83
|
-
|
|
94
|
+
const runner = createRunner(resultsFileName, reporterName, reporterOptions, config);
|
|
84
95
|
|
|
85
|
-
|
|
96
|
+
await runner.runAll();
|
|
86
97
|
|
|
87
|
-
|
|
98
|
+
// Test reporter results
|
|
88
99
|
});
|
|
89
100
|
|
|
90
101
|
test('test reporter at urlResults state', async () => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
const runner = createRunner(resultsFileName, reporterName, reporterOptions, config);
|
|
103
|
+
|
|
104
|
+
await runner.runUntil(RunnerStates.beginUrl, 'http://localhost:8080/page1-no-errors.html');
|
|
105
|
+
let currentState = runner.getCurrentState();
|
|
106
|
+
// { state: "beginUrl", url: "http://localhost:8080/page1-no-errors.html" }
|
|
107
|
+
const nextState = runner.getNextState();
|
|
108
|
+
// { state: "urlResults", url: "http://localhost:8080/page1-no-errors.html" }
|
|
109
|
+
await runner.runNext();
|
|
110
|
+
currentState = runner.getCurrentState();
|
|
111
|
+
// { state: "urlResults", url: "http://localhost:8080/page1-no-errors.html" }
|
|
112
|
+
|
|
113
|
+
// Test reporter results
|
|
99
114
|
});
|
|
100
115
|
```
|
|
101
116
|
|
package/index.js
CHANGED
|
@@ -117,6 +117,7 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
117
117
|
/**
|
|
118
118
|
* Implements the runner beforeAll event, calling reporter.beforeAll.
|
|
119
119
|
*
|
|
120
|
+
* @async
|
|
120
121
|
* @private
|
|
121
122
|
*/
|
|
122
123
|
const beforeAll = async () => {
|
|
@@ -126,6 +127,7 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
126
127
|
/**
|
|
127
128
|
* Implements the runner beginUrl event, calling reporter.begin.
|
|
128
129
|
*
|
|
130
|
+
* @async
|
|
129
131
|
* @private
|
|
130
132
|
* @param {string} url The url being analyzed.
|
|
131
133
|
*/
|
|
@@ -137,6 +139,7 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
137
139
|
* Implements the runner urlResults event, calling reporter.results or
|
|
138
140
|
* reporter.error as appropriate based on the results.
|
|
139
141
|
*
|
|
142
|
+
* @async
|
|
140
143
|
* @private
|
|
141
144
|
* @param {string} url The url being analyzed.
|
|
142
145
|
*/
|
|
@@ -151,6 +154,7 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
151
154
|
/**
|
|
152
155
|
* Implements the runner afterAll event, calling reporter.afterAll.
|
|
153
156
|
*
|
|
157
|
+
* @async
|
|
154
158
|
* @private
|
|
155
159
|
*/
|
|
156
160
|
const afterAll = async () => {
|
|
@@ -172,6 +176,7 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
172
176
|
/**
|
|
173
177
|
* Resets the runner to the initial state.
|
|
174
178
|
*
|
|
179
|
+
* @async
|
|
175
180
|
* @public
|
|
176
181
|
* @instance
|
|
177
182
|
*/
|
|
@@ -182,6 +187,7 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
182
187
|
/**
|
|
183
188
|
* Executes the entire Pa11y CI sequence, calling all reporter functions.
|
|
184
189
|
*
|
|
190
|
+
* @async
|
|
185
191
|
* @public
|
|
186
192
|
* @instance
|
|
187
193
|
*/
|
|
@@ -193,6 +199,7 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
193
199
|
* Executes the next event in the Pa11y CI sequence, calling the
|
|
194
200
|
* appropriate reporter function.
|
|
195
201
|
*
|
|
202
|
+
* @async
|
|
196
203
|
* @public
|
|
197
204
|
* @instance
|
|
198
205
|
*/
|
|
@@ -202,11 +209,12 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
202
209
|
|
|
203
210
|
/**
|
|
204
211
|
* Executes the entire Pa11y CI sequence, calling all reporter functions,
|
|
205
|
-
* until the specified state and optional URL are reached. If
|
|
212
|
+
* until the specified current state and optional URL are reached. If a URL is not
|
|
206
213
|
* specified, the run completes on the first occurrence of the target state.
|
|
207
214
|
*
|
|
215
|
+
* @async
|
|
208
216
|
* @public
|
|
209
|
-
* @
|
|
217
|
+
* @instance
|
|
210
218
|
* @param {string} targetState The target state to run to.
|
|
211
219
|
* @param {string} [targetUrl] The target URL to run to.
|
|
212
220
|
*/
|
|
@@ -214,11 +222,49 @@ const createRunner = (resultsFileName, reporterName, options = {}, config = {})
|
|
|
214
222
|
await service.runUntil(targetState, targetUrl);
|
|
215
223
|
};
|
|
216
224
|
|
|
225
|
+
/**
|
|
226
|
+
* Executes the entire Pa11y CI sequence, calling all reporter functions,
|
|
227
|
+
* until the specified next state and optional URL are reached. If a URL is not
|
|
228
|
+
* specified, the run completes on the first occurrence of the target state.
|
|
229
|
+
*
|
|
230
|
+
* @async
|
|
231
|
+
* @public
|
|
232
|
+
* @instance
|
|
233
|
+
* @param {string} targetState The target state to run to.
|
|
234
|
+
* @param {string} [targetUrl] The target URL to run to.
|
|
235
|
+
*/
|
|
236
|
+
const runUntilNext = async (targetState, targetUrl) => {
|
|
237
|
+
await service.runUntilNext(targetState, targetUrl);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Get the current state (state, url).
|
|
242
|
+
*
|
|
243
|
+
* @public
|
|
244
|
+
* @instance
|
|
245
|
+
* @returns {object} The current state.
|
|
246
|
+
*/
|
|
247
|
+
// eslint-disable-next-line prefer-destructuring -- required for jsdoc
|
|
248
|
+
const getCurrentState = service.getCurrentState;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get the next state (state, url).
|
|
252
|
+
*
|
|
253
|
+
* @public
|
|
254
|
+
* @instance
|
|
255
|
+
* @returns {object} The next state.
|
|
256
|
+
*/
|
|
257
|
+
// eslint-disable-next-line prefer-destructuring -- required for jsdoc
|
|
258
|
+
const getNextState = service.getNextState;
|
|
259
|
+
|
|
217
260
|
return {
|
|
261
|
+
getCurrentState,
|
|
262
|
+
getNextState,
|
|
218
263
|
reset,
|
|
219
264
|
runAll,
|
|
220
265
|
runNext,
|
|
221
|
-
runUntil
|
|
266
|
+
runUntil,
|
|
267
|
+
runUntilNext
|
|
222
268
|
};
|
|
223
269
|
};
|
|
224
270
|
|
package/lib/pa11yci-machine.js
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* State machine for pa11yci.
|
|
6
|
+
*
|
|
7
|
+
* @module pa11yci-machine
|
|
8
|
+
*/
|
|
9
|
+
|
|
3
10
|
const { createMachine, assign } = require('xstate');
|
|
4
11
|
|
|
12
|
+
/**
|
|
13
|
+
* State machine for pa11yci.
|
|
14
|
+
*/
|
|
5
15
|
const pa11yciMachine = createMachine(
|
|
6
16
|
{
|
|
7
17
|
id: 'pa11yci-runner',
|
package/lib/pa11yci-service.js
CHANGED
|
@@ -1,11 +1,43 @@
|
|
|
1
|
+
/* eslint-disable max-lines */
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Service that interprets pa11yci-machine.
|
|
6
|
+
*
|
|
7
|
+
* @module pa11yci-service
|
|
8
|
+
*/
|
|
5
9
|
|
|
10
|
+
const machine = require('./pa11yci-machine');
|
|
6
11
|
const RunnerStates = require('./runner-states');
|
|
12
|
+
|
|
7
13
|
const finalState = RunnerStates.afterAll;
|
|
8
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Enum for machine events.
|
|
17
|
+
*
|
|
18
|
+
* @enum {string}
|
|
19
|
+
* @private
|
|
20
|
+
* @readonly
|
|
21
|
+
* @static
|
|
22
|
+
*/
|
|
23
|
+
const MachineEvents = Object.freeze({
|
|
24
|
+
NEXT: 'NEXT',
|
|
25
|
+
RESET: 'RESET'
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Enum for runner service states.
|
|
30
|
+
*
|
|
31
|
+
* @enum {string}
|
|
32
|
+
* @private
|
|
33
|
+
* @readonly
|
|
34
|
+
* @static
|
|
35
|
+
*/
|
|
36
|
+
const StateTypes = Object.freeze({
|
|
37
|
+
current: 'current',
|
|
38
|
+
next: 'next'
|
|
39
|
+
});
|
|
40
|
+
|
|
9
41
|
/**
|
|
10
42
|
* Gets the initial pa11yci-runner state machine context given an array of URLs.
|
|
11
43
|
*
|
|
@@ -19,19 +51,29 @@ const getInitialContext = urls => ({
|
|
|
19
51
|
});
|
|
20
52
|
|
|
21
53
|
/**
|
|
22
|
-
* Checks the state to determine whether it has an associated URL.
|
|
54
|
+
* Checks the runner state to determine whether it has an associated URL.
|
|
23
55
|
*
|
|
24
56
|
* @private
|
|
25
|
-
* @param {
|
|
26
|
-
* @returns {boolean}
|
|
57
|
+
* @param {string} state The state to check.
|
|
58
|
+
* @returns {boolean} True if the state has an associated url.
|
|
27
59
|
*/
|
|
28
60
|
const hasUrl = state => state === RunnerStates.beginUrl || state === RunnerStates.urlResults;
|
|
29
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Gets the URL for the given machine state.
|
|
64
|
+
*
|
|
65
|
+
* @private
|
|
66
|
+
* @param {object} machineState The machine state to check against.
|
|
67
|
+
* @returns {string} The current URL for the machine state.
|
|
68
|
+
*/
|
|
69
|
+
const getUrlForState = machineState => hasUrl(machineState.value)
|
|
70
|
+
? machineState.context.urls[machineState.context.urlIndex] : undefined;
|
|
71
|
+
|
|
30
72
|
/**
|
|
31
73
|
* Validates that the given state is a valid RunnerStates value. Throws if not.
|
|
32
74
|
*
|
|
33
75
|
* @private
|
|
34
|
-
* @param
|
|
76
|
+
* @param {string} state The state to validate.
|
|
35
77
|
*/
|
|
36
78
|
const validateRunnerState = (state) => {
|
|
37
79
|
if (!Object.keys(RunnerStates).includes(state)) {
|
|
@@ -40,21 +82,34 @@ const validateRunnerState = (state) => {
|
|
|
40
82
|
};
|
|
41
83
|
|
|
42
84
|
/**
|
|
43
|
-
* Checks if the
|
|
85
|
+
* Checks if the machine state matches the targetState and either no
|
|
44
86
|
* targetUrl was specified or the context matches the targetUrl.
|
|
45
87
|
*
|
|
46
88
|
* @private
|
|
47
|
-
* @param {object}
|
|
48
|
-
* @param {
|
|
49
|
-
* @param {string}
|
|
50
|
-
* @returns {boolean}
|
|
89
|
+
* @param {object} machineState The machine state to check against.
|
|
90
|
+
* @param {RunnerStates} targetState The target runner state.
|
|
91
|
+
* @param {string} [targetUrl] The target URL.
|
|
92
|
+
* @returns {boolean} True if the context matches the target, otherwise false.
|
|
51
93
|
*/
|
|
52
|
-
const isAtTarget = (
|
|
53
|
-
return
|
|
94
|
+
const isAtTarget = (machineState, targetState, targetUrl) => {
|
|
95
|
+
return machineState.value === targetState &&
|
|
96
|
+
(!targetUrl || getUrlForState(machineState) === targetUrl);
|
|
54
97
|
};
|
|
55
98
|
|
|
56
99
|
/**
|
|
57
|
-
*
|
|
100
|
+
* Gets a summary of the machine state (state, url).
|
|
101
|
+
*
|
|
102
|
+
* @private
|
|
103
|
+
* @param {object} machineState The machine state.
|
|
104
|
+
* @returns {object} The machine state summary.
|
|
105
|
+
*/
|
|
106
|
+
const getStateSummary = machineState => ({
|
|
107
|
+
state: machineState.value,
|
|
108
|
+
url: getUrlForState(machineState)
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Factory function that returns a pa11yci-runner service.
|
|
58
113
|
*
|
|
59
114
|
* @public
|
|
60
115
|
* @static
|
|
@@ -65,35 +120,16 @@ const isAtTarget = (context, targetState, targetUrl) => {
|
|
|
65
120
|
// eslint-disable-next-line max-lines-per-function
|
|
66
121
|
const serviceFactory = (urls, actions) => {
|
|
67
122
|
let pendingCommand;
|
|
68
|
-
const currentContext = {
|
|
69
|
-
state: undefined,
|
|
70
|
-
url: undefined
|
|
71
|
-
};
|
|
72
123
|
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
// to get the url from the original urls array.
|
|
80
|
-
currentContext.state = state.value;
|
|
81
|
-
currentContext.url = hasUrl(currentContext.state)
|
|
82
|
-
? urls[state.context.urlIndex] : undefined;
|
|
83
|
-
|
|
84
|
-
if (pendingCommand) {
|
|
85
|
-
// Do not take any action in init state
|
|
86
|
-
if (currentContext.state !== 'init') {
|
|
87
|
-
await actions[currentContext.state](currentContext.url);
|
|
88
|
-
}
|
|
89
|
-
pendingCommand.resolve();
|
|
90
|
-
pendingCommand = undefined;
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
service.start();
|
|
124
|
+
// Implement custom xstate interpreter, which allows for tracking for current
|
|
125
|
+
// and the next state, which is required for some control functions.
|
|
126
|
+
const pa11yMachine = machine.withContext(getInitialContext(urls));
|
|
127
|
+
let currentState = pa11yMachine.initialState;
|
|
128
|
+
// machine.transition is a pure function, so only retrieves the state
|
|
129
|
+
let nextState = machine.transition(currentState, MachineEvents.NEXT);
|
|
94
130
|
|
|
95
131
|
/**
|
|
96
|
-
*
|
|
132
|
+
* Validates that a command is allowed in the given state. Throws if invalid.
|
|
97
133
|
*
|
|
98
134
|
* @private
|
|
99
135
|
*/
|
|
@@ -101,80 +137,163 @@ const serviceFactory = (urls, actions) => {
|
|
|
101
137
|
if (pendingCommand) {
|
|
102
138
|
throw new Error('runner cannot accept a command while another command is pending, await previous command');
|
|
103
139
|
}
|
|
104
|
-
if (
|
|
140
|
+
if (currentState.value === finalState) {
|
|
105
141
|
throw new Error(`runner must be reset before executing any other functions from the ${finalState} state`);
|
|
106
142
|
}
|
|
107
143
|
};
|
|
108
144
|
|
|
109
145
|
/**
|
|
110
|
-
* Sends the specified event to the pa11yci-
|
|
111
|
-
* the
|
|
146
|
+
* Sends the specified event to the pa11yci-machine and executes
|
|
147
|
+
* the applicable action for that state.
|
|
112
148
|
*
|
|
149
|
+
* @async
|
|
113
150
|
* @private
|
|
114
|
-
* @param {
|
|
115
|
-
* @returns {Promise<void>} Promise that indicates a pending state change.
|
|
151
|
+
* @param {MachineEvents} event The event name to be sent.
|
|
116
152
|
*/
|
|
117
|
-
const sendEvent = (event) => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
153
|
+
const sendEvent = async (event) => {
|
|
154
|
+
try {
|
|
155
|
+
// Track pending command to block other commands
|
|
156
|
+
pendingCommand = true;
|
|
157
|
+
|
|
158
|
+
// Send event to the machine and executes the action for the
|
|
159
|
+
// current state (except in init, which has no action)
|
|
160
|
+
currentState = machine.transition(currentState, event);
|
|
161
|
+
if (currentState.value !== 'init') {
|
|
162
|
+
await actions[currentState.value](getUrlForState(currentState));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Check next state and save for reference (machine.transition
|
|
166
|
+
// is a pure function, so only retrieves the state)
|
|
167
|
+
if (currentState.value !== finalState) {
|
|
168
|
+
nextState = machine.transition(currentState, MachineEvents.NEXT);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
// Ensure pending command is reset in all cases, including on error
|
|
173
|
+
pendingCommand = false;
|
|
174
|
+
}
|
|
122
175
|
};
|
|
123
176
|
|
|
124
177
|
/**
|
|
125
178
|
* Resets the service to the init state.
|
|
126
179
|
*
|
|
180
|
+
* @async
|
|
127
181
|
* @public
|
|
128
182
|
* @instance
|
|
129
183
|
*/
|
|
130
184
|
const reset = async () => {
|
|
131
|
-
await sendEvent(
|
|
185
|
+
await sendEvent(MachineEvents.RESET);
|
|
132
186
|
};
|
|
133
187
|
|
|
134
188
|
/**
|
|
135
189
|
* Executes the next event in the Pa11y CI sequence, calling the
|
|
136
190
|
* appropriate reporter function.
|
|
137
191
|
*
|
|
192
|
+
* @async
|
|
138
193
|
* @public
|
|
139
194
|
* @instance
|
|
140
195
|
*/
|
|
141
196
|
const runNext = async () => {
|
|
142
197
|
validateCommandAllowed();
|
|
143
198
|
|
|
144
|
-
await sendEvent(
|
|
199
|
+
await sendEvent(MachineEvents.NEXT);
|
|
145
200
|
};
|
|
146
201
|
|
|
147
202
|
/**
|
|
148
|
-
*
|
|
149
|
-
* until the specified state and optional URL are reached. If no URL is provided
|
|
150
|
-
* specified, the run completes on the first occurrence of the target state.
|
|
203
|
+
* Gets the state for the given state type (current or next).
|
|
151
204
|
*
|
|
152
|
-
* @
|
|
153
|
-
* @
|
|
154
|
-
* @
|
|
155
|
-
* @param {string} [targetUrl] The target URL to run to.
|
|
205
|
+
* @private
|
|
206
|
+
* @param {StateTypes} stateType The state type.
|
|
207
|
+
* @returns {object} The state object for teh given type.
|
|
156
208
|
*/
|
|
157
|
-
const
|
|
209
|
+
const getState = stateType => stateType === StateTypes.current ? currentState : nextState;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Common function for executing runUntil and runUntilNext using the
|
|
213
|
+
* specified state type to check for completion. Executes the entire
|
|
214
|
+
* Pa11y CI sequence, calling all reporter functions, until the
|
|
215
|
+
* specified state and optional URL are reached. If a URL is not specified,
|
|
216
|
+
* the run completes on the first occurrence of the target state.
|
|
217
|
+
*
|
|
218
|
+
* @async
|
|
219
|
+
* @private
|
|
220
|
+
* @param {StateTypes} stateType The state type.
|
|
221
|
+
* @param {RunnerStates} targetState The target state to run to.
|
|
222
|
+
* @param {string} [targetUrl] The target URL to run to.
|
|
223
|
+
*/
|
|
224
|
+
const runUntilInternal = async (stateType, targetState, targetUrl) => {
|
|
158
225
|
validateCommandAllowed();
|
|
159
226
|
validateRunnerState(targetState);
|
|
160
227
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
228
|
+
// Run until target or final state is achieved
|
|
229
|
+
while (!isAtTarget(getState(stateType), targetState, targetUrl)
|
|
230
|
+
&& (getState(stateType)).value !== finalState) {
|
|
231
|
+
await sendEvent(MachineEvents.NEXT);
|
|
164
232
|
}
|
|
165
233
|
|
|
166
234
|
// If the finalState is reached and not at target then it is
|
|
167
235
|
// not in the results and throw to indicate the command failed.
|
|
168
|
-
if (!isAtTarget(
|
|
236
|
+
if (!isAtTarget(getState(stateType), targetState, targetUrl)) {
|
|
169
237
|
const urlString = targetUrl ? ` for targetUrl "${targetUrl}"` : '';
|
|
170
238
|
throw new Error(`targetState "${targetState}"${urlString} was not found`);
|
|
171
239
|
}
|
|
172
240
|
};
|
|
173
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Executes the entire Pa11y CI sequence, calling all reporter functions,
|
|
244
|
+
* until the specified current state and optional URL are reached. If a URL is not
|
|
245
|
+
* specified, the run completes on the first occurrence of the target state.
|
|
246
|
+
*
|
|
247
|
+
* @async
|
|
248
|
+
* @public
|
|
249
|
+
* @instance
|
|
250
|
+
* @param {RunnerStates} targetState The target state to run to.
|
|
251
|
+
* @param {string} [targetUrl] The target URL to run to.
|
|
252
|
+
*/
|
|
253
|
+
const runUntil = async (targetState, targetUrl) => {
|
|
254
|
+
await runUntilInternal(StateTypes.current, targetState, targetUrl);
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Executes the entire Pa11y CI sequence, calling all reporter functions,
|
|
259
|
+
* until the specified next state and optional URL are reached. If a URL is not
|
|
260
|
+
* specified, the run completes on the first occurrence of the target state.
|
|
261
|
+
*
|
|
262
|
+
* @async
|
|
263
|
+
* @public
|
|
264
|
+
* @instance
|
|
265
|
+
* @param {RunnerStates} targetState The target state to run to.
|
|
266
|
+
* @param {string} [targetUrl] The target URL to run to.
|
|
267
|
+
*/
|
|
268
|
+
const runUntilNext = async (targetState, targetUrl) => {
|
|
269
|
+
await runUntilInternal(StateTypes.next, targetState, targetUrl);
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Get the current state (state, url).
|
|
274
|
+
*
|
|
275
|
+
* @public
|
|
276
|
+
* @instance
|
|
277
|
+
* @returns {object} The current state.
|
|
278
|
+
*/
|
|
279
|
+
const getCurrentState = () => getStateSummary(currentState);
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Get the next state (state, url).
|
|
283
|
+
*
|
|
284
|
+
* @public
|
|
285
|
+
* @instance
|
|
286
|
+
* @returns {object} The next state.
|
|
287
|
+
*/
|
|
288
|
+
const getNextState = () => getStateSummary(nextState);
|
|
289
|
+
|
|
174
290
|
return {
|
|
291
|
+
getCurrentState,
|
|
292
|
+
getNextState,
|
|
175
293
|
reset,
|
|
176
294
|
runNext,
|
|
177
|
-
runUntil
|
|
295
|
+
runUntil,
|
|
296
|
+
runUntilNext
|
|
178
297
|
};
|
|
179
298
|
};
|
|
180
299
|
|
package/lib/runner-states.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pa11y-ci-reporter-runner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Pa11y CI Reporter Runner is designed to facilitate testing of Pa11y CI reporters. Given a Pa11y CI JSON results file and optional configuration it simulates the Pa11y CI calls to the reporter.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"homepage": "https://gitlab.com/gitlab-ci-utils/pa11y-ci-reporter-runner#readme",
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@aarongoldenthal/eslint-config-standard": "^12.0.2",
|
|
39
|
-
"eslint": "^8.
|
|
39
|
+
"eslint": "^8.11.0",
|
|
40
40
|
"jest": "^27.5.1",
|
|
41
41
|
"jest-junit": "^13.0.0",
|
|
42
42
|
"markdownlint-cli": "^0.31.1",
|
|
@@ -44,6 +44,6 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"lodash": "^4.17.21",
|
|
47
|
-
"xstate": "^4.30.
|
|
47
|
+
"xstate": "^4.30.6"
|
|
48
48
|
}
|
|
49
49
|
}
|