codeceptjs 3.5.6 → 3.5.7-beta.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/CHANGELOG.md +2950 -0
- package/docs/bdd.md +11 -7
- package/docs/build/ApiDataFactory.js +2 -1
- package/docs/build/Appium.js +25 -23
- package/docs/build/Expect.js +422 -0
- package/docs/build/Nightmare.js +53 -56
- package/docs/build/Playwright.js +166 -103
- package/docs/build/Protractor.js +66 -69
- package/docs/build/Puppeteer.js +79 -79
- package/docs/build/TestCafe.js +56 -55
- package/docs/build/WebDriver.js +81 -82
- package/docs/changelog.md +388 -1
- package/docs/commands.md +12 -0
- package/docs/community-helpers.md +8 -4
- package/docs/examples.md +8 -2
- package/docs/helpers/Appium.md +50 -32
- package/docs/helpers/Expect.md +275 -0
- package/docs/helpers/Nightmare.md +141 -94
- package/docs/helpers/Playwright.md +280 -211
- package/docs/helpers/Protractor.md +229 -169
- package/docs/helpers/Puppeteer.md +256 -185
- package/docs/helpers/TestCafe.md +201 -149
- package/docs/helpers/WebDriver.md +252 -178
- package/docs/mobile.md +17 -21
- package/docs/plugins.md +35 -1
- package/docs/webapi/amOnPage.mustache +1 -1
- package/docs/webapi/appendField.mustache +1 -1
- package/docs/webapi/attachFile.mustache +1 -1
- package/docs/webapi/blur.mustache +1 -0
- package/docs/webapi/checkOption.mustache +1 -1
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/clearField.mustache +1 -1
- package/docs/webapi/click.mustache +1 -1
- package/docs/webapi/clickLink.mustache +1 -1
- package/docs/webapi/closeCurrentTab.mustache +1 -1
- package/docs/webapi/closeOtherTabs.mustache +1 -1
- package/docs/webapi/dontSee.mustache +1 -1
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/dontSeeCookie.mustache +1 -1
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +1 -1
- package/docs/webapi/dontSeeElement.mustache +1 -1
- package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
- package/docs/webapi/dontSeeInCurrentUrl.mustache +1 -1
- package/docs/webapi/dontSeeInField.mustache +1 -1
- package/docs/webapi/dontSeeInSource.mustache +1 -1
- package/docs/webapi/dontSeeInTitle.mustache +1 -1
- package/docs/webapi/doubleClick.mustache +1 -1
- package/docs/webapi/downloadFile.mustache +1 -1
- package/docs/webapi/dragAndDrop.mustache +1 -1
- package/docs/webapi/dragSlider.mustache +1 -1
- package/docs/webapi/executeAsyncScript.mustache +0 -2
- package/docs/webapi/executeScript.mustache +0 -2
- package/docs/webapi/fillField.mustache +1 -1
- package/docs/webapi/focus.mustache +1 -0
- package/docs/webapi/forceClick.mustache +1 -1
- package/docs/webapi/forceRightClick.mustache +1 -1
- package/docs/webapi/grabCookie.mustache +1 -1
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +1 -1
- package/docs/webapi/moveCursorTo.mustache +1 -1
- package/docs/webapi/openNewTab.mustache +1 -1
- package/docs/webapi/pressKey.mustache +1 -1
- package/docs/webapi/pressKeyDown.mustache +1 -1
- package/docs/webapi/pressKeyUp.mustache +1 -1
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
- package/docs/webapi/refreshPage.mustache +1 -1
- package/docs/webapi/resizeWindow.mustache +1 -1
- package/docs/webapi/rightClick.mustache +1 -1
- package/docs/webapi/saveElementScreenshot.mustache +1 -1
- package/docs/webapi/saveScreenshot.mustache +1 -1
- package/docs/webapi/say.mustache +1 -1
- package/docs/webapi/scrollIntoView.mustache +1 -1
- package/docs/webapi/scrollPageToBottom.mustache +1 -1
- package/docs/webapi/scrollPageToTop.mustache +1 -1
- package/docs/webapi/scrollTo.mustache +1 -1
- package/docs/webapi/see.mustache +1 -1
- package/docs/webapi/seeAttributesOnElements.mustache +1 -1
- package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/seeCookie.mustache +1 -1
- package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
- package/docs/webapi/seeCurrentUrlEquals.mustache +1 -1
- package/docs/webapi/seeElement.mustache +1 -1
- package/docs/webapi/seeElementInDOM.mustache +1 -1
- package/docs/webapi/seeInCurrentUrl.mustache +1 -1
- package/docs/webapi/seeInField.mustache +1 -1
- package/docs/webapi/seeInPopup.mustache +1 -1
- package/docs/webapi/seeInSource.mustache +1 -1
- package/docs/webapi/seeInTitle.mustache +1 -1
- package/docs/webapi/seeNumberOfElements.mustache +1 -1
- package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/seeTextEquals.mustache +1 -1
- package/docs/webapi/seeTitleEquals.mustache +1 -1
- package/docs/webapi/selectOption.mustache +1 -1
- package/docs/webapi/setCookie.mustache +1 -1
- package/docs/webapi/setGeoLocation.mustache +1 -1
- package/docs/webapi/switchTo.mustache +1 -1
- package/docs/webapi/switchToNextTab.mustache +1 -1
- package/docs/webapi/switchToPreviousTab.mustache +1 -1
- package/docs/webapi/type.mustache +1 -1
- package/docs/webapi/uncheckOption.mustache +1 -1
- package/docs/webapi/wait.mustache +1 -1
- package/docs/webapi/waitForClickable.mustache +1 -1
- package/docs/webapi/waitForDetached.mustache +1 -1
- package/docs/webapi/waitForElement.mustache +1 -1
- package/docs/webapi/waitForEnabled.mustache +1 -1
- package/docs/webapi/waitForFunction.mustache +1 -1
- package/docs/webapi/waitForInvisible.mustache +1 -1
- package/docs/webapi/waitForText.mustache +1 -1
- package/docs/webapi/waitForValue.mustache +1 -1
- package/docs/webapi/waitForVisible.mustache +1 -1
- package/docs/webapi/waitInUrl.mustache +1 -1
- package/docs/webapi/waitNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/waitToHide.mustache +1 -1
- package/docs/webapi/waitUrlEquals.mustache +1 -1
- package/lib/ai.js +12 -3
- package/lib/cli.js +3 -1
- package/lib/command/dryRun.js +2 -1
- package/lib/helper/ApiDataFactory.js +2 -1
- package/lib/helper/Appium.js +7 -5
- package/lib/helper/Expect.js +422 -0
- package/lib/helper/Playwright.js +91 -32
- package/lib/helper/Puppeteer.js +2 -2
- package/lib/html.js +3 -3
- package/lib/interfaces/gherkin.js +21 -2
- package/lib/output.js +1 -1
- package/lib/pause.js +6 -3
- package/lib/plugin/autoLogin.js +35 -3
- package/lib/plugin/heal.js +40 -7
- package/lib/recorder.js +12 -5
- package/package.json +15 -8
- package/translations/de-DE.js +5 -0
- package/translations/fr-FR.js +1 -0
- package/translations/it-IT.js +1 -0
- package/translations/ja-JP.js +5 -0
- package/translations/pl-PL.js +5 -0
- package/translations/pt-BR.js +1 -0
- package/translations/ru-RU.js +1 -0
- package/translations/zh-CN.js +5 -0
- package/translations/zh-TW.js +5 -0
- package/typings/promiseBasedTypes.d.ts +904 -862
- package/typings/types.d.ts +904 -845
|
@@ -18,6 +18,11 @@ parser.stopAtFirstError = false;
|
|
|
18
18
|
|
|
19
19
|
module.exports = (text, file) => {
|
|
20
20
|
const ast = parser.parse(text);
|
|
21
|
+
let currentLanguage;
|
|
22
|
+
|
|
23
|
+
if (ast.feature) {
|
|
24
|
+
currentLanguage = getTranslation(ast.feature.language);
|
|
25
|
+
}
|
|
21
26
|
|
|
22
27
|
if (!ast.feature) {
|
|
23
28
|
throw new Error(`No 'Features' available in Gherkin '${file}' provided!`);
|
|
@@ -96,7 +101,7 @@ module.exports = (text, file) => {
|
|
|
96
101
|
suite.beforeEach('Before', scenario.injected(async () => runSteps(child.background.steps), suite, 'before'));
|
|
97
102
|
continue;
|
|
98
103
|
}
|
|
99
|
-
if (child.scenario && child.scenario.keyword === 'Scenario Outline') {
|
|
104
|
+
if (child.scenario && (currentLanguage ? child.scenario.keyword === currentLanguage.contexts.ScenarioOutline : child.scenario.keyword === 'Scenario Outline')) {
|
|
100
105
|
for (const examples of child.scenario.examples) {
|
|
101
106
|
const fields = examples.tableHeader.cells.map(c => c.value);
|
|
102
107
|
for (const example of examples.tableBody) {
|
|
@@ -141,7 +146,7 @@ function transformTable(table) {
|
|
|
141
146
|
let str = '';
|
|
142
147
|
for (const id in table.rows) {
|
|
143
148
|
const cells = table.rows[id].cells;
|
|
144
|
-
str += cells.map(c => c.value).map(c => c.
|
|
149
|
+
str += cells.map(c => c.value).map(c => c.padEnd(15)).join(' | ');
|
|
145
150
|
str += '\n';
|
|
146
151
|
}
|
|
147
152
|
return str;
|
|
@@ -162,3 +167,17 @@ function addExampleInTable(exampleSteps, placeholders) {
|
|
|
162
167
|
}
|
|
163
168
|
return steps;
|
|
164
169
|
}
|
|
170
|
+
|
|
171
|
+
function getTranslation(language) {
|
|
172
|
+
const translations = Object.keys(require('../../translations'));
|
|
173
|
+
|
|
174
|
+
for (const availableTranslation of translations) {
|
|
175
|
+
if (!language) {
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (availableTranslation.includes(language)) {
|
|
180
|
+
return require('../../translations')[availableTranslation];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
package/lib/output.js
CHANGED
|
@@ -106,7 +106,7 @@ module.exports = {
|
|
|
106
106
|
if (!step) return;
|
|
107
107
|
// Avoid to print non-gherkin steps, when gherkin is running for --steps mode
|
|
108
108
|
if (outputLevel === 1) {
|
|
109
|
-
if (step.hasBDDAncestor()) {
|
|
109
|
+
if (typeof step === 'object' && step.hasBDDAncestor()) {
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
112
112
|
}
|
package/lib/pause.js
CHANGED
|
@@ -18,8 +18,7 @@ let nextStep;
|
|
|
18
18
|
let finish;
|
|
19
19
|
let next;
|
|
20
20
|
let registeredVariables = {};
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
let aiAssistant;
|
|
23
22
|
/**
|
|
24
23
|
* Pauses test execution and starts interactive shell
|
|
25
24
|
* @param {Object<string, *>} [passedObject]
|
|
@@ -45,6 +44,8 @@ function pauseSession(passedObject = {}) {
|
|
|
45
44
|
let vars = Object.keys(registeredVariables).join(', ');
|
|
46
45
|
if (vars) vars = `(vars: ${vars})`;
|
|
47
46
|
|
|
47
|
+
aiAssistant = AiAssistant.getInstance();
|
|
48
|
+
|
|
48
49
|
output.print(colors.yellow(' Interactive shell started'));
|
|
49
50
|
output.print(colors.yellow(' Use JavaScript syntax to try steps in action'));
|
|
50
51
|
output.print(colors.yellow(` - Press ${colors.bold('ENTER')} to run the next step`));
|
|
@@ -102,7 +103,9 @@ async function parseInput(cmd) {
|
|
|
102
103
|
let isAiCommand = false;
|
|
103
104
|
let $res;
|
|
104
105
|
try {
|
|
106
|
+
// eslint-disable-next-line
|
|
105
107
|
const locate = global.locate; // enable locate in this context
|
|
108
|
+
// eslint-disable-next-line
|
|
106
109
|
const I = container.support('I');
|
|
107
110
|
if (cmd.trim().startsWith('=>')) {
|
|
108
111
|
isCustomCommand = true;
|
|
@@ -115,7 +118,7 @@ async function parseInput(cmd) {
|
|
|
115
118
|
executeCommand = executeCommand.then(async () => {
|
|
116
119
|
try {
|
|
117
120
|
const html = await res;
|
|
118
|
-
aiAssistant.setHtmlContext(html);
|
|
121
|
+
await aiAssistant.setHtmlContext(html);
|
|
119
122
|
} catch (err) {
|
|
120
123
|
output.print(output.styles.error(' ERROR '), 'Can\'t get HTML context', err.stack);
|
|
121
124
|
return;
|
package/lib/plugin/autoLogin.js
CHANGED
|
@@ -61,7 +61,7 @@ const defaultConfig = {
|
|
|
61
61
|
* #### How It Works
|
|
62
62
|
*
|
|
63
63
|
* 1. `restore` method is executed. It should open a page and set credentials.
|
|
64
|
-
* 2. `check` method is executed. It should reload a page (so cookies are applied) and check that this page belongs to logged
|
|
64
|
+
* 2. `check` method is executed. It should reload a page (so cookies are applied) and check that this page belongs to logged-in user. When you pass the second args `session`, you could perform the validation using passed session.
|
|
65
65
|
* 3. If `restore` and `check` were not successful, `login` is executed
|
|
66
66
|
* 4. `login` should fill in login form
|
|
67
67
|
* 5. After successful login, `fetch` is executed to save cookies into memory or file.
|
|
@@ -212,6 +212,38 @@ const defaultConfig = {
|
|
|
212
212
|
* })
|
|
213
213
|
* ```
|
|
214
214
|
*
|
|
215
|
+
* #### Tips: Using session to validate user
|
|
216
|
+
*
|
|
217
|
+
* Instead of asserting on page elements for the current user in `check`, you can use the `session` you saved in `fetch`
|
|
218
|
+
*
|
|
219
|
+
* ```js
|
|
220
|
+
* autoLogin: {
|
|
221
|
+
* enabled: true,
|
|
222
|
+
* saveToFile: true,
|
|
223
|
+
* inject: 'login',
|
|
224
|
+
* users: {
|
|
225
|
+
* admin: {
|
|
226
|
+
* login: async (I) => { // If you use async function in the autoLogin plugin
|
|
227
|
+
* const phrase = await I.grabTextFrom('#phrase')
|
|
228
|
+
* I.fillField('username', 'admin'),
|
|
229
|
+
* I.fillField('password', 'password')
|
|
230
|
+
* I.fillField('phrase', phrase)
|
|
231
|
+
* },
|
|
232
|
+
* check: (I, session) => {
|
|
233
|
+
* // Throwing an error in `check` will make CodeceptJS perform the login step for the user
|
|
234
|
+
* if (session.profile.email !== the.email.you.expect@some-mail.com) {
|
|
235
|
+
* throw new Error ('Wrong user signed in');
|
|
236
|
+
* }
|
|
237
|
+
* },
|
|
238
|
+
* }
|
|
239
|
+
* }
|
|
240
|
+
* }
|
|
241
|
+
* ```
|
|
242
|
+
*
|
|
243
|
+
* ```js
|
|
244
|
+
* Scenario('login', async ( {I, login} ) => {
|
|
245
|
+
* await login('admin') // you should use `await`
|
|
246
|
+
* })
|
|
215
247
|
*
|
|
216
248
|
*
|
|
217
249
|
*/
|
|
@@ -264,10 +296,10 @@ module.exports = function (config) {
|
|
|
264
296
|
recorder.session.start('check login');
|
|
265
297
|
if (shouldAwait) {
|
|
266
298
|
await userSession.restore(I, cookies);
|
|
267
|
-
await userSession.check(I);
|
|
299
|
+
await userSession.check(I, cookies);
|
|
268
300
|
} else {
|
|
269
301
|
userSession.restore(I, cookies);
|
|
270
|
-
userSession.check(I);
|
|
302
|
+
userSession.check(I, cookies);
|
|
271
303
|
}
|
|
272
304
|
recorder.session.catch((err) => {
|
|
273
305
|
debug(`Failed auto login for ${name} due to ${err}`);
|
package/lib/plugin/heal.js
CHANGED
|
@@ -8,6 +8,7 @@ const output = require('../output');
|
|
|
8
8
|
const supportedHelpers = require('./standardActingHelpers');
|
|
9
9
|
|
|
10
10
|
const defaultConfig = {
|
|
11
|
+
healTries: 1,
|
|
11
12
|
healLimit: 2,
|
|
12
13
|
healSteps: [
|
|
13
14
|
'click',
|
|
@@ -54,11 +55,14 @@ const defaultConfig = {
|
|
|
54
55
|
*
|
|
55
56
|
*/
|
|
56
57
|
module.exports = function (config = {}) {
|
|
57
|
-
const aiAssistant =
|
|
58
|
+
const aiAssistant = AiAssistant.getInstance();
|
|
58
59
|
|
|
59
60
|
let currentTest = null;
|
|
60
61
|
let currentStep = null;
|
|
61
62
|
let healedSteps = 0;
|
|
63
|
+
let caughtError;
|
|
64
|
+
let healTries = 0;
|
|
65
|
+
let isHealing = false;
|
|
62
66
|
|
|
63
67
|
const healSuggestions = [];
|
|
64
68
|
|
|
@@ -67,20 +71,35 @@ module.exports = function (config = {}) {
|
|
|
67
71
|
event.dispatcher.on(event.test.before, (test) => {
|
|
68
72
|
currentTest = test;
|
|
69
73
|
healedSteps = 0;
|
|
74
|
+
caughtError = null;
|
|
70
75
|
});
|
|
71
76
|
|
|
72
77
|
event.dispatcher.on(event.step.started, step => currentStep = step);
|
|
73
78
|
|
|
74
|
-
event.dispatcher.on(event.step.
|
|
79
|
+
event.dispatcher.on(event.step.after, (step) => {
|
|
80
|
+
if (isHealing) return;
|
|
75
81
|
const store = require('../store');
|
|
76
82
|
if (store.debugMode) return;
|
|
77
|
-
|
|
78
83
|
recorder.catchWithoutStop(async (err) => {
|
|
79
|
-
|
|
84
|
+
isHealing = true;
|
|
85
|
+
if (caughtError === err) throw err; // avoid double handling
|
|
86
|
+
caughtError = err;
|
|
87
|
+
if (!aiAssistant.isEnabled) {
|
|
88
|
+
output.print(colors.yellow('Heal plugin can\'t operate, AI assistant is disabled. Please set OPENAI_API_KEY env variable to enable it.'));
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
80
91
|
if (!currentStep) throw err;
|
|
81
92
|
if (!config.healSteps.includes(currentStep.name)) throw err;
|
|
82
93
|
const test = currentTest;
|
|
83
94
|
|
|
95
|
+
if (healTries >= config.healTries) {
|
|
96
|
+
output.print(colors.bold.red(`Healing failed for ${config.healTries} time(s)`));
|
|
97
|
+
output.print('AI couldn\'t identify the correct solution');
|
|
98
|
+
output.print('Probably the entire flow has changed and the test should be updated');
|
|
99
|
+
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
|
|
84
103
|
if (healedSteps >= config.healLimit) {
|
|
85
104
|
output.print(colors.bold.red(`Can't heal more than ${config.healLimit} step(s) in a test`));
|
|
86
105
|
output.print('Entire flow can be broken, please check it manually');
|
|
@@ -111,9 +130,17 @@ module.exports = function (config = {}) {
|
|
|
111
130
|
|
|
112
131
|
if (!html) throw err;
|
|
113
132
|
|
|
114
|
-
|
|
133
|
+
healTries++;
|
|
134
|
+
await aiAssistant.setHtmlContext(html);
|
|
115
135
|
await tryToHeal(step, err);
|
|
116
|
-
|
|
136
|
+
|
|
137
|
+
recorder.add('close healing session', () => {
|
|
138
|
+
recorder.session.restore('heal');
|
|
139
|
+
recorder.ignoreErr(err);
|
|
140
|
+
});
|
|
141
|
+
await recorder.promise();
|
|
142
|
+
|
|
143
|
+
isHealing = false;
|
|
117
144
|
});
|
|
118
145
|
});
|
|
119
146
|
|
|
@@ -155,6 +182,9 @@ module.exports = function (config = {}) {
|
|
|
155
182
|
for (const codeSnippet of codeSnippets) {
|
|
156
183
|
try {
|
|
157
184
|
debug('Executing', codeSnippet);
|
|
185
|
+
recorder.catch((e) => {
|
|
186
|
+
console.log(e);
|
|
187
|
+
});
|
|
158
188
|
await eval(codeSnippet); // eslint-disable-line
|
|
159
189
|
|
|
160
190
|
healSuggestions.push({
|
|
@@ -163,14 +193,17 @@ module.exports = function (config = {}) {
|
|
|
163
193
|
snippet: codeSnippet,
|
|
164
194
|
});
|
|
165
195
|
|
|
166
|
-
output.print(colors.bold.green(' Code healed successfully'));
|
|
196
|
+
recorder.add('healed', () => output.print(colors.bold.green(' Code healed successfully')));
|
|
167
197
|
healedSteps++;
|
|
168
198
|
return;
|
|
169
199
|
} catch (err) {
|
|
170
200
|
debug('Failed to execute code', err);
|
|
201
|
+
recorder.ignoreErr(err); // healing ded not help
|
|
202
|
+
// recorder.catch(() => output.print(colors.bold.red(' Failed healing code')));
|
|
171
203
|
}
|
|
172
204
|
}
|
|
173
205
|
|
|
174
206
|
output.debug(`Couldn't heal the code for ${failedStep.toCode()}`);
|
|
175
207
|
}
|
|
208
|
+
return recorder.promise();
|
|
176
209
|
};
|
package/lib/recorder.js
CHANGED
|
@@ -11,6 +11,7 @@ let errFn;
|
|
|
11
11
|
let queueId = 0;
|
|
12
12
|
let sessionId = null;
|
|
13
13
|
let asyncErr = null;
|
|
14
|
+
let ignoredErrs = [];
|
|
14
15
|
|
|
15
16
|
let tasks = [];
|
|
16
17
|
let oldPromises = [];
|
|
@@ -93,6 +94,7 @@ module.exports = {
|
|
|
93
94
|
promise = Promise.resolve();
|
|
94
95
|
oldPromises = [];
|
|
95
96
|
tasks = [];
|
|
97
|
+
ignoredErrs = [];
|
|
96
98
|
this.session.running = false;
|
|
97
99
|
// reset this retries makes the retryFailedStep plugin won't work if there is Before/BeforeSuit block due to retries is undefined on Scenario
|
|
98
100
|
// this.retries = [];
|
|
@@ -226,9 +228,10 @@ module.exports = {
|
|
|
226
228
|
* @inner
|
|
227
229
|
*/
|
|
228
230
|
catch(customErrFn) {
|
|
229
|
-
|
|
231
|
+
const fnDescription = customErrFn?.toString()?.replace(/\s{2,}/g, ' ').replace(/\n/g, ' ')?.slice(0, 50);
|
|
232
|
+
debug(`${currentQueue()}Queued | catch with error handler ${fnDescription || ''}`);
|
|
230
233
|
return promise = promise.catch((err) => {
|
|
231
|
-
log(`${currentQueue()}Error | ${err}
|
|
234
|
+
log(`${currentQueue()}Error | ${err} ${fnDescription}...`);
|
|
232
235
|
if (!(err instanceof Error)) { // strange things may happen
|
|
233
236
|
err = new Error(`[Wrapped Error] ${printObjectProperties(err)}`); // we should be prepared for them
|
|
234
237
|
}
|
|
@@ -247,15 +250,15 @@ module.exports = {
|
|
|
247
250
|
* @inner
|
|
248
251
|
*/
|
|
249
252
|
catchWithoutStop(customErrFn) {
|
|
253
|
+
const fnDescription = customErrFn?.toString()?.replace(/\s{2,}/g, ' ').replace(/\n/g, ' ')?.slice(0, 50);
|
|
250
254
|
return promise = promise.catch((err) => {
|
|
251
|
-
|
|
255
|
+
if (ignoredErrs.includes(err)) return; // already caught
|
|
256
|
+
log(`${currentQueue()}Error (Non-Terminated) | ${err} | ${fnDescription || ''}...`);
|
|
252
257
|
if (!(err instanceof Error)) { // strange things may happen
|
|
253
258
|
err = new Error(`[Wrapped Error] ${JSON.stringify(err)}`); // we should be prepared for them
|
|
254
259
|
}
|
|
255
260
|
if (customErrFn) {
|
|
256
261
|
return customErrFn(err);
|
|
257
|
-
} if (errFn) {
|
|
258
|
-
return errFn(err);
|
|
259
262
|
}
|
|
260
263
|
});
|
|
261
264
|
},
|
|
@@ -274,6 +277,10 @@ module.exports = {
|
|
|
274
277
|
});
|
|
275
278
|
},
|
|
276
279
|
|
|
280
|
+
ignoreErr(err) {
|
|
281
|
+
ignoredErrs.push(err);
|
|
282
|
+
},
|
|
283
|
+
|
|
277
284
|
/**
|
|
278
285
|
* @param {*} err
|
|
279
286
|
* @inner
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.7-beta.1",
|
|
4
4
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acceptance",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"test:unit:webbapi:puppeteer": "mocha test/helper/Puppeteer_test.js",
|
|
52
52
|
"test:unit:webbapi:webDriver": "mocha test/helper/WebDriver_test.js",
|
|
53
53
|
"test:unit:webbapi:testCafe": "mocha test/helper/TestCafe_test.js",
|
|
54
|
+
"test:unit:expect": "mocha test/helper/Expect_test.js",
|
|
54
55
|
"def": "./runok.js def",
|
|
55
56
|
"dev:graphql": "node test/data/graphql/index.js",
|
|
56
57
|
"publish:site": "./runok.js publish:site",
|
|
@@ -70,6 +71,11 @@
|
|
|
70
71
|
"axios": "1.3.3",
|
|
71
72
|
"chai": "4.3.8",
|
|
72
73
|
"chai-deep-match": "1.2.1",
|
|
74
|
+
"chai-exclude": "^2.1.0",
|
|
75
|
+
"chai-json-schema": "^1.5.1",
|
|
76
|
+
"chai-json-schema-ajv": "^5.2.4",
|
|
77
|
+
"chai-match-pattern": "^1.3.0",
|
|
78
|
+
"chai-string": "^1.5.0",
|
|
73
79
|
"chalk": "4.1.2",
|
|
74
80
|
"commander": "11.0.0",
|
|
75
81
|
"cross-spawn": "7.0.3",
|
|
@@ -80,7 +86,7 @@
|
|
|
80
86
|
"fn-args": "4.0.0",
|
|
81
87
|
"fs-extra": "8.1.0",
|
|
82
88
|
"glob": "6.0.1",
|
|
83
|
-
"html-minifier": "
|
|
89
|
+
"html-minifier-terser": "^7.2.0",
|
|
84
90
|
"inquirer": "6.5.2",
|
|
85
91
|
"joi": "17.6.0",
|
|
86
92
|
"js-beautify": "1.14.9",
|
|
@@ -104,6 +110,7 @@
|
|
|
104
110
|
"@faker-js/faker": "7.6.0",
|
|
105
111
|
"@pollyjs/adapter-puppeteer": "6.0.6",
|
|
106
112
|
"@pollyjs/core": "5.1.0",
|
|
113
|
+
"@types/chai": "^4.3.7",
|
|
107
114
|
"@types/inquirer": "9.0.3",
|
|
108
115
|
"@types/node": "20.4.4",
|
|
109
116
|
"@wdio/sauce-service": "8.3.8",
|
|
@@ -115,7 +122,7 @@
|
|
|
115
122
|
"contributor-faces": "1.0.3",
|
|
116
123
|
"documentation": "12.3.0",
|
|
117
124
|
"dtslint": "4.1.6",
|
|
118
|
-
"electron": "
|
|
125
|
+
"electron": "27.0.2",
|
|
119
126
|
"eslint": "8.50.0",
|
|
120
127
|
"eslint-config-airbnb-base": "15.0.0",
|
|
121
128
|
"eslint-plugin-import": "2.25.4",
|
|
@@ -128,23 +135,23 @@
|
|
|
128
135
|
"jsdoc": "3.6.10",
|
|
129
136
|
"jsdoc-typeof-plugin": "1.0.0",
|
|
130
137
|
"json-server": "0.10.1",
|
|
131
|
-
"playwright": "1.
|
|
138
|
+
"playwright": "1.39.0",
|
|
132
139
|
"puppeteer": "21.1.1",
|
|
133
140
|
"qrcode-terminal": "0.12.0",
|
|
134
141
|
"rosie": "2.1.0",
|
|
135
142
|
"runok": "0.9.3",
|
|
136
143
|
"sinon": "15.2.0",
|
|
137
144
|
"sinon-chai": "3.7.0",
|
|
138
|
-
"testcafe": "3.0
|
|
145
|
+
"testcafe": "3.3.0",
|
|
139
146
|
"ts-morph": "19.0.0",
|
|
140
147
|
"ts-node": "10.9.1",
|
|
141
148
|
"tsd-jsdoc": "2.5.0",
|
|
142
149
|
"typedoc": "0.24.8",
|
|
143
150
|
"typedoc-plugin-markdown": "3.13.4",
|
|
144
|
-
"typescript": "5.
|
|
151
|
+
"typescript": "5.2.2",
|
|
145
152
|
"wdio-docker-service": "1.5.0",
|
|
146
153
|
"webdriverio": "8.3.8",
|
|
147
|
-
"xml2js": "0.6.
|
|
154
|
+
"xml2js": "0.6.2",
|
|
148
155
|
"xmldom": "0.6.0",
|
|
149
156
|
"xpath": "0.0.33"
|
|
150
157
|
},
|
|
@@ -153,4 +160,4 @@
|
|
|
153
160
|
"npm": ">=5.6.0"
|
|
154
161
|
},
|
|
155
162
|
"es6": true
|
|
156
|
-
}
|
|
163
|
+
}
|
package/translations/de-DE.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
I: 'Ich',
|
|
3
|
+
contexts: {
|
|
4
|
+
Feature: 'Funktionalität',
|
|
5
|
+
Scenario: 'Szenario',
|
|
6
|
+
ScenarioOutline: 'Szenariogrundriss',
|
|
7
|
+
},
|
|
3
8
|
actions: {
|
|
4
9
|
amOutsideAngularApp: 'befinde_mich_außerhalb_der_angular_app',
|
|
5
10
|
amInsideAngularApp: 'bedinde_mich_innerhalb_der_angular_app',
|
package/translations/fr-FR.js
CHANGED
package/translations/it-IT.js
CHANGED
package/translations/ja-JP.js
CHANGED
package/translations/pl-PL.js
CHANGED
package/translations/pt-BR.js
CHANGED
package/translations/ru-RU.js
CHANGED
package/translations/zh-CN.js
CHANGED