@koenvanbelle/cypress-soft-assertions 1.0.7 → 1.0.9
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/dist/index.js +70 -98
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
let softAssertionErrors = [];
|
|
11
11
|
let isInSoftTest = false;
|
|
12
|
-
let
|
|
13
|
-
|
|
12
|
+
let activeFailHandler = null;
|
|
13
|
+
let activeSoftTestTitle = null;
|
|
14
|
+
let finalizerInstalled = false;
|
|
14
15
|
/**
|
|
15
16
|
* Track a soft assertion failure so it can be reported at test end.
|
|
16
17
|
*/
|
|
@@ -26,98 +27,89 @@ function captureSoftAssertion(error) {
|
|
|
26
27
|
stack
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*/
|
|
32
|
-
function getCurrentCommand() {
|
|
30
|
+
function getCurrentCommandName() {
|
|
31
|
+
var _a;
|
|
33
32
|
const state = cy === null || cy === void 0 ? void 0 : cy.state;
|
|
34
33
|
if (typeof state !== 'function') {
|
|
35
|
-
return
|
|
34
|
+
return '';
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!command) {
|
|
41
|
-
return undefined;
|
|
36
|
+
const current = state('current');
|
|
37
|
+
if (!current) {
|
|
38
|
+
return '';
|
|
42
39
|
}
|
|
43
|
-
if (typeof
|
|
44
|
-
return
|
|
40
|
+
if (typeof current.get === 'function') {
|
|
41
|
+
return String(current.get('name') || '');
|
|
45
42
|
}
|
|
46
|
-
|
|
47
|
-
return command.attributes[prop];
|
|
48
|
-
}
|
|
49
|
-
return command[prop];
|
|
43
|
+
return String(current.name || ((_a = current.attributes) === null || _a === void 0 ? void 0 : _a.name) || '');
|
|
50
44
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
function getAssertionContext() {
|
|
55
|
-
const command = getCurrentCommand();
|
|
56
|
-
const commandId = String(getCommandProp(command, 'id') || getCommandProp(command, 'chainerId') || '');
|
|
57
|
-
const commandName = String(getCommandProp(command, 'name') || '');
|
|
58
|
-
const timeout = Number(getCommandProp(command, 'timeout')) || Number(Cypress.config('defaultCommandTimeout'));
|
|
59
|
-
const isRetriable = commandName === 'should' || commandName === 'and';
|
|
60
|
-
return {
|
|
61
|
-
commandId,
|
|
62
|
-
timeout,
|
|
63
|
-
isRetriable,
|
|
64
|
-
};
|
|
45
|
+
function isRetryTimeoutError(error) {
|
|
46
|
+
const message = String((error === null || error === void 0 ? void 0 : error.message) || '');
|
|
47
|
+
return /Timed out retrying after/i.test(message);
|
|
65
48
|
}
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
if (isRetriable && !/Timed out retrying after/i.test(message)) {
|
|
69
|
-
return {
|
|
70
|
-
...error,
|
|
71
|
-
message: `Timed out retrying after ${timeout}ms: ${message}`,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
return error;
|
|
49
|
+
function isRetriableAssertionCommand(commandName) {
|
|
50
|
+
return commandName === 'should' || commandName === 'and';
|
|
75
51
|
}
|
|
76
52
|
/**
|
|
77
|
-
* Intercept
|
|
53
|
+
* Intercept Cypress failures and make assertion failures soft in soft_it() tests.
|
|
78
54
|
*/
|
|
79
55
|
function setupSoftAssertions() {
|
|
80
|
-
if (!
|
|
81
|
-
|
|
56
|
+
if (!activeFailHandler) {
|
|
57
|
+
activeFailHandler = (error) => {
|
|
58
|
+
if (!isInSoftTest) {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
const commandName = getCurrentCommandName();
|
|
62
|
+
if (isRetriableAssertionCommand(commandName) && !isRetryTimeoutError(error)) {
|
|
63
|
+
// Let Cypress continue polling/retrying for retriable assertions.
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
captureSoftAssertion(error);
|
|
67
|
+
return false;
|
|
68
|
+
};
|
|
69
|
+
Cypress.on('fail', activeFailHandler);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function getTestTitle(test) {
|
|
73
|
+
if (test && typeof test.fullTitle === 'function') {
|
|
74
|
+
return test.fullTitle();
|
|
82
75
|
}
|
|
83
|
-
|
|
76
|
+
return String((test === null || test === void 0 ? void 0 : test.title) || '');
|
|
77
|
+
}
|
|
78
|
+
function installFinalizer() {
|
|
79
|
+
if (finalizerInstalled) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
afterEach(function () {
|
|
83
|
+
var _a, _b;
|
|
84
84
|
if (!isInSoftTest) {
|
|
85
|
-
return
|
|
85
|
+
return;
|
|
86
86
|
}
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (context.commandId) {
|
|
91
|
-
retryWindows.delete(context.commandId);
|
|
92
|
-
}
|
|
93
|
-
return result;
|
|
87
|
+
const currentTest = (this.currentTest || this.test);
|
|
88
|
+
if (!currentTest || getTestTitle(currentTest) !== activeSoftTestTitle) {
|
|
89
|
+
return;
|
|
94
90
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (context.isRetriable && context.commandId) {
|
|
98
|
-
const currentWindow = retryWindows.get(context.commandId) || {
|
|
99
|
-
startedAt: Date.now(),
|
|
100
|
-
timeout: context.timeout,
|
|
101
|
-
};
|
|
102
|
-
retryWindows.set(context.commandId, currentWindow);
|
|
103
|
-
const elapsed = Date.now() - currentWindow.startedAt;
|
|
104
|
-
if (elapsed < currentWindow.timeout) {
|
|
105
|
-
throw rawError;
|
|
106
|
-
}
|
|
107
|
-
retryWindows.delete(context.commandId);
|
|
108
|
-
}
|
|
109
|
-
captureSoftAssertion(error);
|
|
91
|
+
const finalError = finalizeSoftTest();
|
|
92
|
+
if (!finalError) {
|
|
110
93
|
return;
|
|
111
94
|
}
|
|
112
|
-
|
|
95
|
+
currentTest.err = finalError;
|
|
96
|
+
currentTest.state = 'failed';
|
|
97
|
+
const runner = (_b = (_a = Cypress === null || Cypress === void 0 ? void 0 : Cypress.mocha) === null || _a === void 0 ? void 0 : _a.getRunner) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
98
|
+
if (runner && typeof runner.fail === 'function') {
|
|
99
|
+
runner.fail(currentTest, finalError);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
throw finalError;
|
|
103
|
+
});
|
|
104
|
+
finalizerInstalled = true;
|
|
113
105
|
}
|
|
114
106
|
/**
|
|
115
107
|
* Restore original Chai assertion behavior.
|
|
116
108
|
*/
|
|
117
109
|
function restoreAssertions() {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
110
|
+
if (activeFailHandler) {
|
|
111
|
+
Cypress.off('fail', activeFailHandler);
|
|
112
|
+
activeFailHandler = null;
|
|
121
113
|
}
|
|
122
114
|
}
|
|
123
115
|
/**
|
|
@@ -151,6 +143,7 @@ function buildSoftAssertionError() {
|
|
|
151
143
|
function finalizeSoftTest() {
|
|
152
144
|
isInSoftTest = false;
|
|
153
145
|
restoreAssertions();
|
|
146
|
+
activeSoftTestTitle = null;
|
|
154
147
|
return buildSoftAssertionError();
|
|
155
148
|
}
|
|
156
149
|
/**
|
|
@@ -159,52 +152,31 @@ function finalizeSoftTest() {
|
|
|
159
152
|
function abortSoftTest() {
|
|
160
153
|
isInSoftTest = false;
|
|
161
154
|
restoreAssertions();
|
|
155
|
+
activeSoftTestTitle = null;
|
|
162
156
|
}
|
|
163
157
|
/**
|
|
164
158
|
* Create a soft_it variant from a Mocha it function.
|
|
165
159
|
*/
|
|
166
160
|
function createSoftIt(baseIt) {
|
|
161
|
+
installFinalizer();
|
|
167
162
|
return function (title, fn) {
|
|
168
163
|
return baseIt(title, function () {
|
|
169
164
|
isInSoftTest = true;
|
|
170
165
|
softAssertionErrors = [];
|
|
166
|
+
activeSoftTestTitle = getTestTitle(this.currentTest || this.test);
|
|
171
167
|
setupSoftAssertions();
|
|
172
168
|
try {
|
|
173
169
|
const result = fn.call(this);
|
|
174
170
|
if (result && typeof result.then === 'function') {
|
|
175
171
|
return result
|
|
176
172
|
.catch((error) => {
|
|
177
|
-
if ((error === null || error === void 0 ? void 0 : error.name) === 'AssertionError') {
|
|
178
|
-
captureSoftAssertion(error);
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
173
|
abortSoftTest();
|
|
182
174
|
throw error;
|
|
183
|
-
})
|
|
184
|
-
.then(() => cy.wrap(null).then(() => {
|
|
185
|
-
const finalError = finalizeSoftTest();
|
|
186
|
-
if (finalError) {
|
|
187
|
-
throw finalError;
|
|
188
|
-
}
|
|
189
|
-
}));
|
|
175
|
+
});
|
|
190
176
|
}
|
|
191
|
-
return
|
|
192
|
-
const finalError = finalizeSoftTest();
|
|
193
|
-
if (finalError) {
|
|
194
|
-
throw finalError;
|
|
195
|
-
}
|
|
196
|
-
});
|
|
177
|
+
return result;
|
|
197
178
|
}
|
|
198
179
|
catch (error) {
|
|
199
|
-
if ((error === null || error === void 0 ? void 0 : error.name) === 'AssertionError') {
|
|
200
|
-
captureSoftAssertion(error);
|
|
201
|
-
return cy.wrap(null).then(() => {
|
|
202
|
-
const finalError = finalizeSoftTest();
|
|
203
|
-
if (finalError) {
|
|
204
|
-
throw finalError;
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
180
|
abortSoftTest();
|
|
209
181
|
throw error;
|
|
210
182
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koenvanbelle/cypress-soft-assertions",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "A Cypress plugin that provides soft_it() for soft assertions - all assertions continue on failure and are reported together",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|