@jahia/cypress 6.3.1 → 6.4.1
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/support/jsErrorsLogger.d.ts +37 -9
- package/dist/support/jsErrorsLogger.js +147 -184
- package/dist/support/registerSupport.js +0 -8
- package/dist/utils/Logger.d.ts +10 -2
- package/dist/utils/Logger.js +64 -4
- package/docs/js-errors-logger.md +78 -61
- package/package.json +1 -1
- package/src/support/jsErrorsLogger.ts +167 -187
- package/src/support/registerSupport.ts +0 -9
- package/src/utils/Logger.ts +96 -5
|
@@ -4,15 +4,31 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
6
|
* Strategy for handling JavaScript errors and warnings in Cypress tests.
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
* - failAfterEach: Collect all errors and warnings *during test* execution and fail if any issues are found.
|
|
9
|
+
*
|
|
10
|
+
* Proc: Allows each test to run, collects console errors and warnings,
|
|
11
|
+
* and fails the particular test by the end of its execution if any issues are found.
|
|
12
|
+
* Cons: Since the analysis happens in afterEach() hook, the rest of spec will be ignored.
|
|
13
|
+
*
|
|
9
14
|
* - failAfterAll: Collect all errors and warnings *after all tests* and fail at the end of the test suite.
|
|
15
|
+
*
|
|
16
|
+
* Proc: Allows all tests to run, collects console errors and warnings, and fails the test suite at the end if any issues are found.
|
|
17
|
+
* This is useful for reporting all issues at once after all tests are executed, rather than failing immediately on the first issue.
|
|
18
|
+
* Cons: Reporting might be confusing, e.g. - cypress will report the very last test as failed, while many tests might have issues.
|
|
19
|
+
* This is because the hook is executed after all tests are completed, so the last test is reported as failed.
|
|
10
20
|
*/
|
|
11
21
|
declare enum STRATEGY {
|
|
12
|
-
|
|
13
|
-
failAfterAll = 1
|
|
14
|
-
failAfterEach = 2
|
|
22
|
+
failAfterEach = 0,
|
|
23
|
+
failAfterAll = 1
|
|
15
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns the current strategy for handling JavaScript errors and warnings in Cypress tests.
|
|
27
|
+
* @returns {STRATEGY} - The current strategy for handling JavaScript errors and warnings.
|
|
28
|
+
* @note be careful with Cypress.env(envVarStrategy), since it might return `0` for `failAfterEach` strategy,
|
|
29
|
+
* which is falsy in JavaScript, so we need to check if the variable is undefined.
|
|
30
|
+
*/
|
|
31
|
+
declare function getStrategy(): STRATEGY;
|
|
16
32
|
/**
|
|
17
33
|
* Sets the strategy for handling JavaScript errors and warnings in Cypress tests.
|
|
18
34
|
* @param {STRATEGY} strategy - Strategy for handling JavaScript errors and warnings.
|
|
@@ -20,26 +36,38 @@ declare enum STRATEGY {
|
|
|
20
36
|
* @returns {void}
|
|
21
37
|
*/
|
|
22
38
|
declare function setStrategy(strategy: STRATEGY): void;
|
|
39
|
+
/**
|
|
40
|
+
* Returns the list of allowed warnings that will not be reported by the logger.
|
|
41
|
+
* @returns {string[]} - Array of allowed warning messages.
|
|
42
|
+
*/
|
|
43
|
+
declare function getAllowedJsWarnings(): string[];
|
|
23
44
|
/**
|
|
24
45
|
* Sets the list of allowed warnings that will not be reported by the logger.
|
|
25
46
|
* @param warnings {string[]} - Array of warning messages to be allowed.
|
|
26
47
|
* @return {void}
|
|
27
48
|
*/
|
|
28
49
|
declare function setAllowedJsWarnings(warnings: string[]): void;
|
|
50
|
+
/**
|
|
51
|
+
* Disables the js errors and warnings logger.
|
|
52
|
+
* @returns {void}
|
|
53
|
+
*/
|
|
54
|
+
declare function disable(): void;
|
|
29
55
|
/**
|
|
30
56
|
* Attaches custom hooks to Cypress events to monitor and report JavaScript errors and warnings.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* and throws an error if any issues are found after all tests are executed.
|
|
57
|
+
* It sets up listeners for console errors and warnings, collects them for each visited URL in each test,
|
|
58
|
+
* and throws an error if any issues are found after each or all tests are executed (depending on the strategy chosen).
|
|
34
59
|
*/
|
|
35
|
-
declare function
|
|
60
|
+
declare function enable(): void;
|
|
36
61
|
/**
|
|
37
62
|
* Exports the jsLogger module with methods to attach hooks, enable/disable logging, and set allowed warnings.
|
|
38
63
|
*/
|
|
39
64
|
export declare const jsErrorsLogger: {
|
|
40
|
-
attachHooks: typeof attachHooks;
|
|
41
65
|
setAllowedJsWarnings: typeof setAllowedJsWarnings;
|
|
66
|
+
getAllowedJsWarnings: typeof getAllowedJsWarnings;
|
|
42
67
|
setStrategy: typeof setStrategy;
|
|
68
|
+
getStrategy: typeof getStrategy;
|
|
69
|
+
enable: typeof enable;
|
|
70
|
+
disable: typeof disable;
|
|
43
71
|
STRATEGY: typeof STRATEGY;
|
|
44
72
|
};
|
|
45
73
|
export {};
|
|
@@ -12,30 +12,54 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
|
|
|
12
12
|
};
|
|
13
13
|
exports.__esModule = true;
|
|
14
14
|
exports.jsErrorsLogger = void 0;
|
|
15
|
-
var
|
|
15
|
+
var envVarDisableAll = 'JAHIA_HOOKS_DISABLE';
|
|
16
|
+
var envVarDisableJsLogger = 'JAHIA_HOOKS_DISABLE_JS_LOGGER';
|
|
16
17
|
var envVarCollector = '__JS_LOGGER_FAILURES__';
|
|
17
18
|
var envVarAllowedWarnings = '__JS_LOGGER_ALLOWED_WARNINGS__';
|
|
18
19
|
var envVarStrategy = '__JS_LOGGER_STRATEGY__';
|
|
19
20
|
/**
|
|
20
21
|
* Strategy for handling JavaScript errors and warnings in Cypress tests.
|
|
21
|
-
*
|
|
22
|
+
*
|
|
22
23
|
* - failAfterEach: Collect all errors and warnings *during test* execution and fail if any issues are found.
|
|
24
|
+
*
|
|
25
|
+
* Proc: Allows each test to run, collects console errors and warnings,
|
|
26
|
+
* and fails the particular test by the end of its execution if any issues are found.
|
|
27
|
+
* Cons: Since the analysis happens in afterEach() hook, the rest of spec will be ignored.
|
|
28
|
+
*
|
|
23
29
|
* - failAfterAll: Collect all errors and warnings *after all tests* and fail at the end of the test suite.
|
|
30
|
+
*
|
|
31
|
+
* Proc: Allows all tests to run, collects console errors and warnings, and fails the test suite at the end if any issues are found.
|
|
32
|
+
* This is useful for reporting all issues at once after all tests are executed, rather than failing immediately on the first issue.
|
|
33
|
+
* Cons: Reporting might be confusing, e.g. - cypress will report the very last test as failed, while many tests might have issues.
|
|
34
|
+
* This is because the hook is executed after all tests are completed, so the last test is reported as failed.
|
|
24
35
|
*/
|
|
25
36
|
var STRATEGY;
|
|
26
37
|
(function (STRATEGY) {
|
|
27
|
-
STRATEGY[STRATEGY["
|
|
38
|
+
STRATEGY[STRATEGY["failAfterEach"] = 0] = "failAfterEach";
|
|
28
39
|
STRATEGY[STRATEGY["failAfterAll"] = 1] = "failAfterAll";
|
|
29
|
-
STRATEGY[STRATEGY["failAfterEach"] = 2] = "failAfterEach";
|
|
30
40
|
})(STRATEGY || (STRATEGY = {}));
|
|
41
|
+
/**
|
|
42
|
+
* Returns an emoji based on the type of message.
|
|
43
|
+
* @param {string} type
|
|
44
|
+
*/
|
|
45
|
+
function getEmoji(type) {
|
|
46
|
+
switch (type) {
|
|
47
|
+
case 'warn':
|
|
48
|
+
return '⚠️';
|
|
49
|
+
case 'error':
|
|
50
|
+
return '❌️';
|
|
51
|
+
default:
|
|
52
|
+
return '';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
31
55
|
/**
|
|
32
56
|
* Returns the current strategy for handling JavaScript errors and warnings in Cypress tests.
|
|
33
57
|
* @returns {STRATEGY} - The current strategy for handling JavaScript errors and warnings.
|
|
34
|
-
* @note be careful with Cypress.env(envVarStrategy), since it might return `0` for `
|
|
58
|
+
* @note be careful with Cypress.env(envVarStrategy), since it might return `0` for `failAfterEach` strategy,
|
|
35
59
|
* which is falsy in JavaScript, so we need to check if the variable is undefined.
|
|
36
60
|
*/
|
|
37
61
|
function getStrategy() {
|
|
38
|
-
return typeof Cypress.env(envVarStrategy) === 'undefined' ? STRATEGY.
|
|
62
|
+
return typeof Cypress.env(envVarStrategy) === 'undefined' ? STRATEGY.failAfterAll : Cypress.env(envVarStrategy);
|
|
39
63
|
}
|
|
40
64
|
/**
|
|
41
65
|
* Sets the strategy for handling JavaScript errors and warnings in Cypress tests.
|
|
@@ -44,11 +68,26 @@ function getStrategy() {
|
|
|
44
68
|
* @returns {void}
|
|
45
69
|
*/
|
|
46
70
|
function setStrategy(strategy) { Cypress.env(envVarStrategy, strategy); }
|
|
71
|
+
/**
|
|
72
|
+
* Returns console issues collected during the test execution.
|
|
73
|
+
* @returns {CollectorItem []} - Array of collected issues, each issue is an object with test title and errors.
|
|
74
|
+
*/
|
|
75
|
+
function getCollectedIssues() { return Cypress.env(envVarCollector) || []; }
|
|
76
|
+
/**
|
|
77
|
+
* Sets the console issues collected during the test execution.
|
|
78
|
+
* @returns {void}
|
|
79
|
+
*/
|
|
80
|
+
function setCollectedIssues(items) { Cypress.env(envVarCollector, items); }
|
|
47
81
|
/**
|
|
48
82
|
* Checks if the js errors and warnings logger is disabled.
|
|
49
83
|
* @returns {boolean} - true if the logger is disabled, false otherwise.
|
|
50
84
|
*/
|
|
51
|
-
function isDisabled() { return Cypress.env(
|
|
85
|
+
function isDisabled() { return ((Cypress.env(envVarDisableAll) === true) || (Cypress.env(envVarDisableJsLogger) === true)); }
|
|
86
|
+
/**
|
|
87
|
+
* Returns the list of allowed warnings that will not be reported by the logger.
|
|
88
|
+
* @returns {string[]} - Array of allowed warning messages.
|
|
89
|
+
*/
|
|
90
|
+
function getAllowedJsWarnings() { return Cypress.env(envVarAllowedWarnings) || []; }
|
|
52
91
|
/**
|
|
53
92
|
* Sets the list of allowed warnings that will not be reported by the logger.
|
|
54
93
|
* @param warnings {string[]} - Array of warning messages to be allowed.
|
|
@@ -56,225 +95,149 @@ function isDisabled() { return Cypress.env(envVarDisabled) === true; }
|
|
|
56
95
|
*/
|
|
57
96
|
function setAllowedJsWarnings(warnings) { Cypress.env(envVarAllowedWarnings, warnings); }
|
|
58
97
|
/**
|
|
59
|
-
* Attaches custom
|
|
60
|
-
* This method is called automatically in registerSupport.ts#registerSupport
|
|
61
|
-
* It sets up listeners for console errors and warnings, collects them after each test,
|
|
62
|
-
* and throws an error if any issues are found after all tests are executed.
|
|
63
|
-
*/
|
|
64
|
-
function attachHooks() {
|
|
65
|
-
// Skip hook attachment if the logger is disabled (e.g. from CI/CD pipeline)
|
|
66
|
-
if (isDisabled()) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
switch (getStrategy()) {
|
|
70
|
-
case STRATEGY.failAfterAll:
|
|
71
|
-
attachFailAfterAll();
|
|
72
|
-
break;
|
|
73
|
-
case STRATEGY.failAfterEach:
|
|
74
|
-
attachFailAfterEach();
|
|
75
|
-
break;
|
|
76
|
-
default:
|
|
77
|
-
attachFailFast();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Custom hook implementation which fails the test after all tests are executed if any JavaScript errors or warnings are found.
|
|
82
|
-
*
|
|
83
|
-
* Proc: Allows all tests to run, collects console errors and warnings, and fails the test suite at the end if any issues are found.
|
|
84
|
-
* This is useful for reporting all issues at once after all tests are executed, rather than failing immediately on the first issue.
|
|
85
|
-
* Cons: Reporting might be confusing, e.g. - cypress will report the very last test as failed, while many tests might have issues.
|
|
86
|
-
* This is because the hook is executed after all tests are completed, so the last test is reported as failed.
|
|
98
|
+
* Attaches a custom JavaScript interceptor to capture console errors and warnings.
|
|
87
99
|
*/
|
|
88
|
-
function
|
|
100
|
+
function attachJsInterceptor() {
|
|
89
101
|
/**
|
|
90
|
-
* Custom 'window:before:load' hook to
|
|
91
|
-
*
|
|
102
|
+
* Custom 'window:before:load' hook to attach interceptors before the page is loaded,
|
|
103
|
+
* allowing us to spy on console messages.
|
|
92
104
|
*/
|
|
93
105
|
Cypress.on('window:before:load', function (window) {
|
|
94
|
-
// Skip 'window:before:load' hook if the logger is
|
|
95
|
-
// Double-check in case if functionality was disabled within the test-case code
|
|
96
|
-
// to skip js validations for some particular test and enable it afterward
|
|
106
|
+
// Skip 'window:before:load' hook if the logger is disabled
|
|
97
107
|
if (isDisabled()) {
|
|
98
108
|
return;
|
|
99
109
|
}
|
|
110
|
+
// Spy on console.error and console.warn to capture errors and warnings
|
|
100
111
|
cy.spy(window.console, 'error').as('errors');
|
|
101
112
|
cy.spy(window.console, 'warn').as('warnings');
|
|
102
113
|
});
|
|
103
114
|
/**
|
|
104
|
-
* Custom '
|
|
115
|
+
* Custom 'window:load' hook to collect JavaScript errors and warnings right after the page is loaded.
|
|
105
116
|
*/
|
|
106
|
-
|
|
107
|
-
// Skip '
|
|
108
|
-
// Double-check in case if functionality was disabled within the test-case code
|
|
109
|
-
// to skip js validations for some particular test and enable it afterward
|
|
117
|
+
Cypress.on('window:load', function (win) {
|
|
118
|
+
// Skip 'window:load' hook if the logger is disabled
|
|
110
119
|
if (isDisabled()) {
|
|
111
120
|
return;
|
|
112
121
|
}
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
// Collect issues immediately after the window is loaded and analyze them
|
|
123
|
+
collectIssues(win);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Collects JavaScript errors and warnings using the spies set up in attachJsInterceptor.
|
|
128
|
+
* @returns {Cypress.Chainable} - Cypress chainable object that resolves when issues are collected.
|
|
129
|
+
*/
|
|
130
|
+
function collectIssues(win) {
|
|
131
|
+
var allowedWarnings = getAllowedJsWarnings();
|
|
132
|
+
var consoleIssues = [];
|
|
133
|
+
var url = win.location.href;
|
|
134
|
+
// Look for console errors and warnings, collected by the spies
|
|
135
|
+
return cy.get('@errors')
|
|
136
|
+
.invoke('getCalls')
|
|
137
|
+
.then(function (errorCalls) {
|
|
115
138
|
// All errors should be collected
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
//
|
|
139
|
+
consoleIssues = errorCalls.flatMap(function (call) { return call.args.map(function (arg) { return ({ type: 'error', msg: String(arg) }); }); });
|
|
140
|
+
})
|
|
141
|
+
.then(function () {
|
|
142
|
+
// Analyze warnings
|
|
120
143
|
cy.get('@warnings')
|
|
121
144
|
.invoke('getCalls')
|
|
122
|
-
.
|
|
123
|
-
call.args.forEach(function (arg) {
|
|
145
|
+
.then(function (warningCalls) {
|
|
146
|
+
warningCalls.flatMap(function (call) { return call.args; }).forEach(function (arg) {
|
|
147
|
+
// Only warnings not in the allowed list should be collected
|
|
124
148
|
if (!allowedWarnings.some(function (item) { return arg.includes(item); })) {
|
|
125
|
-
consoleIssues.push(arg);
|
|
149
|
+
consoleIssues.push({ type: 'warn', msg: String(arg) });
|
|
126
150
|
}
|
|
127
151
|
});
|
|
128
152
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
/**
|
|
140
|
-
* Custom 'after' hook to analyze collected errors and warnings after all tests are executed.
|
|
141
|
-
*/
|
|
142
|
-
after(function () {
|
|
143
|
-
// Skip 'after' hook if the logger is not enabled
|
|
144
|
-
// Double-check in case if functionality was disabled within the test-case code
|
|
145
|
-
// to skip js validations for some particular test and enable it afterward
|
|
146
|
-
if (isDisabled()) {
|
|
147
|
-
return;
|
|
153
|
+
})
|
|
154
|
+
.then(function () {
|
|
155
|
+
// Update the Cypress environment variable with the collected issues
|
|
156
|
+
if (consoleIssues.length > 0) {
|
|
157
|
+
setCollectedIssues(__spreadArray(__spreadArray([], getCollectedIssues()), [
|
|
158
|
+
{ url: url, test: Cypress.currentTest.title, errors: consoleIssues }
|
|
159
|
+
]));
|
|
148
160
|
}
|
|
149
|
-
// Analyze collected errors and warnings
|
|
150
|
-
var failures = Cypress.env(envVarCollector) || [];
|
|
151
|
-
cy.log('[JS ERRORS LOGGER] Analyze collected issues').then(function () {
|
|
152
|
-
if (failures.length > 0) {
|
|
153
|
-
// Format the error message for each test
|
|
154
|
-
var errorMessage = failures.map(function (failure) {
|
|
155
|
-
return "TEST: " + failure.test + "\nISSUES:\n" + failure.errors.map(function (e) { return "- " + e; }).join('\n');
|
|
156
|
-
}).join('\n\n');
|
|
157
|
-
// Throw an error with the collected issues
|
|
158
|
-
throw new Error('CONSOLE ERRORS and WARNINGS FOUND:\n\n' + errorMessage);
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
cy.log('[JS ERRORS LOGGER] No console errors or warnings found.');
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
161
|
});
|
|
165
162
|
}
|
|
166
163
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* Proc: Allows each test to run, collects console errors and warnings, and fails the particular test by the end of it's execution
|
|
170
|
-
* if any issues are found.
|
|
171
|
-
* Cons: If errors or warnings were found during beforeEach or afterEach hook(s), the rest of spec will be ignored.
|
|
164
|
+
* Analyzes collected JavaScript errors and warnings and throws an error if any were found.
|
|
172
165
|
*/
|
|
173
|
-
function
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
166
|
+
function analyzeIssues() {
|
|
167
|
+
cy.then(function () {
|
|
168
|
+
var failures = getCollectedIssues();
|
|
169
|
+
if (failures.length > 0) {
|
|
170
|
+
// Group all issues by test title
|
|
171
|
+
var groupedByTest = failures.reduce(function (acc, failure) {
|
|
172
|
+
acc[failure.test] = acc[failure.test] || [];
|
|
173
|
+
acc[failure.test].push(failure);
|
|
174
|
+
return acc;
|
|
175
|
+
}, {});
|
|
176
|
+
// Format the error message for each test with its collected issues
|
|
177
|
+
var errorMessage = Object.entries(groupedByTest).map(function (_a) {
|
|
178
|
+
var test = _a[0], items = _a[1];
|
|
179
|
+
var urlsAndErrors = items.map(function (item) {
|
|
180
|
+
return "URL: " + item.url + "\nISSUES:\n" + item.errors.map(function (e) { return "- " + (e.type === 'warn' ? getEmoji('warn') : getEmoji('error')) + " " + e.msg; }).join('\n');
|
|
181
|
+
}).join('\n\n');
|
|
182
|
+
// Return the formatted message for the test;
|
|
183
|
+
// Intentionally use fixed-width (50 chars) separators for better readability,
|
|
184
|
+
// when the message might be wrapped
|
|
185
|
+
return getEmoji('error') + "\uFE0F TEST: " + test.trim() + " " + getEmoji('error') + "\uFE0F\n" + '-'.repeat(50) + "\n" + urlsAndErrors + "\n" + '='.repeat(50);
|
|
186
|
+
}).join('\n\n');
|
|
187
|
+
// Reset the collector for the next test run
|
|
188
|
+
setCollectedIssues([]);
|
|
189
|
+
// Throw an error with the collected issues
|
|
190
|
+
throw new Error('CONSOLE ERRORS and WARNINGS FOUND:\n\n' + errorMessage);
|
|
191
|
+
}
|
|
186
192
|
});
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Disables the js errors and warnings logger.
|
|
196
|
+
* @returns {void}
|
|
197
|
+
*/
|
|
198
|
+
function disable() { Cypress.env(envVarDisableJsLogger, true); }
|
|
199
|
+
/**
|
|
200
|
+
* Attaches custom hooks to Cypress events to monitor and report JavaScript errors and warnings.
|
|
201
|
+
* It sets up listeners for console errors and warnings, collects them for each visited URL in each test,
|
|
202
|
+
* and throws an error if any issues are found after each or all tests are executed (depending on the strategy chosen).
|
|
203
|
+
*/
|
|
204
|
+
function enable() {
|
|
205
|
+
// Ensure the logger is enabled by default
|
|
206
|
+
Cypress.env(envVarDisableJsLogger, false);
|
|
207
|
+
// Attach errors and warnings collector
|
|
208
|
+
attachJsInterceptor();
|
|
187
209
|
/**
|
|
188
|
-
* Custom 'afterEach' hook to
|
|
210
|
+
* Custom 'afterEach' hook to analyze JavaScript errors and warnings after EACH test execution.
|
|
189
211
|
*/
|
|
190
212
|
afterEach(function () {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
.invoke('getCalls')
|
|
196
|
-
.then(function (calls) { consoleIssues = calls; });
|
|
197
|
-
// Only warnings not in the allowed list should be collected
|
|
198
|
-
cy.get('@warnings')
|
|
199
|
-
.invoke('getCalls')
|
|
200
|
-
.each(function (call) {
|
|
201
|
-
call.args.forEach(function (arg) {
|
|
202
|
-
if (!allowedWarnings.some(function (item) { return arg.includes(item); })) {
|
|
203
|
-
consoleIssues.push(arg);
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
});
|
|
213
|
+
// Skip the hook if the logger is disabled or if the strategy is not failAfterEach
|
|
214
|
+
if (isDisabled() || getStrategy() !== STRATEGY.failAfterEach) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
207
217
|
// Analyze collected errors and warnings
|
|
208
|
-
|
|
209
|
-
if (consoleIssues.length > 0) {
|
|
210
|
-
// Format the error message for each test
|
|
211
|
-
var errorMessage = consoleIssues.map(function (e) { return "- " + e; }).join('\n');
|
|
212
|
-
// Throw an error with the collected issues
|
|
213
|
-
throw new Error('CONSOLE ERRORS and WARNINGS FOUND:\n\n' + errorMessage);
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
cy.log('[JS ERRORS LOGGER] No console errors or warnings found.');
|
|
217
|
-
}
|
|
218
|
-
});
|
|
218
|
+
analyzeIssues();
|
|
219
219
|
});
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Custom hook implementation which fails the test immediately when a JavaScript error or warning is detected.
|
|
223
|
-
*
|
|
224
|
-
* Proc: Allows each test to run, looks for console errors and warnings, and fails the particular test IMMEDIATELLY
|
|
225
|
-
* if any issues are found.
|
|
226
|
-
* Cons: If errors or warnings were found during beforeEach or afterEach hook(s), the rest of spec will be ignored.
|
|
227
|
-
*/
|
|
228
|
-
function attachFailFast() {
|
|
229
|
-
// Double-check in case if functionality was disabled within the test-case code
|
|
230
|
-
// to skip js validations for some particular test and enable it afterward
|
|
231
|
-
if (isDisabled()) {
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
220
|
/**
|
|
235
|
-
* Custom '
|
|
236
|
-
* This hook is executed before the page is loaded, allowing us to capture console messages.
|
|
221
|
+
* Custom 'after' hook to analyze JavaScript errors and warnings after ALL tests execution.
|
|
237
222
|
*/
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
var allowedWarnings = Cypress.env(envVarAllowedWarnings) || [];
|
|
246
|
-
// All errors should be collected
|
|
247
|
-
cy.get('@errors')
|
|
248
|
-
.invoke('getCalls')
|
|
249
|
-
.then(function (calls) { consoleIssues = calls; });
|
|
250
|
-
// Only warnings not in the allowed list should be collected
|
|
251
|
-
cy.get('@warnings')
|
|
252
|
-
.invoke('getCalls')
|
|
253
|
-
.each(function (call) {
|
|
254
|
-
call.args.forEach(function (arg) {
|
|
255
|
-
if (!allowedWarnings.some(function (item) { return arg.includes(item); })) {
|
|
256
|
-
consoleIssues.push(arg);
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
}).then(function () {
|
|
260
|
-
if (consoleIssues.length > 0) {
|
|
261
|
-
// Format the error message for each test
|
|
262
|
-
var errorMessage = consoleIssues.map(function (e) { return "- " + e; }).join('\n');
|
|
263
|
-
// Throw an error with the collected issues
|
|
264
|
-
throw new Error('CONSOLE ERRORS and WARNINGS FOUND:\n' + errorMessage);
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
cy.log('[JS ERRORS LOGGER] No console errors or warnings found.');
|
|
268
|
-
}
|
|
269
|
-
});
|
|
223
|
+
after(function () {
|
|
224
|
+
// Skip the hook if the logger is disabled or if the strategy is not failAfterAll
|
|
225
|
+
if (isDisabled() || getStrategy() !== STRATEGY.failAfterAll) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// Analyze collected errors and warnings
|
|
229
|
+
analyzeIssues();
|
|
270
230
|
});
|
|
271
231
|
}
|
|
272
232
|
/**
|
|
273
233
|
* Exports the jsLogger module with methods to attach hooks, enable/disable logging, and set allowed warnings.
|
|
274
234
|
*/
|
|
275
235
|
exports.jsErrorsLogger = {
|
|
276
|
-
attachHooks: attachHooks,
|
|
277
236
|
setAllowedJsWarnings: setAllowedJsWarnings,
|
|
237
|
+
getAllowedJsWarnings: getAllowedJsWarnings,
|
|
278
238
|
setStrategy: setStrategy,
|
|
239
|
+
getStrategy: getStrategy,
|
|
240
|
+
enable: enable,
|
|
241
|
+
disable: disable,
|
|
279
242
|
STRATEGY: STRATEGY
|
|
280
243
|
};
|
|
@@ -8,8 +8,6 @@ var logout_1 = require("./logout");
|
|
|
8
8
|
var fixture_1 = require("./fixture");
|
|
9
9
|
var repeatUntil_1 = require("./repeatUntil");
|
|
10
10
|
var testStep_1 = require("./testStep");
|
|
11
|
-
// FUNCTIONALITY IS TEMPORARY DISABLED DUE TO UNEXPECTED ISSUES
|
|
12
|
-
// import {jsErrorsLogger} from './jsErrorsLogger';
|
|
13
11
|
var registerSupport = function () {
|
|
14
12
|
Cypress.Commands.add('apolloClient', apollo_1.apolloClient);
|
|
15
13
|
Cypress.Commands.add('apollo', { prevSubject: 'optional' }, apollo_1.apollo);
|
|
@@ -24,11 +22,5 @@ var registerSupport = function () {
|
|
|
24
22
|
Cypress.Commands.add('repeatUntil', repeatUntil_1.repeatUntil);
|
|
25
23
|
Cypress.Commands.overwrite('fixture', fixture_1.fixture);
|
|
26
24
|
Cypress.Commands.add('step', testStep_1.step);
|
|
27
|
-
// Since registerSupport() function is called in each repo from e2e.js,
|
|
28
|
-
// attaching the JavaScript errors logger hooks here ensures that logger is initialized automatically
|
|
29
|
-
// for all tests without needing to call it explicitly in each test file.
|
|
30
|
-
// This is useful for capturing and logging JavaScript errors across all tests.
|
|
31
|
-
// FUNCTIONALITY IS TEMPORARY DISABLED DUE TO UNEXPECTED ISSUES
|
|
32
|
-
// jsErrorsLogger.attachHooks();
|
|
33
25
|
};
|
|
34
26
|
exports.registerSupport = registerSupport;
|
package/dist/utils/Logger.d.ts
CHANGED
|
@@ -13,11 +13,12 @@
|
|
|
13
13
|
* It tells the logger to log only messages with the given level and above.
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
|
-
* Logging levels enumerator
|
|
16
|
+
* Logging levels enumerator
|
|
17
17
|
*/
|
|
18
18
|
declare enum LEVEL {
|
|
19
19
|
DEBUG = 0,
|
|
20
|
-
INFO = 1
|
|
20
|
+
INFO = 1,
|
|
21
|
+
WARNING = 2
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
24
|
* Sets the logging verbosity level for the logger. Messages with a level lower than the set level will not be logged.
|
|
@@ -37,6 +38,12 @@ declare function info(message: string): Cypress.Chainable;
|
|
|
37
38
|
* @returns {Cypress.Chainable} - Cypress chainable object
|
|
38
39
|
*/
|
|
39
40
|
declare function debug(message: string): Cypress.Chainable;
|
|
41
|
+
/**
|
|
42
|
+
* Logs WARNING message
|
|
43
|
+
* @param {string} message - log message
|
|
44
|
+
* @returns {Cypress.Chainable} - Cypress chainable object
|
|
45
|
+
*/
|
|
46
|
+
declare function warning(message: string): Cypress.Chainable;
|
|
40
47
|
/**
|
|
41
48
|
* Logs JSON object with logging level given
|
|
42
49
|
* @param {LEVEL} level - log level (e.g. 'INFO', 'DEBUG')
|
|
@@ -47,6 +54,7 @@ declare function json(level: LEVEL, text: string): Cypress.Chainable;
|
|
|
47
54
|
export declare const Log: {
|
|
48
55
|
info: typeof info;
|
|
49
56
|
debug: typeof debug;
|
|
57
|
+
warning: typeof warning;
|
|
50
58
|
json: typeof json;
|
|
51
59
|
setVerbosity: typeof setVerbosity;
|
|
52
60
|
LEVEL: typeof LEVEL;
|
package/dist/utils/Logger.js
CHANGED
|
@@ -15,16 +15,65 @@
|
|
|
15
15
|
*/
|
|
16
16
|
exports.__esModule = true;
|
|
17
17
|
exports.Log = void 0;
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* ENV variable to store the logging verbosity level
|
|
20
|
+
*/
|
|
19
21
|
var envVarLoggingVerbosity = '__LOG_VERBOSITY__';
|
|
20
22
|
/**
|
|
21
|
-
* Logging levels enumerator
|
|
23
|
+
* Logging levels enumerator
|
|
22
24
|
*/
|
|
23
25
|
var LEVEL;
|
|
24
26
|
(function (LEVEL) {
|
|
25
27
|
LEVEL[LEVEL["DEBUG"] = 0] = "DEBUG";
|
|
26
28
|
LEVEL[LEVEL["INFO"] = 1] = "INFO";
|
|
29
|
+
LEVEL[LEVEL["WARNING"] = 2] = "WARNING";
|
|
27
30
|
})(LEVEL || (LEVEL = {}));
|
|
31
|
+
/**
|
|
32
|
+
* Base colors for each log level
|
|
33
|
+
*/
|
|
34
|
+
var LOGGER_COLORS = [
|
|
35
|
+
{ name: 'DEBUG', color: '#686868' },
|
|
36
|
+
{ name: 'INFO', color: '#10b981' },
|
|
37
|
+
{ name: 'WARNING', color: '#fbbf24' }
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* Unique style ID to identify the logger styles in the document head
|
|
41
|
+
*/
|
|
42
|
+
var LOGGER_STYLE_ID = 'jahia-cypress-ptf-logger-styles';
|
|
43
|
+
/**
|
|
44
|
+
* Helper function to convert hex colors to rgb
|
|
45
|
+
* @param {string} hex - hex color
|
|
46
|
+
* @returns {string} - rgb color in format "r g b"
|
|
47
|
+
* @example hex2rgb("#ffffff") => "255 255 255"
|
|
48
|
+
*/
|
|
49
|
+
function hex2rgb(hex) {
|
|
50
|
+
var r = parseInt(hex.slice(1, 3), 16);
|
|
51
|
+
var g = parseInt(hex.slice(3, 5), 16);
|
|
52
|
+
var b = parseInt(hex.slice(5, 7), 16);
|
|
53
|
+
return r + " " + g + " " + b;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Creates a custom logger styles and attaches them to the document head.
|
|
57
|
+
* Basically - attaches CSS styles to Cypress browser window to style the log messages.
|
|
58
|
+
*/
|
|
59
|
+
function attachLoggerStyles() {
|
|
60
|
+
// Check if style tag with the corresponding attribute exists in the document head to avoid duplicating styles
|
|
61
|
+
if (Cypress.$(window.top.document.head).find("style[data-id=\"" + LOGGER_STYLE_ID + "\"]").length > 0) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Create style element
|
|
65
|
+
var styleSheet = document.createElement('style');
|
|
66
|
+
// Add marker attribute to identify the style tag
|
|
67
|
+
styleSheet.setAttribute('data-id', LOGGER_STYLE_ID);
|
|
68
|
+
// Build styles for each log level
|
|
69
|
+
LOGGER_COLORS.forEach(function (logger) {
|
|
70
|
+
var name = logger.name.toLowerCase();
|
|
71
|
+
var color = hex2rgb(logger.color);
|
|
72
|
+
styleSheet.textContent += "\n .command.command-name-ptf-" + name + " span.command-method {\n margin-right: 0.5rem;\n border-radius: 0.125rem;\n border-width: 1px;\n padding: 0.125rem 0.375rem;\n text-transform: uppercase;\n\n border-color: rgb(" + color + " / 1);\n background-color: rgb(" + color + " / 0.2);\n color: rgb(" + color + " / 1) !important;\n }\n\n .command.command-name-ptf-" + name + " span.command-message {\n color: rgb(" + color + " / 1);\n font-weight: normal;\n }\n\n .command.command-name-ptf-" + name + " span.command-message strong,\n .command.command-name-ptf-" + name + " span.command-message em { \n color: rgb(" + color + " / 1);\n }\n ";
|
|
73
|
+
});
|
|
74
|
+
// Attach styles to the document head
|
|
75
|
+
Cypress.$(window.top.document.head).append(styleSheet);
|
|
76
|
+
}
|
|
28
77
|
/**
|
|
29
78
|
* Return the current logging verbosity level.
|
|
30
79
|
* @returns {LEVEL} - current logging level set in Cypress environment variable `__LOG_VERBOSITY__`
|
|
@@ -58,6 +107,14 @@ function info(message) {
|
|
|
58
107
|
function debug(message) {
|
|
59
108
|
return _send_(exports.Log.LEVEL.DEBUG, message);
|
|
60
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Logs WARNING message
|
|
112
|
+
* @param {string} message - log message
|
|
113
|
+
* @returns {Cypress.Chainable} - Cypress chainable object
|
|
114
|
+
*/
|
|
115
|
+
function warning(message) {
|
|
116
|
+
return _send_(exports.Log.LEVEL.WARNING, message);
|
|
117
|
+
}
|
|
61
118
|
/**
|
|
62
119
|
* Logs JSON object with logging level given
|
|
63
120
|
* @param {LEVEL} level - log level (e.g. 'INFO', 'DEBUG')
|
|
@@ -83,6 +140,8 @@ function _send_(level, message) {
|
|
|
83
140
|
if (!Object.values(exports.Log.LEVEL).includes(level)) {
|
|
84
141
|
throw new Error("Log level \"" + level + "\" is not supported. Supported levels are: " + exports.Log.LEVEL);
|
|
85
142
|
}
|
|
143
|
+
// Attach logger styles to the document head (done only once)
|
|
144
|
+
attachLoggerStyles();
|
|
86
145
|
// Check if the log level is enabled,
|
|
87
146
|
// take into account the log level set in Cypress.env('LOG_LEVEL') and the log level set in the Log.LEVEL variable.
|
|
88
147
|
// If the log level is enabled, send the message to Cypress log.
|
|
@@ -91,14 +150,15 @@ function _send_(level, message) {
|
|
|
91
150
|
// use cy.then() to ensure that the log message is sent in the correct order
|
|
92
151
|
// and use cy.wrap() to return the Cypress chainable object
|
|
93
152
|
return cy.then(function () {
|
|
94
|
-
Cypress.log({
|
|
95
|
-
}).then(cy.wrap);
|
|
153
|
+
Cypress.log({ name: "ptf-" + exports.Log.LEVEL[level].toLowerCase(), displayName: "" + exports.Log.LEVEL[level].toUpperCase(), message: "" + message });
|
|
154
|
+
}).then(function () { return cy.wrap(null, { log: false }); });
|
|
96
155
|
}
|
|
97
156
|
}
|
|
98
157
|
// Export the Log module with methods to log messages and set the logging level
|
|
99
158
|
exports.Log = {
|
|
100
159
|
info: info,
|
|
101
160
|
debug: debug,
|
|
161
|
+
warning: warning,
|
|
102
162
|
json: json,
|
|
103
163
|
setVerbosity: setVerbosity,
|
|
104
164
|
LEVEL: LEVEL
|