@koenvanbelle/cypress-soft-assertions 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/LICENSE +21 -0
- package/README.md +293 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +173 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Cypress Soft Assertions
|
|
2
|
+
|
|
3
|
+
A Cypress plugin that provides `soft_it()` - a drop-in replacement for `it()` that makes all assertions soft. Assertions continue execution on failure, and all failures are aggregated and reported at the end of the test.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Standard Cypress assertions stop test execution at the first failure. With `soft_it()`:
|
|
8
|
+
|
|
9
|
+
- All assertions run even if some fail
|
|
10
|
+
- See all failures at once - no need to fix one issue and rerun to find the next
|
|
11
|
+
- Drop-in replacement - just change `it()` to `soft_it()`
|
|
12
|
+
- No manual tracking - failures automatically aggregated and reported
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Install the plugin as a development dependency:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install cypress-soft-assertions --save-dev
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
or using Yarn:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
yarn add cypress-soft-assertions --dev
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Integration
|
|
29
|
+
|
|
30
|
+
### Step 1: Import the Plugin
|
|
31
|
+
|
|
32
|
+
Add the import to your Cypress support file. This registers the `soft_it()` function globally.
|
|
33
|
+
|
|
34
|
+
**For TypeScript projects** - Edit `cypress/support/e2e.ts` (or `cypress/support/commands.ts`):
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import 'cypress-soft-assertions';
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**For JavaScript projects** - Edit `cypress/support/e2e.js` (or `cypress/support/commands.js`):
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
require('cypress-soft-assertions');
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Step 2: Add Type Definitions (TypeScript only)
|
|
47
|
+
|
|
48
|
+
If you're using TypeScript, ensure your `tsconfig.json` includes the plugin types:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"compilerOptions": {
|
|
53
|
+
"types": ["cypress", "cypress-soft-assertions"]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Alternatively, add a reference directive at the top of your test files:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
/// <reference types="cypress-soft-assertions" />
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Step 3: Use in Tests
|
|
65
|
+
|
|
66
|
+
Replace `it()` with `soft_it()` in any test where you want soft assertion behavior:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
describe('Product Page', () => {
|
|
70
|
+
soft_it('validates all product details', () => {
|
|
71
|
+
cy.visit('https://example.com/product/123');
|
|
72
|
+
|
|
73
|
+
// All these assertions will run even if some fail
|
|
74
|
+
cy.get('.product-name').should('have.text', 'Awesome Product');
|
|
75
|
+
cy.get('.product-price').should('have.text', '$99.99');
|
|
76
|
+
cy.get('.stock-status').should('have.text', 'In Stock');
|
|
77
|
+
Supported Assertion Types
|
|
78
|
+
|
|
79
|
+
`soft_it()` works with all Cypress assertion styles:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
soft_it('supports all assertion types', () => {
|
|
83
|
+
cy.visit('/page');
|
|
84
|
+
|
|
85
|
+
// .should() assertions
|
|
86
|
+
cy.get('.title').should('be.visible');
|
|
87
|
+
cy.get('.title').should('have.text', 'Welcome');
|
|
88
|
+
|
|
89
|
+
// .should() with callback
|
|
90
|
+
cy.get('.items').should(($items) => {
|
|
91
|
+
expect($items).to.have.length(5);
|
|
92
|
+
expect($items.first()).to.contain('Item 1');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// expect() in .then()
|
|
96
|
+
cy.get('.price').then($el => {
|
|
97
|
+
expect($el.text()).to.equal('$99.99');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Chained assertions
|
|
101
|
+
cy.get('.button')
|
|
102
|
+
.should('be.visible')
|
|
103
|
+
.and('have.class', 'active')
|
|
104
|
+
.and('contain', 'Submit');
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Mixing soft_it() with Regular it()
|
|
109
|
+
|
|
110
|
+
You can use both `soft_it()` and regular `it()` in the same test suite:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
describe('User Profile', () => {
|
|
114
|
+
// Regular test - stops on first failure
|
|
115
|
+
it('loads the page', () => {
|
|
116
|
+
cy.visit('/profile');
|
|
117
|
+
cy.get('h1').should('be.visible');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Soft test - all assertions run
|
|
121
|
+
soft_it('validates profile fields', () => {
|
|
122
|
+
cy.get('.username').should('have.text', 'john_doe');
|
|
123
|
+
cy.get('.email').should('have.text', 'john@example.com');
|
|
124
|
+
cy.get('.member-since').should('contain', '2023');
|
|
125
|
+
cy.get('.posts-count').should('have.text', '42
|
|
126
|
+
|
|
127
|
+
// Chained assertions
|
|
128
|
+
cy.get('.button')
|
|
129
|
+
.should('be.visible')
|
|
130
|
+
.and('have.class', 'active')
|
|
131
|
+
.and('contain', 'Submit');
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Multiple Tests
|
|
136
|
+
|
|
137
|
+
You can mix `soft_it()` with regular `it()` tests:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
describe('User Profile', () => {
|
|
141
|
+
// Regular test - stops on first failure
|
|
142
|
+
it('loads the page', () => {
|
|
143
|
+
cy.visit('/profile');
|
|
144
|
+
cy.get('h1').should('be.visible');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Soft test - all assertions run
|
|
148
|
+
soft_it('validates profile fields', () => {
|
|
149
|
+
cy.get('.username').should('have.text', 'john_doe');
|
|
150
|
+
cy.get('.email').should('have.text', 'john@example.com');
|
|
151
|
+
cy.get('.member-since').should('contain', '2023');
|
|
152
|
+
cy.get('.posts-count').should('have.text', '42');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Another soft test
|
|
156
|
+
soft_it('validates account settings', () => {
|
|
157
|
+
cy.get('[data-test=notifications]').should('be.checked');
|
|
158
|
+
cy.get('[data-test=newsletter]').should('not.be.checked');
|
|
159
|
+
cy.get('[data-test=theme]').should('have.value', 'dark');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Using soft_it.only and soft_it.skip
|
|
165
|
+
|
|
166
|
+
Just like regular `it()`:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
describe('Test Suite', () => {
|
|
170
|
+
// Run only this test
|
|
171
|
+
soft_it.only('validates important fields', () => {
|
|
172
|
+
cy.get('.field1').should('exist');
|
|
173
|
+
The plugin supports `.only` and `.skip` modifiers just like regular `it()`:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
describe('Test Suite', () => {
|
|
177
|
+
// Run only this test
|
|
178
|
+
soft_it.only('validates important fields', () => {
|
|
179
|
+
cy.get('.field1').should('exist');
|
|
180
|
+
cy.get('.field2').should('exist');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Skip this test
|
|
184
|
+
soft_it.skip('validates optional fields', () => {
|
|
185
|
+
cy.get('.optional').should('exist');
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## How It Works
|
|
191
|
+
|
|
192
|
+
`soft_it()` intercepts Chai assertions within the test block and captures failures instead of throwing them immediately. At the end of the test, all captured failures are aggregated and reported in a single error message.
|
|
193
|
+
|
|
194
|
+
The plugin works with:
|
|
195
|
+
- `.should()` assertions
|
|
196
|
+
- `expect()` assertions
|
|
197
|
+
- `assert()` assertions
|
|
198
|
+
- Custom Cypress commands that use assertions
|
|
199
|
+
- Assertion chains (`.and()`)
|
|
200
|
+
|
|
201
|
+
## Important Notes
|
|
202
|
+
|
|
203
|
+
### When Assertions Are Reported
|
|
204
|
+
|
|
205
|
+
Failures are reported at the end of the test after all Cypress commands complete. The test will be marked as failed, and all assertion failures will be listed together.
|
|
206
|
+
|
|
207
|
+
### Regular vs Soft Tests
|
|
208
|
+
|
|
209
|
+
- **Regular `it()`**: Stops at first assertion failure
|
|
210
|
+
- **Soft `soft_it()`**: Runs all assertions, reports all failures at the end
|
|
211
|
+
|
|
212
|
+
### Non-Assertion Errors
|
|
213
|
+
|
|
214
|
+
Non-assertion errors (network errors, timeouts, command errors) will still stop test execution immediately. `soft_it()` only makes assertions soft.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
soft_it('example', () => {
|
|
218
|
+
cy.visit('/page'); // If this fails (timeout, 404), test stops immediately
|
|
219
|
+
cy.get('.missing').should('exist'); // This assertion is soft
|
|
220
|
+
cy.get('.other').should('exist'); // This assertion is soft
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Best Practices
|
|
225
|
+
|
|
226
|
+
### Use for Validation-Heavy Tests
|
|
227
|
+
|
|
228
|
+
`soft_it()` is ideal for tests that validate many fields:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
soft_it('validates user profile completeness', () => {
|
|
232
|
+
cy.get('.name').should('not.be.empty');
|
|
233
|
+
cy.get('.email').should('match', /@/);
|
|
234
|
+
cy.get('.phone').should('have.length.at.least', 10);
|
|
235
|
+
cy.get('.address').should('not.be.empty');
|
|
236
|
+
cy.get('.city').should('not.be.empty');
|
|
237
|
+
cy.get('.avatar').should('be.visible');
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Use Regular it() for Critical Setup
|
|
242
|
+
|
|
243
|
+
Use regular `it()` for setup steps that must succeed:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
it('logs in successfully', () => {
|
|
247
|
+
cy.visit('/login');
|
|
248
|
+
cy.get('#username').type('user');
|
|
249
|
+
cy.get('#password').type('pass');
|
|
250
|
+
cy.get('button[type=submit]').click();
|
|
251
|
+
cy.url().should('include', '/dashboard');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
soft_it('validates dashboard widgets', () => {
|
|
255
|
+
cy.get('.widget-1').should('be.visible');
|
|
256
|
+
cy.get('.widget-2').should('be.visible');
|
|
257
|
+
cy.get('.widget-3').should('be.visible');
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Group Related Validations
|
|
262
|
+
|
|
263
|
+
Use `soft_it()` to group validations of related elements:
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
soft_it('validates navigation menu', () => {
|
|
267
|
+
cy.get('nav a').eq(0).should('have.text', 'Home');
|
|
268
|
+
cy.get('nav a').eq(1).should('have.text', 'Products');
|
|
269
|
+
cy.get('nav a').eq(2).should('have.text', 'About');
|
|
270
|
+
cy.get('nav a').eq(3).should('have.text', 'Contact');
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Error Output Format
|
|
275
|
+
|
|
276
|
+
When soft assertions fail, you receive a formatted error report:
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
================================================================================
|
|
280
|
+
SOFT ASSERTION FAILURES (4 failed):
|
|
281
|
+
================================================================================
|
|
282
|
+
1. expected '<input#email>' to have value 'test@example.com', but the value was 'wrong@example.com'
|
|
283
|
+
2. expected '<div.order-total>' to contain '$99.99', but it contained '$89.99'
|
|
284
|
+
3. expected '<div.tax>' to contain '$8.75', but it contained '$7.50'
|
|
285
|
+
4. expected '<div.grand-total>' to contain '$113.74', but it contained '$102.49'
|
|
286
|
+
================================================================================
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## License
|
|
290
|
+
|
|
291
|
+
MIT
|
|
292
|
+
|
|
293
|
+
##
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cypress Soft Assertions Plugin
|
|
3
|
+
*
|
|
4
|
+
* Provides soft_it() function that wraps Cypress tests to make all assertions soft.
|
|
5
|
+
* Assertions don't stop execution on failure - they continue and all failures are
|
|
6
|
+
* aggregated and reported at the end of the test.
|
|
7
|
+
*/
|
|
8
|
+
declare global {
|
|
9
|
+
/**
|
|
10
|
+
* soft_it - Define a test where all assertions are soft (non-blocking)
|
|
11
|
+
*
|
|
12
|
+
* All Cypress assertions (.should(), expect(), assert()) within this test block
|
|
13
|
+
* will continue execution even when they fail. At the end of the test, all failures
|
|
14
|
+
* are collected and reported together in a single error.
|
|
15
|
+
*
|
|
16
|
+
* @param title - Test title
|
|
17
|
+
* @param fn - Test function
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* soft_it('validates product page', () => {
|
|
21
|
+
* cy.visit('/product/123');
|
|
22
|
+
* cy.get('.title').should('have.text', 'Product Name');
|
|
23
|
+
* cy.get('.price').should('have.text', '$99.99');
|
|
24
|
+
* cy.get('.stock').should('contain', 'In Stock');
|
|
25
|
+
* // All assertions run, failures reported together at the end
|
|
26
|
+
* });
|
|
27
|
+
*/
|
|
28
|
+
function soft_it(title: string, fn: Mocha.Func | Mocha.AsyncFunc): Mocha.Test;
|
|
29
|
+
namespace soft_it {
|
|
30
|
+
/**
|
|
31
|
+
* Run only this test (like it.only)
|
|
32
|
+
*/
|
|
33
|
+
function only(title: string, fn: Mocha.Func | Mocha.AsyncFunc): Mocha.Test;
|
|
34
|
+
/**
|
|
35
|
+
* Skip this test (like it.skip)
|
|
36
|
+
*/
|
|
37
|
+
function skip(title: string, fn: Mocha.Func | Mocha.AsyncFunc): void;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cypress Soft Assertions Plugin
|
|
4
|
+
*
|
|
5
|
+
* Provides soft_it() function that wraps Cypress tests to make all assertions soft.
|
|
6
|
+
* Assertions don't stop execution on failure - they continue and all failures are
|
|
7
|
+
* aggregated and reported at the end of the test.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
let softAssertionErrors = [];
|
|
11
|
+
let isInSoftTest = false;
|
|
12
|
+
let originalAssert = null;
|
|
13
|
+
/**
|
|
14
|
+
* Intercept Chai assertions to capture failures instead of throwing
|
|
15
|
+
*/
|
|
16
|
+
function setupSoftAssertions() {
|
|
17
|
+
if (!originalAssert) {
|
|
18
|
+
// Store the original assert function
|
|
19
|
+
originalAssert = chai.Assertion.prototype.assert;
|
|
20
|
+
}
|
|
21
|
+
// Override the assert function to capture errors
|
|
22
|
+
chai.Assertion.prototype.assert = function (...args) {
|
|
23
|
+
if (isInSoftTest) {
|
|
24
|
+
try {
|
|
25
|
+
// Call the original assert
|
|
26
|
+
originalAssert.apply(this, args);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
// Capture the error instead of throwing
|
|
30
|
+
softAssertionErrors.push({
|
|
31
|
+
message: error.message,
|
|
32
|
+
stack: error.stack
|
|
33
|
+
});
|
|
34
|
+
// Don't throw - let the test continue
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Normal behavior for regular tests
|
|
39
|
+
originalAssert.apply(this, args);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Restore original Chai assertion behavior
|
|
45
|
+
*/
|
|
46
|
+
function restoreAssertions() {
|
|
47
|
+
if (originalAssert) {
|
|
48
|
+
chai.Assertion.prototype.assert = originalAssert;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Report all collected soft assertion failures
|
|
53
|
+
*/
|
|
54
|
+
function reportSoftAssertionFailures() {
|
|
55
|
+
if (softAssertionErrors.length > 0) {
|
|
56
|
+
const errorMessages = softAssertionErrors
|
|
57
|
+
.map((entry, index) => ` ${index + 1}. ${entry.message}`)
|
|
58
|
+
.join('\n');
|
|
59
|
+
const finalMessage = [
|
|
60
|
+
'',
|
|
61
|
+
'='.repeat(80),
|
|
62
|
+
`SOFT ASSERTION FAILURES (${softAssertionErrors.length} failed):`,
|
|
63
|
+
'='.repeat(80),
|
|
64
|
+
errorMessages,
|
|
65
|
+
'='.repeat(80),
|
|
66
|
+
''
|
|
67
|
+
].join('\n');
|
|
68
|
+
// Clear errors
|
|
69
|
+
const errorCount = softAssertionErrors.length;
|
|
70
|
+
softAssertionErrors = [];
|
|
71
|
+
// Throw the aggregated error
|
|
72
|
+
const error = new Error(finalMessage);
|
|
73
|
+
error.name = 'SoftAssertionError';
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* soft_it - Define a test where all assertions are soft (non-blocking)
|
|
79
|
+
*
|
|
80
|
+
* All Cypress assertions (.should(), expect(), assert()) within this test
|
|
81
|
+
* will continue execution on failure. At the end, all failures are reported together.
|
|
82
|
+
*
|
|
83
|
+
* @param title - Test title
|
|
84
|
+
* @param fn - Test function
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* soft_it('validates multiple fields', () => {
|
|
88
|
+
* cy.visit('/page');
|
|
89
|
+
* cy.get('.name').should('have.text', 'John'); // Won't stop if fails
|
|
90
|
+
* cy.get('.age').should('have.text', '25'); // Won't stop if fails
|
|
91
|
+
* cy.get('.city').should('have.text', 'NYC'); // Won't stop if fails
|
|
92
|
+
* });
|
|
93
|
+
*/
|
|
94
|
+
globalThis.soft_it = function (title, fn) {
|
|
95
|
+
return it(title, function () {
|
|
96
|
+
// Setup soft assertion mode
|
|
97
|
+
isInSoftTest = true;
|
|
98
|
+
softAssertionErrors = [];
|
|
99
|
+
setupSoftAssertions();
|
|
100
|
+
// Wrap the test function execution
|
|
101
|
+
const executeTest = () => {
|
|
102
|
+
try {
|
|
103
|
+
const result = fn.call(this);
|
|
104
|
+
// Handle async tests (Cypress tests return undefined, but we need to check after cy commands)
|
|
105
|
+
if (result && typeof result.then === 'function') {
|
|
106
|
+
return result.then(() => {
|
|
107
|
+
// Test completed - check for errors at the end
|
|
108
|
+
return cy.wrap(null).then(() => {
|
|
109
|
+
isInSoftTest = false;
|
|
110
|
+
reportSoftAssertionFailures();
|
|
111
|
+
});
|
|
112
|
+
}, (err) => {
|
|
113
|
+
isInSoftTest = false;
|
|
114
|
+
restoreAssertions();
|
|
115
|
+
throw err;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// For Cypress tests, we need to hook into the end of the command chain
|
|
119
|
+
return cy.wrap(null).then(() => {
|
|
120
|
+
isInSoftTest = false;
|
|
121
|
+
reportSoftAssertionFailures();
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
isInSoftTest = false;
|
|
126
|
+
restoreAssertions();
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
return executeTest();
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* soft_it.only - Run only this soft test
|
|
135
|
+
*/
|
|
136
|
+
globalThis.soft_it.only = function (title, fn) {
|
|
137
|
+
return it.only(title, function () {
|
|
138
|
+
isInSoftTest = true;
|
|
139
|
+
softAssertionErrors = [];
|
|
140
|
+
setupSoftAssertions();
|
|
141
|
+
const executeTest = () => {
|
|
142
|
+
try {
|
|
143
|
+
const result = fn.call(this);
|
|
144
|
+
if (result && typeof result.then === 'function') {
|
|
145
|
+
return result.then(() => {
|
|
146
|
+
return cy.wrap(null).then(() => {
|
|
147
|
+
isInSoftTest = false;
|
|
148
|
+
reportSoftAssertionFailures();
|
|
149
|
+
});
|
|
150
|
+
}, (err) => {
|
|
151
|
+
isInSoftTest = false;
|
|
152
|
+
restoreAssertions();
|
|
153
|
+
throw err;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return cy.wrap(null).then(() => {
|
|
157
|
+
isInSoftTest = false;
|
|
158
|
+
reportSoftAssertionFailures();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
isInSoftTest = false;
|
|
163
|
+
restoreAssertions();
|
|
164
|
+
throw err;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
return executeTest();
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* soft_it.skip - Skip this soft test
|
|
172
|
+
*/
|
|
173
|
+
globalThis.soft_it.skip = it.skip;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@koenvanbelle/cypress-soft-assertions",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A Cypress plugin that provides soft_it() for soft assertions - all assertions continue on failure and are reported together",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepublishOnly": "npm run build",
|
|
10
|
+
"cy:open": "cypress open",
|
|
11
|
+
"cy:run": "cypress run",
|
|
12
|
+
"test": "npm run build && cypress run"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"cypress",
|
|
16
|
+
"soft-assertions",
|
|
17
|
+
"testing",
|
|
18
|
+
"automation",
|
|
19
|
+
"e2e",
|
|
20
|
+
"cypress-plugin",
|
|
21
|
+
"test",
|
|
22
|
+
"assert",
|
|
23
|
+
"assertion"
|
|
24
|
+
],
|
|
25
|
+
"author": "Koen Van Belle",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/vanbellekoen/cypress-soft-assertions"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/vanbellekoen/cypress-soft-assertions/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/vanbellekoen/cypress-soft-assertions#readme",
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"cypress": ">=10.0.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"cypress": "^15.9.0",
|
|
40
|
+
"typescript": "^5.9.3",
|
|
41
|
+
"@types/mocha": "^10.0.10"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md"
|
|
46
|
+
]
|
|
47
|
+
}
|