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.
Files changed (140) hide show
  1. package/CHANGELOG.md +2950 -0
  2. package/docs/bdd.md +11 -7
  3. package/docs/build/ApiDataFactory.js +2 -1
  4. package/docs/build/Appium.js +25 -23
  5. package/docs/build/Expect.js +422 -0
  6. package/docs/build/Nightmare.js +53 -56
  7. package/docs/build/Playwright.js +166 -103
  8. package/docs/build/Protractor.js +66 -69
  9. package/docs/build/Puppeteer.js +79 -79
  10. package/docs/build/TestCafe.js +56 -55
  11. package/docs/build/WebDriver.js +81 -82
  12. package/docs/changelog.md +388 -1
  13. package/docs/commands.md +12 -0
  14. package/docs/community-helpers.md +8 -4
  15. package/docs/examples.md +8 -2
  16. package/docs/helpers/Appium.md +50 -32
  17. package/docs/helpers/Expect.md +275 -0
  18. package/docs/helpers/Nightmare.md +141 -94
  19. package/docs/helpers/Playwright.md +280 -211
  20. package/docs/helpers/Protractor.md +229 -169
  21. package/docs/helpers/Puppeteer.md +256 -185
  22. package/docs/helpers/TestCafe.md +201 -149
  23. package/docs/helpers/WebDriver.md +252 -178
  24. package/docs/mobile.md +17 -21
  25. package/docs/plugins.md +35 -1
  26. package/docs/webapi/amOnPage.mustache +1 -1
  27. package/docs/webapi/appendField.mustache +1 -1
  28. package/docs/webapi/attachFile.mustache +1 -1
  29. package/docs/webapi/blur.mustache +1 -0
  30. package/docs/webapi/checkOption.mustache +1 -1
  31. package/docs/webapi/clearCookie.mustache +1 -1
  32. package/docs/webapi/clearField.mustache +1 -1
  33. package/docs/webapi/click.mustache +1 -1
  34. package/docs/webapi/clickLink.mustache +1 -1
  35. package/docs/webapi/closeCurrentTab.mustache +1 -1
  36. package/docs/webapi/closeOtherTabs.mustache +1 -1
  37. package/docs/webapi/dontSee.mustache +1 -1
  38. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
  39. package/docs/webapi/dontSeeCookie.mustache +1 -1
  40. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +1 -1
  41. package/docs/webapi/dontSeeElement.mustache +1 -1
  42. package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
  43. package/docs/webapi/dontSeeInCurrentUrl.mustache +1 -1
  44. package/docs/webapi/dontSeeInField.mustache +1 -1
  45. package/docs/webapi/dontSeeInSource.mustache +1 -1
  46. package/docs/webapi/dontSeeInTitle.mustache +1 -1
  47. package/docs/webapi/doubleClick.mustache +1 -1
  48. package/docs/webapi/downloadFile.mustache +1 -1
  49. package/docs/webapi/dragAndDrop.mustache +1 -1
  50. package/docs/webapi/dragSlider.mustache +1 -1
  51. package/docs/webapi/executeAsyncScript.mustache +0 -2
  52. package/docs/webapi/executeScript.mustache +0 -2
  53. package/docs/webapi/fillField.mustache +1 -1
  54. package/docs/webapi/focus.mustache +1 -0
  55. package/docs/webapi/forceClick.mustache +1 -1
  56. package/docs/webapi/forceRightClick.mustache +1 -1
  57. package/docs/webapi/grabCookie.mustache +1 -1
  58. package/docs/webapi/grabDataFromPerformanceTiming.mustache +1 -1
  59. package/docs/webapi/moveCursorTo.mustache +1 -1
  60. package/docs/webapi/openNewTab.mustache +1 -1
  61. package/docs/webapi/pressKey.mustache +1 -1
  62. package/docs/webapi/pressKeyDown.mustache +1 -1
  63. package/docs/webapi/pressKeyUp.mustache +1 -1
  64. package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
  65. package/docs/webapi/refreshPage.mustache +1 -1
  66. package/docs/webapi/resizeWindow.mustache +1 -1
  67. package/docs/webapi/rightClick.mustache +1 -1
  68. package/docs/webapi/saveElementScreenshot.mustache +1 -1
  69. package/docs/webapi/saveScreenshot.mustache +1 -1
  70. package/docs/webapi/say.mustache +1 -1
  71. package/docs/webapi/scrollIntoView.mustache +1 -1
  72. package/docs/webapi/scrollPageToBottom.mustache +1 -1
  73. package/docs/webapi/scrollPageToTop.mustache +1 -1
  74. package/docs/webapi/scrollTo.mustache +1 -1
  75. package/docs/webapi/see.mustache +1 -1
  76. package/docs/webapi/seeAttributesOnElements.mustache +1 -1
  77. package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
  78. package/docs/webapi/seeCookie.mustache +1 -1
  79. package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
  80. package/docs/webapi/seeCurrentUrlEquals.mustache +1 -1
  81. package/docs/webapi/seeElement.mustache +1 -1
  82. package/docs/webapi/seeElementInDOM.mustache +1 -1
  83. package/docs/webapi/seeInCurrentUrl.mustache +1 -1
  84. package/docs/webapi/seeInField.mustache +1 -1
  85. package/docs/webapi/seeInPopup.mustache +1 -1
  86. package/docs/webapi/seeInSource.mustache +1 -1
  87. package/docs/webapi/seeInTitle.mustache +1 -1
  88. package/docs/webapi/seeNumberOfElements.mustache +1 -1
  89. package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
  90. package/docs/webapi/seeTextEquals.mustache +1 -1
  91. package/docs/webapi/seeTitleEquals.mustache +1 -1
  92. package/docs/webapi/selectOption.mustache +1 -1
  93. package/docs/webapi/setCookie.mustache +1 -1
  94. package/docs/webapi/setGeoLocation.mustache +1 -1
  95. package/docs/webapi/switchTo.mustache +1 -1
  96. package/docs/webapi/switchToNextTab.mustache +1 -1
  97. package/docs/webapi/switchToPreviousTab.mustache +1 -1
  98. package/docs/webapi/type.mustache +1 -1
  99. package/docs/webapi/uncheckOption.mustache +1 -1
  100. package/docs/webapi/wait.mustache +1 -1
  101. package/docs/webapi/waitForClickable.mustache +1 -1
  102. package/docs/webapi/waitForDetached.mustache +1 -1
  103. package/docs/webapi/waitForElement.mustache +1 -1
  104. package/docs/webapi/waitForEnabled.mustache +1 -1
  105. package/docs/webapi/waitForFunction.mustache +1 -1
  106. package/docs/webapi/waitForInvisible.mustache +1 -1
  107. package/docs/webapi/waitForText.mustache +1 -1
  108. package/docs/webapi/waitForValue.mustache +1 -1
  109. package/docs/webapi/waitForVisible.mustache +1 -1
  110. package/docs/webapi/waitInUrl.mustache +1 -1
  111. package/docs/webapi/waitNumberOfVisibleElements.mustache +1 -1
  112. package/docs/webapi/waitToHide.mustache +1 -1
  113. package/docs/webapi/waitUrlEquals.mustache +1 -1
  114. package/lib/ai.js +12 -3
  115. package/lib/cli.js +3 -1
  116. package/lib/command/dryRun.js +2 -1
  117. package/lib/helper/ApiDataFactory.js +2 -1
  118. package/lib/helper/Appium.js +7 -5
  119. package/lib/helper/Expect.js +422 -0
  120. package/lib/helper/Playwright.js +91 -32
  121. package/lib/helper/Puppeteer.js +2 -2
  122. package/lib/html.js +3 -3
  123. package/lib/interfaces/gherkin.js +21 -2
  124. package/lib/output.js +1 -1
  125. package/lib/pause.js +6 -3
  126. package/lib/plugin/autoLogin.js +35 -3
  127. package/lib/plugin/heal.js +40 -7
  128. package/lib/recorder.js +12 -5
  129. package/package.json +15 -8
  130. package/translations/de-DE.js +5 -0
  131. package/translations/fr-FR.js +1 -0
  132. package/translations/it-IT.js +1 -0
  133. package/translations/ja-JP.js +5 -0
  134. package/translations/pl-PL.js +5 -0
  135. package/translations/pt-BR.js +1 -0
  136. package/translations/ru-RU.js +1 -0
  137. package/translations/zh-CN.js +5 -0
  138. package/translations/zh-TW.js +5 -0
  139. package/typings/promiseBasedTypes.d.ts +904 -862
  140. 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.slice(0, 15).padEnd(15)).join(' | ');
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
- const aiAssistant = new AiAssistant();
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;
@@ -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 in user.
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}`);
@@ -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 = new 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.before, () => {
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
- if (!aiAssistant.isEnabled) throw err;
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
- aiAssistant.setHtmlContext(html);
133
+ healTries++;
134
+ await aiAssistant.setHtmlContext(html);
115
135
  await tryToHeal(step, err);
116
- recorder.session.restore();
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
- debug(`${currentQueue()}Queued | catch with error handler`);
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
- log(`${currentQueue()}Error | ${err}`);
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.6",
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": "4.0.0",
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": "26.1.0",
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.38.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.1",
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.1.6",
151
+ "typescript": "5.2.2",
145
152
  "wdio-docker-service": "1.5.0",
146
153
  "webdriverio": "8.3.8",
147
- "xml2js": "0.6.0",
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
+ }
@@ -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',
@@ -3,6 +3,7 @@ module.exports = {
3
3
  contexts: {
4
4
  Feature: 'Fonctionnalité',
5
5
  Scenario: 'Scénario',
6
+ ScenarioOutline: 'Plan du scénario',
6
7
  Before: 'Avant',
7
8
  After: 'Après',
8
9
  BeforeSuite: 'AvantLaSuite',
@@ -3,6 +3,7 @@ module.exports = {
3
3
  contexts: {
4
4
  Feature: 'Caratteristica',
5
5
  Scenario: 'lo_scenario',
6
+ ScenarioOutline: 'Schema dello scenario',
6
7
  Before: 'Prima',
7
8
  After: 'Dopo',
8
9
  BeforeSuite: 'Prima_della_suite',
@@ -1,5 +1,10 @@
1
1
  module.exports = {
2
2
  I: '私は',
3
+ contexts: {
4
+ Feature: 'フィーチャ',
5
+ Scenario: 'シナリオ',
6
+ ScenarioOutline: 'シナリオアウトライン',
7
+ },
3
8
  actions: {
4
9
  amOutsideAngularApp: 'Angularの外に出る',
5
10
  amInsideAngularApp: 'Angularの中に入る',
@@ -1,5 +1,10 @@
1
1
  module.exports = {
2
2
  I: 'Ja',
3
+ contexts: {
4
+ Feature: 'Funkcja',
5
+ Scenario: 'Scenariusz',
6
+ ScenarioOutline: 'Szablon scenariusza',
7
+ },
3
8
  actions: {
4
9
  amOutsideAngularApp: 'jestem_poza_aplikacją_angular',
5
10
  amInsideAngularApp: 'jestem_w_aplikacji_angular',
@@ -3,6 +3,7 @@ module.exports = {
3
3
  contexts: {
4
4
  Feature: 'Funcionalidade',
5
5
  Scenario: 'Cenário',
6
+ ScenarioOutline: 'Esquema do Cenário',
6
7
  Before: 'Antes',
7
8
  After: 'Depois',
8
9
  BeforeSuite: 'AntesDaSuite',
@@ -3,6 +3,7 @@ module.exports = {
3
3
  contexts: {
4
4
  Feature: 'Цель',
5
5
  Scenario: 'Сценарий',
6
+ ScenarioOutline: 'Структура сценария',
6
7
  Before: 'Начало',
7
8
  After: 'Конец',
8
9
  BeforeSuite: 'Перед_всем',
@@ -1,5 +1,10 @@
1
1
  module.exports = {
2
2
  I: '我',
3
+ contexts: {
4
+ Feature: '功能',
5
+ Scenario: '场景',
6
+ ScenarioOutline: '场景大纲',
7
+ },
3
8
  actions: {
4
9
  amOutsideAngularApp: '在Angular应用外',
5
10
  amInsideAngularApp: '在Angular应用内',
@@ -1,5 +1,10 @@
1
1
  module.exports = {
2
2
  I: '我',
3
+ contexts: {
4
+ Feature: '功能',
5
+ Scenario: '場景',
6
+ ScenarioOutline: '場景大綱',
7
+ },
3
8
  actions: {
4
9
  amOutsideAngularApp: '在Angular應用外',
5
10
  amInsideAngularApp: '在Angular應用內',