cypress-voice-plugin 1.0.0 → 1.0.2
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/index.js +149 -141
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -15,7 +15,14 @@ if (
|
|
|
15
15
|
addStyles();
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
// Used when user navigates away from current spec within the test runner
|
|
19
|
+
// Stops the voice from continuing
|
|
20
|
+
Cypress.on("window:unload", () => {
|
|
21
|
+
const voice = window.speechSynthesis;
|
|
22
|
+
voice.cancel();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
Cypress.on("test:after:run", (_, test) => {
|
|
19
26
|
// Additional context of test index
|
|
20
27
|
// To account for loops where there is one test per describe and suite names may stay
|
|
21
28
|
// And to account for both specs with multiple suites or only one suite
|
|
@@ -26,16 +33,6 @@ if (
|
|
|
26
33
|
|
|
27
34
|
// Checking the current test index is either equal to the last index of the suite or the test context
|
|
28
35
|
const currentTestIsLast = lastTestIndex === testNumber;
|
|
29
|
-
|
|
30
|
-
// Checks within the document for a failure state
|
|
31
|
-
const failed = window.top?.document.querySelector(".runnable-failed");
|
|
32
|
-
// Checks within the document for a retried state to determine if retry occurred
|
|
33
|
-
const retried = window.top?.document.querySelector(".runnable-retried");
|
|
34
|
-
// Checks within the document for a passed state
|
|
35
|
-
const passed = window.top?.document.querySelector(".runnable-passed");
|
|
36
|
-
// Checks within the document for a skipped state
|
|
37
|
-
const skipped = window.top?.document.querySelector(".runnable-pending");
|
|
38
|
-
|
|
39
36
|
// Rate toggle for speed of spoken text
|
|
40
37
|
const rate = window.top?.document.querySelector("#rate");
|
|
41
38
|
|
|
@@ -45,18 +42,26 @@ if (
|
|
|
45
42
|
// Volume toggle for volume of spoken text
|
|
46
43
|
const volume = window.top?.document.querySelector("#volume");
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
// Logic involved with waiting for the restart button to appear
|
|
46
|
+
// This signals the Cypress Test Runner has completed it's current run
|
|
47
|
+
function waitForElement(selector, callback) {
|
|
48
|
+
const observer = new MutationObserver((mutations, observer) => {
|
|
49
|
+
const element = window.top?.document.querySelector(selector);
|
|
50
|
+
if (element) {
|
|
51
|
+
observer.disconnect();
|
|
52
|
+
callback(element);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
observer.observe(window.top?.document.body, {
|
|
57
|
+
childList: true,
|
|
58
|
+
subtree: true,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Checks within the document for a failure state
|
|
62
|
+
const failed = window.top?.document.querySelector(".runnable-failed");
|
|
63
|
+
// Checks within the document for a retried state to determine if retry occurred
|
|
64
|
+
const retried = window.top?.document.querySelector(".runnable-retried");
|
|
60
65
|
|
|
61
66
|
// Check test result count for passed, failed, skipped, retried
|
|
62
67
|
// If count is 1, use singular
|
|
@@ -69,7 +74,7 @@ if (
|
|
|
69
74
|
// Only return seconds if minutes are less than or equal to 0
|
|
70
75
|
function specTime() {
|
|
71
76
|
const specTime = window.top?.document.querySelector(
|
|
72
|
-
'[data-cy="spec-duration"]'
|
|
77
|
+
'[data-cy="spec-duration"]',
|
|
73
78
|
)?.textContent;
|
|
74
79
|
const specSec = specTime?.slice(-2);
|
|
75
80
|
const specMin = specTime?.slice(0, 2);
|
|
@@ -137,33 +142,42 @@ if (
|
|
|
137
142
|
}
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
149
|
-
|
|
145
|
+
// Retrieve count of passed, failed, retried, and skipped tests
|
|
146
|
+
function retrieveTestStats() {
|
|
147
|
+
let failedTests = window.top?.document
|
|
148
|
+
.querySelector(".failed")
|
|
149
|
+
.innerText.replace("Failed:\n", "");
|
|
150
|
+
|
|
151
|
+
const retriedTests = window.top?.document.querySelectorAll(
|
|
152
|
+
".test.runnable-passed.runnable-retried",
|
|
153
|
+
).length;
|
|
154
|
+
|
|
155
|
+
let passedTests = window.top?.document
|
|
156
|
+
.querySelector(".passed")
|
|
157
|
+
.innerText.replace("Passed:\n", "");
|
|
158
|
+
|
|
159
|
+
let skippedTests = window.top?.document
|
|
160
|
+
.querySelector(".pending")
|
|
161
|
+
.innerText.replace("Pending:\n", "");
|
|
162
|
+
|
|
163
|
+
if (passedTests === "--") {
|
|
164
|
+
passedTests = 0;
|
|
150
165
|
} else {
|
|
151
|
-
|
|
166
|
+
passedTests = parseInt(passedTests);
|
|
152
167
|
}
|
|
153
|
-
}
|
|
154
168
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
function checkSkipped() {
|
|
158
|
-
if (skipped && !failed && !passed) {
|
|
159
|
-
return true;
|
|
169
|
+
if (failedTests === "--") {
|
|
170
|
+
failedTests = 0;
|
|
160
171
|
} else {
|
|
161
|
-
|
|
172
|
+
failedTests = parseInt(failedTests);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (skippedTests === "--") {
|
|
176
|
+
skippedTests = 0;
|
|
177
|
+
} else {
|
|
178
|
+
skippedTests = parseInt(skippedTests);
|
|
162
179
|
}
|
|
163
|
-
}
|
|
164
180
|
|
|
165
|
-
// Retrieve count of passed, failed, retried, and skipped tests
|
|
166
|
-
function retrieveTestStats() {
|
|
167
181
|
const stats = [
|
|
168
182
|
`${passedTests - retriedTests}` +
|
|
169
183
|
pluralizeWord(" test", " tests", `${passedTests - retriedTests}`) +
|
|
@@ -183,102 +197,96 @@ if (
|
|
|
183
197
|
return `${filteredStats.toString()}`;
|
|
184
198
|
}
|
|
185
199
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
);
|
|
277
|
-
message.rate = rate.value;
|
|
278
|
-
message.pitch = pitch.value;
|
|
279
|
-
message.volume = volume.value;
|
|
280
|
-
speechSynthesis.speak(message);
|
|
281
|
-
}
|
|
200
|
+
if (currentTestIsLast) {
|
|
201
|
+
waitForElement(".restart", () => {
|
|
202
|
+
// Announce spec run result and/or total time based on provided environment variable(s)
|
|
203
|
+
if (
|
|
204
|
+
Cypress.env("voiceResultType") === "simple" &&
|
|
205
|
+
!Cypress.env("voiceTime")
|
|
206
|
+
) {
|
|
207
|
+
const message = new SpeechSynthesisUtterance(
|
|
208
|
+
`Spec ${
|
|
209
|
+
failed ? "failed." : retried ? "passed with retries." : "passed."
|
|
210
|
+
}`,
|
|
211
|
+
);
|
|
212
|
+
message.rate = rate.value;
|
|
213
|
+
message.pitch = pitch.value;
|
|
214
|
+
message.volume = volume.value;
|
|
215
|
+
speechSynthesis.speak(message);
|
|
216
|
+
} else if (
|
|
217
|
+
Cypress.env("voiceTime") &&
|
|
218
|
+
!(Cypress.env("voiceResultType") === "simple") &&
|
|
219
|
+
!(Cypress.env("voiceResultType") === "detailed")
|
|
220
|
+
) {
|
|
221
|
+
const message = new SpeechSynthesisUtterance(
|
|
222
|
+
"Total time: " + specTime(),
|
|
223
|
+
);
|
|
224
|
+
message.rate = rate.value;
|
|
225
|
+
message.pitch = pitch.value;
|
|
226
|
+
message.volume = volume.value;
|
|
227
|
+
speechSynthesis.speak(message);
|
|
228
|
+
} else if (
|
|
229
|
+
Cypress.env("voiceResultType") === "detailed" &&
|
|
230
|
+
!Cypress.env("voiceTime")
|
|
231
|
+
) {
|
|
232
|
+
const message = new SpeechSynthesisUtterance(
|
|
233
|
+
`Spec ${
|
|
234
|
+
failed
|
|
235
|
+
? "failed: " + retrieveTestStats()
|
|
236
|
+
: retried
|
|
237
|
+
? "passed with retries: " + retrieveTestStats()
|
|
238
|
+
: "passed: " + retrieveTestStats()
|
|
239
|
+
}`,
|
|
240
|
+
);
|
|
241
|
+
message.rate = rate.value;
|
|
242
|
+
message.pitch = pitch.value;
|
|
243
|
+
message.volume = volume.value;
|
|
244
|
+
speechSynthesis.speak(message);
|
|
245
|
+
} else if (
|
|
246
|
+
Cypress.env("voiceResultType") === "simple" &&
|
|
247
|
+
Cypress.env("voiceTime")
|
|
248
|
+
) {
|
|
249
|
+
const message = new SpeechSynthesisUtterance(
|
|
250
|
+
`Spec ${
|
|
251
|
+
failed
|
|
252
|
+
? "failed. Total time: " + specTime()
|
|
253
|
+
: retried
|
|
254
|
+
? "passed with retries. Total time: " + specTime()
|
|
255
|
+
: "passed. Total time: " + specTime()
|
|
256
|
+
}`,
|
|
257
|
+
);
|
|
258
|
+
message.rate = rate.value;
|
|
259
|
+
message.pitch = pitch.value;
|
|
260
|
+
message.volume = volume.value;
|
|
261
|
+
speechSynthesis.speak(message);
|
|
262
|
+
} else if (
|
|
263
|
+
Cypress.env("voiceResultType") === "detailed" &&
|
|
264
|
+
Cypress.env("voiceTime")
|
|
265
|
+
) {
|
|
266
|
+
const message = new SpeechSynthesisUtterance(
|
|
267
|
+
`Spec ${
|
|
268
|
+
failed
|
|
269
|
+
? "failed: " +
|
|
270
|
+
retrieveTestStats() +
|
|
271
|
+
" Total time: " +
|
|
272
|
+
specTime()
|
|
273
|
+
: retried
|
|
274
|
+
? "passed with retries: " +
|
|
275
|
+
retrieveTestStats() +
|
|
276
|
+
". Total time: " +
|
|
277
|
+
specTime()
|
|
278
|
+
: "passed: " +
|
|
279
|
+
retrieveTestStats() +
|
|
280
|
+
" Total time: " +
|
|
281
|
+
specTime()
|
|
282
|
+
}`,
|
|
283
|
+
);
|
|
284
|
+
message.rate = rate.value;
|
|
285
|
+
message.pitch = pitch.value;
|
|
286
|
+
message.volume = volume.value;
|
|
287
|
+
speechSynthesis.speak(message);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
282
290
|
}
|
|
283
291
|
});
|
|
284
292
|
}
|