@jahia/cypress 6.4.1 → 6.4.3
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.
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint-disable brace-style */
|
|
3
3
|
/* eslint-disable max-statements-per-line */
|
|
4
|
-
/**
|
|
5
|
-
* Module for monitoring and reporting JavaScript errors and warnings in Cypress tests.
|
|
6
|
-
* Provides methods to enable, disable, and check logger status.
|
|
7
|
-
*/
|
|
8
4
|
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
|
|
9
5
|
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
|
10
6
|
to[j] = from[i];
|
|
@@ -12,6 +8,10 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
|
|
|
12
8
|
};
|
|
13
9
|
exports.__esModule = true;
|
|
14
10
|
exports.jsErrorsLogger = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* Module for monitoring and reporting JavaScript errors and warnings in Cypress tests.
|
|
13
|
+
* Provides methods to enable, disable, and check logger status.
|
|
14
|
+
*/
|
|
15
15
|
var envVarDisableAll = 'JAHIA_HOOKS_DISABLE';
|
|
16
16
|
var envVarDisableJsLogger = 'JAHIA_HOOKS_DISABLE_JS_LOGGER';
|
|
17
17
|
var envVarCollector = '__JS_LOGGER_FAILURES__';
|
|
@@ -99,27 +99,26 @@ function setAllowedJsWarnings(warnings) { Cypress.env(envVarAllowedWarnings, war
|
|
|
99
99
|
*/
|
|
100
100
|
function attachJsInterceptor() {
|
|
101
101
|
/**
|
|
102
|
-
* Custom 'window:before:load' hook to attach interceptors before the page is loaded
|
|
103
|
-
* allowing us to spy on console messages.
|
|
102
|
+
* Custom 'window:before:load' hook to attach interceptors before the page is loaded and spy on console messages.
|
|
104
103
|
*/
|
|
105
|
-
|
|
104
|
+
cy.on('window:before:load', function (window) {
|
|
106
105
|
// Skip 'window:before:load' hook if the logger is disabled
|
|
107
106
|
if (isDisabled()) {
|
|
108
107
|
return;
|
|
109
108
|
}
|
|
110
|
-
// Spy on console.error and console.warn to capture errors and warnings
|
|
109
|
+
// Spy on console.error and console.warn methods to capture errors and warnings
|
|
111
110
|
cy.spy(window.console, 'error').as('errors');
|
|
112
111
|
cy.spy(window.console, 'warn').as('warnings');
|
|
113
112
|
});
|
|
114
113
|
/**
|
|
115
114
|
* Custom 'window:load' hook to collect JavaScript errors and warnings right after the page is loaded.
|
|
116
115
|
*/
|
|
117
|
-
|
|
116
|
+
cy.on('window:load', function (win) {
|
|
118
117
|
// Skip 'window:load' hook if the logger is disabled
|
|
119
118
|
if (isDisabled()) {
|
|
120
119
|
return;
|
|
121
120
|
}
|
|
122
|
-
// Collect
|
|
121
|
+
// Collect errors and warnings after the page is fully loaded
|
|
123
122
|
collectIssues(win);
|
|
124
123
|
});
|
|
125
124
|
}
|
|
@@ -128,9 +127,7 @@ function attachJsInterceptor() {
|
|
|
128
127
|
* @returns {Cypress.Chainable} - Cypress chainable object that resolves when issues are collected.
|
|
129
128
|
*/
|
|
130
129
|
function collectIssues(win) {
|
|
131
|
-
var allowedWarnings = getAllowedJsWarnings();
|
|
132
130
|
var consoleIssues = [];
|
|
133
|
-
var url = win.location.href;
|
|
134
131
|
// Look for console errors and warnings, collected by the spies
|
|
135
132
|
return cy.get('@errors')
|
|
136
133
|
.invoke('getCalls')
|
|
@@ -139,10 +136,11 @@ function collectIssues(win) {
|
|
|
139
136
|
consoleIssues = errorCalls.flatMap(function (call) { return call.args.map(function (arg) { return ({ type: 'error', msg: String(arg) }); }); });
|
|
140
137
|
})
|
|
141
138
|
.then(function () {
|
|
142
|
-
// Analyze warnings
|
|
143
|
-
cy.get('@warnings')
|
|
139
|
+
// Analyze warnings - return the chain to maintain proper async flow
|
|
140
|
+
return cy.get('@warnings')
|
|
144
141
|
.invoke('getCalls')
|
|
145
142
|
.then(function (warningCalls) {
|
|
143
|
+
var allowedWarnings = getAllowedJsWarnings();
|
|
146
144
|
warningCalls.flatMap(function (call) { return call.args; }).forEach(function (arg) {
|
|
147
145
|
// Only warnings not in the allowed list should be collected
|
|
148
146
|
if (!allowedWarnings.some(function (item) { return arg.includes(item); })) {
|
|
@@ -155,7 +153,7 @@ function collectIssues(win) {
|
|
|
155
153
|
// Update the Cypress environment variable with the collected issues
|
|
156
154
|
if (consoleIssues.length > 0) {
|
|
157
155
|
setCollectedIssues(__spreadArray(__spreadArray([], getCollectedIssues()), [
|
|
158
|
-
{ url:
|
|
156
|
+
{ url: win.location.href, test: Cypress.currentTest.title, errors: consoleIssues }
|
|
159
157
|
]));
|
|
160
158
|
}
|
|
161
159
|
});
|
|
@@ -164,8 +162,7 @@ function collectIssues(win) {
|
|
|
164
162
|
* Analyzes collected JavaScript errors and warnings and throws an error if any were found.
|
|
165
163
|
*/
|
|
166
164
|
function analyzeIssues() {
|
|
167
|
-
cy.then(function () {
|
|
168
|
-
var failures = getCollectedIssues();
|
|
165
|
+
return cy.wrap(getCollectedIssues()).then(function (failures) {
|
|
169
166
|
if (failures.length > 0) {
|
|
170
167
|
// Group all issues by test title
|
|
171
168
|
var groupedByTest = failures.reduce(function (acc, failure) {
|
|
@@ -202,16 +199,22 @@ function disable() { Cypress.env(envVarDisableJsLogger, true); }
|
|
|
202
199
|
* and throws an error if any issues are found after each or all tests are executed (depending on the strategy chosen).
|
|
203
200
|
*/
|
|
204
201
|
function enable() {
|
|
205
|
-
// Ensure the logger is enabled
|
|
202
|
+
// Ensure the logger is enabled
|
|
206
203
|
Cypress.env(envVarDisableJsLogger, false);
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
/**
|
|
205
|
+
* Attach Cypress hooks forconsole messages collecting before EACH test execution.
|
|
206
|
+
* Use 'beforeEach' hook and local (cy) context instead of global (Cypress) one
|
|
207
|
+
* to ensure proper async flow and avoid events and hooks flakiness.
|
|
208
|
+
*/
|
|
209
|
+
before(function () {
|
|
210
|
+
attachJsInterceptor();
|
|
211
|
+
});
|
|
209
212
|
/**
|
|
210
213
|
* Custom 'afterEach' hook to analyze JavaScript errors and warnings after EACH test execution.
|
|
211
214
|
*/
|
|
212
215
|
afterEach(function () {
|
|
213
216
|
// Skip the hook if the logger is disabled or if the strategy is not failAfterEach
|
|
214
|
-
if (isDisabled() || getStrategy() !== STRATEGY.failAfterEach) {
|
|
217
|
+
if (isDisabled() || (getStrategy() !== STRATEGY.failAfterEach)) {
|
|
215
218
|
return;
|
|
216
219
|
}
|
|
217
220
|
// Analyze collected errors and warnings
|
|
@@ -222,7 +225,7 @@ function enable() {
|
|
|
222
225
|
*/
|
|
223
226
|
after(function () {
|
|
224
227
|
// Skip the hook if the logger is disabled or if the strategy is not failAfterAll
|
|
225
|
-
if (isDisabled() || getStrategy() !== STRATEGY.failAfterAll) {
|
|
228
|
+
if (isDisabled() || (getStrategy() !== STRATEGY.failAfterAll)) {
|
|
226
229
|
return;
|
|
227
230
|
}
|
|
228
231
|
// Analyze collected errors and warnings
|
package/docs/js-errors-logger.md
CHANGED
|
@@ -28,6 +28,47 @@ The logger supports three distinct strategies for handling JavaScript errors and
|
|
|
28
28
|
- **Use Case**: Ideal for CI/CD environments where you want a complete test run overview
|
|
29
29
|
- **Pros**: Complete test suite execution with comprehensive error reporting
|
|
30
30
|
- **Cons**: Error reporting may be confusing as the last test will be marked as failed, since the errors analysis and reporting is done in after() hook
|
|
31
|
+
- **Hint:** To make reporting less confusing, dummy test can be added by the end of the spec to provide more clarity on why the spec failed, e.g:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
describe('Tests for the UI module', () => {
|
|
35
|
+
it('Should validate flow A', () => { ... });
|
|
36
|
+
|
|
37
|
+
it('Should validate flow B', () => { ... });
|
|
38
|
+
|
|
39
|
+
it('Should validate flow C', () => { ... });
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
// Dummy test to fail if any errors or warnings appear in the browser console,
|
|
43
|
+
// providing clearer insight into execution and failure reasons.
|
|
44
|
+
// Analysis itself will happen inside jsErrorsLogger module (if one is enabled).
|
|
45
|
+
it('Should ensure errors and warnings absense in browser console', () => {
|
|
46
|
+
cy.log('Analyze console messages');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
Say, there were JavaScript errors and warnings in all tests. Without that dummy test, the very last test in spec will be marked by Cypress as failed, even though it might pass:
|
|
51
|
+
```
|
|
52
|
+
✓ Should validate flow A
|
|
53
|
+
✓ Should validate flow B
|
|
54
|
+
- Should validate flow C
|
|
55
|
+
... <errors/warnings list for each visited url, grouped by test> ...
|
|
56
|
+
```
|
|
57
|
+
But with that dummy test it will be much clearer what exactly happened:
|
|
58
|
+
```
|
|
59
|
+
✓ Should validate flow A
|
|
60
|
+
✓ Should validate flow B
|
|
61
|
+
✓ Should validate flow C
|
|
62
|
+
- Should ensure errors and warnings absence in browser console during spec execution
|
|
63
|
+
... <errors/warnings list for each visited url, grouped by test> ...
|
|
64
|
+
```
|
|
65
|
+
And in case of JavaScript errors and warnings absense (and all tests passed) it will also be much clearer - what validations were performed:
|
|
66
|
+
```
|
|
67
|
+
✓ Should validate flow A
|
|
68
|
+
✓ Should validate flow B
|
|
69
|
+
✓ Should validate flow C
|
|
70
|
+
✓ Should ensure errors and warnings absense in browser console during spec execution
|
|
71
|
+
```
|
|
31
72
|
|
|
32
73
|
## Usage
|
|
33
74
|
|
package/env.provision.sh
CHANGED
|
@@ -76,7 +76,7 @@ if [[ -d artifacts/ ]]; then
|
|
|
76
76
|
for file in $(ls -1 *-SNAPSHOT.jar | sort -n)
|
|
77
77
|
do
|
|
78
78
|
echo "$(date +'%d %B %Y - %k:%M') [MODULE_INSTALL] == Submitting module from: $file =="
|
|
79
|
-
curl -u root:${SUPER_USER_PASSWORD} -X POST ${JAHIA_URL}/modules/api/provisioning --form script='[{"
|
|
79
|
+
curl -u root:${SUPER_USER_PASSWORD} -X POST ${JAHIA_URL}/modules/api/provisioning --form script='[{"installOrUpgradeBundle":"'"$file"'", "forceUpdate":true}]' --form file=@$file
|
|
80
80
|
echo
|
|
81
81
|
echo "$(date +'%d %B %Y - %k:%M') [MODULE_INSTALL] == Module submitted =="
|
|
82
82
|
done
|
|
@@ -85,7 +85,7 @@ if [[ -d artifacts/ ]]; then
|
|
|
85
85
|
for file in $(ls -1 *-SNAPSHOT.tgz | sort -n)
|
|
86
86
|
do
|
|
87
87
|
echo "$(date +'%d %B %Y - %k:%M') [MODULE_INSTALL] == Submitting Javascript module from: $file =="
|
|
88
|
-
curl -u root:${SUPER_USER_PASSWORD} -X POST ${JAHIA_URL}/modules/api/provisioning --form script='[{"
|
|
88
|
+
curl -u root:${SUPER_USER_PASSWORD} -X POST ${JAHIA_URL}/modules/api/provisioning --form script='[{"installOrUpgradeBundle":"'"$file"'", "forceUpdate":true}]' --form file=@$file
|
|
89
89
|
echo
|
|
90
90
|
echo "$(date +'%d %B %Y - %k:%M') [MODULE_INSTALL] == Javascript Module submitted =="
|
|
91
91
|
done
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jahia/cypress",
|
|
3
|
-
"version": "6.4.
|
|
3
|
+
"version": "6.4.3",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build": "tsc",
|
|
6
6
|
"lint": "eslint src -c .eslintrc.json --ext .ts --max-warnings=0"
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"types": "dist/index.d.ts",
|
|
16
16
|
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/Jahia/jahia-cypress.git"
|
|
20
|
+
},
|
|
17
21
|
"devDependencies": {
|
|
18
22
|
"@jahia/eslint-config": "^1.1.0",
|
|
19
23
|
"@typescript-eslint/eslint-plugin": "^4.29.3",
|
|
@@ -34,5 +38,5 @@
|
|
|
34
38
|
"graphql": "^15.5.0",
|
|
35
39
|
"graphql-tag": "^2.11.0"
|
|
36
40
|
},
|
|
37
|
-
"packageManager": "yarn@4.
|
|
38
|
-
}
|
|
41
|
+
"packageManager": "yarn@4.12.0"
|
|
42
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable brace-style */
|
|
2
2
|
/* eslint-disable max-statements-per-line */
|
|
3
|
+
|
|
3
4
|
/**
|
|
4
5
|
* Module for monitoring and reporting JavaScript errors and warnings in Cypress tests.
|
|
5
6
|
* Provides methods to enable, disable, and check logger status.
|
|
@@ -108,13 +109,12 @@ function setAllowedJsWarnings(warnings: string[]): void { Cypress.env(envVarAllo
|
|
|
108
109
|
*/
|
|
109
110
|
function attachJsInterceptor(): void {
|
|
110
111
|
/**
|
|
111
|
-
* Custom 'window:before:load' hook to attach interceptors before the page is loaded
|
|
112
|
-
* allowing us to spy on console messages.
|
|
112
|
+
* Custom 'window:before:load' hook to attach interceptors before the page is loaded and spy on console messages.
|
|
113
113
|
*/
|
|
114
|
-
|
|
114
|
+
cy.on('window:before:load', window => {
|
|
115
115
|
// Skip 'window:before:load' hook if the logger is disabled
|
|
116
116
|
if (isDisabled()) { return; }
|
|
117
|
-
// Spy on console.error and console.warn to capture errors and warnings
|
|
117
|
+
// Spy on console.error and console.warn methods to capture errors and warnings
|
|
118
118
|
cy.spy(window.console, 'error').as('errors');
|
|
119
119
|
cy.spy(window.console, 'warn').as('warnings');
|
|
120
120
|
});
|
|
@@ -122,10 +122,10 @@ function attachJsInterceptor(): void {
|
|
|
122
122
|
/**
|
|
123
123
|
* Custom 'window:load' hook to collect JavaScript errors and warnings right after the page is loaded.
|
|
124
124
|
*/
|
|
125
|
-
|
|
125
|
+
cy.on('window:load', win => {
|
|
126
126
|
// Skip 'window:load' hook if the logger is disabled
|
|
127
127
|
if (isDisabled()) { return; }
|
|
128
|
-
// Collect
|
|
128
|
+
// Collect errors and warnings after the page is fully loaded
|
|
129
129
|
collectIssues(win);
|
|
130
130
|
});
|
|
131
131
|
}
|
|
@@ -135,9 +135,7 @@ function attachJsInterceptor(): void {
|
|
|
135
135
|
* @returns {Cypress.Chainable} - Cypress chainable object that resolves when issues are collected.
|
|
136
136
|
*/
|
|
137
137
|
function collectIssues(win: Cypress.AUTWindow): Cypress.Chainable {
|
|
138
|
-
const allowedWarnings = getAllowedJsWarnings();
|
|
139
138
|
let consoleIssues: {type: string, msg: string}[] = [];
|
|
140
|
-
const url = win.location.href;
|
|
141
139
|
|
|
142
140
|
// Look for console errors and warnings, collected by the spies
|
|
143
141
|
return cy.get('@errors')
|
|
@@ -147,10 +145,11 @@ function collectIssues(win: Cypress.AUTWindow): Cypress.Chainable {
|
|
|
147
145
|
consoleIssues = errorCalls.flatMap((call: { args: unknown[] }) => call.args.map((arg: string) => ({type: 'error', msg: String(arg)})));
|
|
148
146
|
})
|
|
149
147
|
.then(() => {
|
|
150
|
-
// Analyze warnings
|
|
151
|
-
cy.get('@warnings')
|
|
148
|
+
// Analyze warnings - return the chain to maintain proper async flow
|
|
149
|
+
return cy.get('@warnings')
|
|
152
150
|
.invoke('getCalls')
|
|
153
151
|
.then(warningCalls => {
|
|
152
|
+
const allowedWarnings = getAllowedJsWarnings();
|
|
154
153
|
warningCalls.flatMap((call: { args: unknown[] }) => call.args).forEach((arg: string) => {
|
|
155
154
|
// Only warnings not in the allowed list should be collected
|
|
156
155
|
if (!allowedWarnings.some((item: string) => arg.includes(item))) { consoleIssues.push({type: 'warn', msg: String(arg)}); }
|
|
@@ -162,7 +161,7 @@ function collectIssues(win: Cypress.AUTWindow): Cypress.Chainable {
|
|
|
162
161
|
if (consoleIssues.length > 0) {
|
|
163
162
|
setCollectedIssues([
|
|
164
163
|
...getCollectedIssues(),
|
|
165
|
-
{url:
|
|
164
|
+
{url: win.location.href, test: Cypress.currentTest.title, errors: consoleIssues}
|
|
166
165
|
]);
|
|
167
166
|
}
|
|
168
167
|
});
|
|
@@ -171,10 +170,8 @@ function collectIssues(win: Cypress.AUTWindow): Cypress.Chainable {
|
|
|
171
170
|
/**
|
|
172
171
|
* Analyzes collected JavaScript errors and warnings and throws an error if any were found.
|
|
173
172
|
*/
|
|
174
|
-
function analyzeIssues():
|
|
175
|
-
cy.
|
|
176
|
-
const failures = getCollectedIssues();
|
|
177
|
-
|
|
173
|
+
function analyzeIssues(): Cypress.Chainable {
|
|
174
|
+
return cy.wrap(getCollectedIssues()).then(failures => {
|
|
178
175
|
if (failures.length > 0) {
|
|
179
176
|
// Group all issues by test title
|
|
180
177
|
const groupedByTest = failures.reduce((acc: Record<string, CollectorItem[]>, failure) => {
|
|
@@ -220,18 +217,24 @@ function disable(): void { Cypress.env(envVarDisableJsLogger, true); }
|
|
|
220
217
|
* and throws an error if any issues are found after each or all tests are executed (depending on the strategy chosen).
|
|
221
218
|
*/
|
|
222
219
|
function enable(): void {
|
|
223
|
-
// Ensure the logger is enabled
|
|
220
|
+
// Ensure the logger is enabled
|
|
224
221
|
Cypress.env(envVarDisableJsLogger, false);
|
|
225
222
|
|
|
226
|
-
|
|
227
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Attach Cypress hooks forconsole messages collecting before EACH test execution.
|
|
225
|
+
* Use 'beforeEach' hook and local (cy) context instead of global (Cypress) one
|
|
226
|
+
* to ensure proper async flow and avoid events and hooks flakiness.
|
|
227
|
+
*/
|
|
228
|
+
before(() => {
|
|
229
|
+
attachJsInterceptor();
|
|
230
|
+
});
|
|
228
231
|
|
|
229
232
|
/**
|
|
230
233
|
* Custom 'afterEach' hook to analyze JavaScript errors and warnings after EACH test execution.
|
|
231
234
|
*/
|
|
232
235
|
afterEach(() => {
|
|
233
236
|
// Skip the hook if the logger is disabled or if the strategy is not failAfterEach
|
|
234
|
-
if (isDisabled() || getStrategy() !== STRATEGY.failAfterEach) { return; }
|
|
237
|
+
if (isDisabled() || (getStrategy() !== STRATEGY.failAfterEach)) { return; }
|
|
235
238
|
// Analyze collected errors and warnings
|
|
236
239
|
analyzeIssues();
|
|
237
240
|
});
|
|
@@ -241,7 +244,7 @@ function enable(): void {
|
|
|
241
244
|
*/
|
|
242
245
|
after(() => {
|
|
243
246
|
// Skip the hook if the logger is disabled or if the strategy is not failAfterAll
|
|
244
|
-
if (isDisabled() || getStrategy() !== STRATEGY.failAfterAll) { return; }
|
|
247
|
+
if (isDisabled() || (getStrategy() !== STRATEGY.failAfterAll)) { return; }
|
|
245
248
|
// Analyze collected errors and warnings
|
|
246
249
|
analyzeIssues();
|
|
247
250
|
});
|