@jahia/cypress 6.4.1 → 6.4.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.
@@ -1,7 +1,3 @@
1
- /**
2
- * Module for monitoring and reporting JavaScript errors and warnings in Cypress tests.
3
- * Provides methods to enable, disable, and check logger status.
4
- */
5
1
  /**
6
2
  * Strategy for handling JavaScript errors and warnings in Cypress tests.
7
3
  *
@@ -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
- Cypress.on('window:before:load', function (window) {
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
- Cypress.on('window:load', function (win) {
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 issues immediately after the window is loaded and analyze them
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: url, test: Cypress.currentTest.title, errors: consoleIssues }
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 by default
202
+ // Ensure the logger is enabled
206
203
  Cypress.env(envVarDisableJsLogger, false);
207
- // Attach errors and warnings collector
208
- attachJsInterceptor();
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
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jahia/cypress",
3
- "version": "6.4.1",
3
+ "version": "6.4.2",
4
4
  "scripts": {
5
5
  "build": "tsc",
6
6
  "lint": "eslint src -c .eslintrc.json --ext .ts --max-warnings=0"
@@ -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
- Cypress.on('window:before:load', window => {
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
- Cypress.on('window:load', win => {
125
+ cy.on('window:load', win => {
126
126
  // Skip 'window:load' hook if the logger is disabled
127
127
  if (isDisabled()) { return; }
128
- // Collect issues immediately after the window is loaded and analyze them
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: url, test: Cypress.currentTest.title, errors: consoleIssues}
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(): void {
175
- cy.then(() => {
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 by default
220
+ // Ensure the logger is enabled
224
221
  Cypress.env(envVarDisableJsLogger, false);
225
222
 
226
- // Attach errors and warnings collector
227
- attachJsInterceptor();
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
  });