codeceptjs 4.0.0-beta.2 → 4.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/bin/codecept.js +84 -81
  2. package/lib/actor.js +13 -13
  3. package/lib/ai.js +10 -13
  4. package/lib/assert/empty.js +20 -21
  5. package/lib/assert/equal.js +37 -39
  6. package/lib/assert/error.js +14 -14
  7. package/lib/assert/include.js +46 -47
  8. package/lib/assert/throws.js +13 -11
  9. package/lib/assert/truth.js +19 -22
  10. package/lib/assert.js +4 -2
  11. package/lib/cli.js +57 -49
  12. package/lib/codecept.js +142 -155
  13. package/lib/colorUtils.js +3 -3
  14. package/lib/command/configMigrate.js +58 -52
  15. package/lib/command/definitions.js +88 -89
  16. package/lib/command/dryRun.js +71 -68
  17. package/lib/command/generate.js +197 -188
  18. package/lib/command/gherkin/init.js +27 -16
  19. package/lib/command/gherkin/snippets.js +20 -20
  20. package/lib/command/gherkin/steps.js +8 -8
  21. package/lib/command/info.js +40 -38
  22. package/lib/command/init.js +290 -288
  23. package/lib/command/interactive.js +32 -32
  24. package/lib/command/list.js +26 -26
  25. package/lib/command/run-multiple/chunk.js +5 -5
  26. package/lib/command/run-multiple/collection.js +3 -3
  27. package/lib/command/run-multiple/run.js +6 -2
  28. package/lib/command/run-multiple.js +113 -93
  29. package/lib/command/run-rerun.js +20 -25
  30. package/lib/command/run-workers.js +64 -66
  31. package/lib/command/run.js +26 -29
  32. package/lib/command/utils.js +80 -65
  33. package/lib/command/workers/runTests.js +10 -10
  34. package/lib/config.js +10 -9
  35. package/lib/container.js +40 -48
  36. package/lib/data/context.js +60 -59
  37. package/lib/data/dataScenarioConfig.js +47 -47
  38. package/lib/data/dataTableArgument.js +29 -29
  39. package/lib/data/table.js +26 -20
  40. package/lib/event.js +163 -167
  41. package/lib/heal.js +13 -17
  42. package/lib/helper/AI.js +130 -41
  43. package/lib/helper/ApiDataFactory.js +73 -69
  44. package/lib/helper/Appium.js +413 -382
  45. package/lib/helper/ExpectHelper.js +40 -48
  46. package/lib/helper/FileSystem.js +80 -79
  47. package/lib/helper/GraphQL.js +44 -43
  48. package/lib/helper/GraphQLDataFactory.js +50 -50
  49. package/lib/helper/JSONResponse.js +65 -62
  50. package/lib/helper/Mochawesome.js +28 -28
  51. package/lib/helper/MockServer.js +12 -14
  52. package/lib/helper/Nightmare.js +662 -566
  53. package/lib/helper/Playwright.js +1361 -1216
  54. package/lib/helper/Protractor.js +663 -627
  55. package/lib/helper/Puppeteer.js +1231 -1128
  56. package/lib/helper/REST.js +159 -68
  57. package/lib/helper/SoftExpectHelper.js +2 -2
  58. package/lib/helper/TestCafe.js +490 -484
  59. package/lib/helper/WebDriver.js +1297 -1156
  60. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  61. package/lib/helper/errors/ConnectionRefused.js +1 -1
  62. package/lib/helper/errors/ElementAssertion.js +2 -2
  63. package/lib/helper/errors/ElementNotFound.js +2 -2
  64. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
  65. package/lib/helper/extras/Console.js +1 -1
  66. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  67. package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
  68. package/lib/helper/extras/PlaywrightRestartOpts.js +21 -18
  69. package/lib/helper/extras/Popup.js +1 -1
  70. package/lib/helper/extras/React.js +3 -3
  71. package/lib/helper/network/actions.js +14 -7
  72. package/lib/helper/network/utils.js +3 -2
  73. package/lib/helper/scripts/blurElement.js +1 -1
  74. package/lib/helper/scripts/focusElement.js +1 -1
  75. package/lib/helper/scripts/highlightElement.js +1 -1
  76. package/lib/helper/scripts/isElementClickable.js +1 -1
  77. package/lib/helper/testcafe/testControllerHolder.js +1 -1
  78. package/lib/helper/testcafe/testcafe-utils.js +6 -7
  79. package/lib/helper.js +1 -3
  80. package/lib/history.js +6 -5
  81. package/lib/hooks.js +6 -6
  82. package/lib/html.js +7 -7
  83. package/lib/index.js +25 -41
  84. package/lib/interfaces/bdd.js +47 -64
  85. package/lib/interfaces/featureConfig.js +19 -19
  86. package/lib/interfaces/gherkin.js +124 -118
  87. package/lib/interfaces/scenarioConfig.js +29 -29
  88. package/lib/listener/artifacts.js +9 -9
  89. package/lib/listener/config.js +24 -24
  90. package/lib/listener/exit.js +12 -12
  91. package/lib/listener/helpers.js +42 -42
  92. package/lib/listener/mocha.js +11 -11
  93. package/lib/listener/retry.js +32 -30
  94. package/lib/listener/steps.js +50 -53
  95. package/lib/listener/timeout.js +54 -54
  96. package/lib/locator.js +6 -10
  97. package/lib/mochaFactory.js +18 -15
  98. package/lib/output.js +6 -10
  99. package/lib/parser.js +15 -12
  100. package/lib/pause.js +40 -33
  101. package/lib/plugin/allure.js +15 -15
  102. package/lib/plugin/autoDelay.js +29 -37
  103. package/lib/plugin/autoLogin.js +70 -65
  104. package/lib/plugin/commentStep.js +18 -18
  105. package/lib/plugin/coverage.js +115 -67
  106. package/lib/plugin/customLocator.js +21 -20
  107. package/lib/plugin/debugErrors.js +24 -24
  108. package/lib/plugin/eachElement.js +38 -38
  109. package/lib/plugin/fakerTransform.js +6 -6
  110. package/lib/plugin/heal.js +67 -108
  111. package/lib/plugin/pauseOnFail.js +11 -11
  112. package/lib/plugin/retryFailedStep.js +32 -39
  113. package/lib/plugin/retryTo.js +46 -40
  114. package/lib/plugin/screenshotOnFail.js +109 -87
  115. package/lib/plugin/selenoid.js +131 -118
  116. package/lib/plugin/standardActingHelpers.js +2 -8
  117. package/lib/plugin/stepByStepReport.js +110 -91
  118. package/lib/plugin/stepTimeout.js +24 -23
  119. package/lib/plugin/subtitles.js +34 -35
  120. package/lib/plugin/tryTo.js +40 -30
  121. package/lib/plugin/wdio.js +78 -75
  122. package/lib/recorder.js +14 -17
  123. package/lib/rerun.js +11 -10
  124. package/lib/scenario.js +25 -23
  125. package/lib/secret.js +4 -2
  126. package/lib/session.js +10 -10
  127. package/lib/step.js +12 -9
  128. package/lib/store.js +2 -3
  129. package/lib/transform.js +1 -1
  130. package/lib/translation.js +7 -8
  131. package/lib/ui.js +12 -14
  132. package/lib/utils.js +70 -72
  133. package/lib/within.js +10 -10
  134. package/lib/workerStorage.js +27 -25
  135. package/lib/workers.js +29 -32
  136. package/package.json +56 -57
  137. package/translations/de-DE.js +1 -1
  138. package/translations/fr-FR.js +1 -1
  139. package/translations/index.js +9 -13
  140. package/translations/it-IT.js +1 -1
  141. package/translations/ja-JP.js +1 -1
  142. package/translations/pl-PL.js +1 -1
  143. package/translations/pt-BR.js +1 -1
  144. package/translations/ru-RU.js +1 -1
  145. package/translations/zh-CN.js +1 -1
  146. package/translations/zh-TW.js +1 -1
  147. package/typings/index.d.ts +415 -65
  148. package/typings/promiseBasedTypes.d.ts +32 -0
  149. package/typings/types.d.ts +32 -0
  150. package/lib/dirname.js +0 -5
  151. package/lib/helper/Expect.js +0 -425
@@ -1,19 +1,14 @@
1
- import debug from 'debug';
2
- import colors from 'chalk';
3
- import Container from '../container.js';
4
- import AiAssistant from '../ai.js';
5
- import recorder from '../recorder.js';
6
- import * as event from '../event.js';
7
- import * as output from '../output.js';
8
- import supportedHelpers from './standardActingHelpers.js';
9
-
10
- debug('codeceptjs:heal');
11
- const heal = require('../heal');
12
- const store = require('../store');
1
+ const debug = require('debug')('codeceptjs:heal')
2
+ const colors = require('chalk')
3
+ const recorder = require('../recorder')
4
+ const event = require('../event')
5
+ const output = require('../output')
6
+ const heal = require('../heal')
7
+ const store = require('../store')
13
8
 
14
9
  const defaultConfig = {
15
10
  healLimit: 2,
16
- };
11
+ }
17
12
 
18
13
  /**
19
14
  * Self-healing tests with AI.
@@ -33,130 +28,94 @@ const defaultConfig = {
33
28
  * * `healLimit` - how many steps can be healed in a single test (default: 2)
34
29
  *
35
30
  */
36
-
37
- export default function (config = {}) {
38
- if (store.store.debugMode && !process.env.DEBUG) {
31
+ module.exports = function (config = {}) {
32
+ if (store.debugMode && !process.env.DEBUG) {
39
33
  event.dispatcher.on(event.test.failed, () => {
40
- output.output.plugin('heal', 'Healing is disabled in --debug mode, use DEBUG="codeceptjs:heal" to enable it in debug mode');
41
- });
42
- return;
34
+ output.plugin(
35
+ 'heal',
36
+ 'Healing is disabled in --debug mode, use DEBUG="codeceptjs:heal" to enable it in debug mode',
37
+ )
38
+ })
39
+ return
43
40
  }
44
41
 
45
- let currentTest = null;
46
- let currentStep = null;
47
- let healedSteps = 0;
48
- let caughtError;
49
- let healTries = 0;
50
- let isHealing = false;
42
+ let currentTest = null
43
+ let currentStep = null
44
+ let healedSteps = 0
45
+ let caughtError
46
+ let healTries = 0
47
+ let isHealing = false
51
48
 
52
- config = Object.assign(defaultConfig, config);
49
+ config = Object.assign(defaultConfig, config)
53
50
 
54
51
  event.dispatcher.on(event.test.before, (test) => {
55
- currentTest = test;
56
- healedSteps = 0;
57
- caughtError = null;
58
- });
52
+ currentTest = test
53
+ healedSteps = 0
54
+ caughtError = null
55
+ })
59
56
 
60
- event.dispatcher.on(event.step.started, step => currentStep = step);
57
+ event.dispatcher.on(event.step.started, (step) => (currentStep = step))
61
58
 
62
59
  event.dispatcher.on(event.step.after, (step) => {
63
- if (isHealing) return;
64
- if (store.store.debugMode) return;
65
- if (healTries >= config.healLimit) return; // out of limit
60
+ if (isHealing) return
61
+ if (healTries >= config.healLimit) return // out of limit
66
62
 
67
- if (!heal.hasCorrespondingRecipes(step)) return;
63
+ if (!heal.hasCorrespondingRecipes(step)) return
68
64
 
69
65
  recorder.catchWithoutStop(async (err) => {
70
- isHealing = true;
71
- if (caughtError === err) throw err; // avoid double handling
72
- caughtError = err;
66
+ isHealing = true
67
+ if (caughtError === err) throw err // avoid double handling
68
+ caughtError = err
73
69
 
74
- const test = currentTest;
70
+ const test = currentTest
75
71
 
76
- recorder.session.start('heal');
72
+ recorder.session.start('heal')
77
73
 
78
- debug('Self-healing started', step.toCode());
74
+ debug('Self-healing started', step.toCode())
79
75
 
80
- await heal.healStep(step, err, { test });
76
+ await heal.healStep(step, err, { test })
81
77
 
82
- healTries++;
78
+ healTries++
83
79
 
84
80
  recorder.add('close healing session', () => {
85
- recorder.reset();
86
- recorder.session.restore('heal');
87
- recorder.ignoreErr(err);
88
- });
89
- await recorder.promise();
81
+ recorder.reset()
82
+ recorder.session.restore('heal')
83
+ recorder.ignoreErr(err)
84
+ })
85
+ await recorder.promise()
90
86
 
91
- isHealing = false;
92
- });
93
- });
87
+ isHealing = false
88
+ })
89
+ })
94
90
 
95
91
  event.dispatcher.on(event.all.result, () => {
96
- if (!heal.fixes?.length) return;
92
+ if (!heal.fixes?.length) return
97
93
 
98
- const { print } = output;
94
+ const { print } = output
99
95
 
100
- print('');
101
- print('===================');
102
- print(colors.bold.green('Self-Healing Report:'));
96
+ print('')
97
+ print('===================')
98
+ print(colors.bold.green('Self-Healing Report:'))
103
99
 
104
- print(`${colors.bold(heal.fixes.length)} ${heal.fixes.length === 1 ? 'step was' : 'steps were'} healed`);
100
+ print(`${colors.bold(heal.fixes.length)} ${heal.fixes.length === 1 ? 'step was' : 'steps were'} healed`)
105
101
 
106
- const suggestions = heal.fixes.filter(fix => fix.recipe && heal.recipes[fix.recipe].suggest);
102
+ const suggestions = heal.fixes.filter((fix) => fix.recipe && heal.recipes[fix.recipe].suggest)
107
103
 
108
- if (!suggestions.length) return;
104
+ if (!suggestions.length) return
109
105
 
110
- let i = 1;
111
- print('');
112
- print('Suggested changes:');
113
- print('');
106
+ let i = 1
107
+ print('')
108
+ print('Suggested changes:')
109
+ print('')
114
110
 
115
111
  for (const suggestion of suggestions) {
116
- print(`${i}. To fix ${colors.bold.magenta(suggestion.test?.title)}`);
117
- print(' Replace the failed code:', colors.gray(`(suggested by ${colors.bold(suggestion.recipe)})`));
118
- print(colors.red(`- ${suggestion.step.toCode()}`));
119
- print(colors.green(`+ ${suggestion.snippet}`));
120
- print(suggestion.step.line());
121
- print('');
122
- i++;
123
- }
124
- });
125
-
126
- async function tryToHeal(failedStep, err) {
127
- output.output.debug(`Running OpenAI to heal ${failedStep.toCode()} step`);
128
-
129
- const codeSnippets = await AiAssistant.healFailedStep(failedStep, err, currentTest);
130
-
131
- output.output.debug(`Received ${codeSnippets.length} suggestions from OpenAI`);
132
- const I = Container.support('I'); // eslint-disable-line
133
-
134
- for (const codeSnippet of codeSnippets) {
135
- try {
136
- debug('Executing', codeSnippet);
137
- recorder.catch((e) => {
138
- console.log(e);
139
- });
140
- await eval(codeSnippet); // eslint-disable-line
141
-
142
- let healSuggestions = [];
143
- healSuggestions.push({
144
- test: currentTest,
145
- step: failedStep,
146
- snippet: codeSnippet,
147
- });
148
-
149
- recorder.add('healed', () => output.print(colors.bold.green(' Code healed successfully')));
150
- healedSteps++;
151
- return;
152
- } catch (err) {
153
- debug('Failed to execute code', err);
154
- recorder.ignoreErr(err); // healing ded not help
155
- // recorder.catch(() => output.print(colors.bold.red(' Failed healing code')));
156
- }
112
+ print(`${i}. To fix ${colors.bold.magenta(suggestion.test?.title)}`)
113
+ print(' Replace the failed code:', colors.gray(`(suggested by ${colors.bold(suggestion.recipe)})`))
114
+ print(colors.red(`- ${suggestion.step.toCode()}`))
115
+ print(colors.green(`+ ${suggestion.snippet}`))
116
+ print(suggestion.step.line())
117
+ print('')
118
+ i++
157
119
  }
158
-
159
- output.output.debug(`Couldn't heal the code for ${failedStep.toCode()}`);
160
- }
161
- return recorder.promise();
120
+ })
162
121
  }
@@ -1,5 +1,5 @@
1
- import * as event from '../event.js';
2
- import pause from '../pause';
1
+ const event = require('../event')
2
+ const pause = require('../pause')
3
3
 
4
4
  /**
5
5
  * Automatically launches [interactive pause](/basics/#pause) when a test fails.
@@ -21,18 +21,18 @@ import pause from '../pause';
21
21
  * ```
22
22
  *
23
23
  */
24
- export default () => {
25
- let failed = false;
24
+ module.exports = () => {
25
+ let failed = false
26
26
 
27
27
  event.dispatcher.on(event.test.started, () => {
28
- failed = false;
29
- });
28
+ failed = false
29
+ })
30
30
 
31
31
  event.dispatcher.on(event.step.failed, () => {
32
- failed = true;
33
- });
32
+ failed = true
33
+ })
34
34
 
35
35
  event.dispatcher.on(event.test.after, () => {
36
- if (failed) pause();
37
- });
38
- };
36
+ if (failed) pause()
37
+ })
38
+ }
@@ -1,22 +1,14 @@
1
- import * as event from '../event.js';
2
- import recorder from '../recorder.js';
3
- import * as output from '../output.js';
4
-
5
- import { store } from '../store.js';
1
+ const event = require('../event')
2
+ const recorder = require('../recorder')
3
+ const container = require('../container')
4
+ const { log } = require('../output')
6
5
 
7
6
  const defaultConfig = {
8
7
  retries: 3,
9
- defaultIgnoredSteps: [
10
- 'amOnPage',
11
- 'wait*',
12
- 'send*',
13
- 'execute*',
14
- 'run*',
15
- 'have*',
16
- ],
8
+ defaultIgnoredSteps: ['amOnPage', 'wait*', 'send*', 'execute*', 'run*', 'have*'],
17
9
  factor: 1.5,
18
10
  ignoredSteps: [],
19
- };
11
+ }
20
12
 
21
13
  /**
22
14
  * Retries each failed step in a test.
@@ -84,45 +76,46 @@ const defaultConfig = {
84
76
  * ```
85
77
  *
86
78
  */
87
- export default (config) => {
88
- config = Object.assign(defaultConfig, config);
89
- config.ignoredSteps = config.ignoredSteps.concat(config.defaultIgnoredSteps);
90
- const customWhen = config.when;
79
+ module.exports = (config) => {
80
+ config = Object.assign(defaultConfig, config)
81
+ config.ignoredSteps = config.ignoredSteps.concat(config.defaultIgnoredSteps)
82
+ const customWhen = config.when
91
83
 
92
- let enableRetry = false;
84
+ let enableRetry = false
93
85
 
94
86
  const when = (err) => {
95
- if (!enableRetry) return;
96
- if (store.debugMode) return false;
97
- if (customWhen) return customWhen(err);
98
- return true;
99
- };
100
- config.when = when;
87
+ if (!enableRetry) return
88
+ const store = require('../store')
89
+ if (store.debugMode) return false
90
+ if (customWhen) return customWhen(err)
91
+ return true
92
+ }
93
+ config.when = when
101
94
 
102
95
  event.dispatcher.on(event.step.started, (step) => {
103
96
  if (process.env.TRY_TO === 'true') {
104
- output.output.log('Info: RetryFailedStep plugin is disabled inside tryTo block');
105
- return;
97
+ log('Info: RetryFailedStep plugin is disabled inside tryTo block')
98
+ return
106
99
  }
107
100
 
108
101
  // if a step is ignored - return
109
102
  for (const ignored of config.ignoredSteps) {
110
- if (step.name === ignored) return;
103
+ if (step.name === ignored) return
111
104
  if (ignored instanceof RegExp) {
112
- if (step.name.match(ignored)) return;
113
- } else if (ignored.indexOf('*') && step.name.startsWith(ignored.slice(0, -1))) return;
105
+ if (step.name.match(ignored)) return
106
+ } else if (ignored.indexOf('*') && step.name.startsWith(ignored.slice(0, -1))) return
114
107
  }
115
- enableRetry = true; // enable retry for a step
116
- });
108
+ enableRetry = true // enable retry for a step
109
+ })
117
110
 
118
111
  event.dispatcher.on(event.step.finished, () => {
119
- enableRetry = false;
120
- });
112
+ enableRetry = false
113
+ })
121
114
 
122
115
  event.dispatcher.on(event.test.before, (test) => {
123
- if (test && test.disableRetryFailedStep) return; // disable retry when a test is not active
116
+ if (test && test.disableRetryFailedStep) return // disable retry when a test is not active
124
117
  // this env var is used to set the retries inside _before() block of helpers
125
- process.env.FAILED_STEP_RETRIES = config.retries;
126
- recorder.retry(config);
127
- });
128
- };
118
+ process.env.FAILED_STEP_RETRIES = config.retries
119
+ recorder.retry(config)
120
+ })
121
+ }
@@ -1,10 +1,10 @@
1
- import recorder from '../recorder.js';
2
- import * as output from '../output.js';
1
+ const recorder = require('../recorder')
2
+ const { debug } = require('../output')
3
3
 
4
4
  const defaultConfig = {
5
5
  registerGlobal: true,
6
6
  pollInterval: 200,
7
- };
7
+ }
8
8
 
9
9
  /**
10
10
  *
@@ -72,50 +72,56 @@ const defaultConfig = {
72
72
  * const retryTo = codeceptjs.container.plugins('retryTo');
73
73
  * ```
74
74
  *
75
- */
76
- export default function (config) {
77
- config = Object.assign(defaultConfig, config);
78
-
79
- if (config.registerGlobal) {
80
- // @ts-ignore
81
- global.retryTo = retryTo;
82
- }
83
- return retryTo;
84
-
85
- function retryTo(callback, maxTries, pollInterval = undefined) {
86
- let tries = 1;
87
- if (!pollInterval) pollInterval = config.pollInterval;
75
+ */
76
+ module.exports = function (config) {
77
+ config = Object.assign(defaultConfig, config)
78
+ function retryTo(callback, maxTries, pollInterval = config.pollInterval) {
79
+ return new Promise((done, reject) => {
80
+ let tries = 1
88
81
 
89
- let err = null;
82
+ function handleRetryException(err) {
83
+ recorder.throw(err)
84
+ reject(err)
85
+ }
90
86
 
91
- return new Promise((done) => {
92
87
  const tryBlock = async () => {
93
- recorder.session.start(`retryTo ${tries}`);
94
- await callback(tries);
88
+ tries++
89
+ recorder.session.start(`retryTo ${tries}`)
90
+ try {
91
+ await callback(tries)
92
+ } catch (err) {
93
+ handleRetryException(err)
94
+ }
95
+
96
+ // Call done if no errors
95
97
  recorder.add(() => {
96
- recorder.session.restore(`retryTo ${tries}`);
97
- done(null);
98
- });
99
- recorder.session.catch((e) => {
100
- err = e;
101
- recorder.session.restore(`retryTo ${tries}`);
102
- tries++;
103
- if (tries <= maxTries) {
104
- output.output.debug(`Error ${err}... Retrying`);
105
- err = null;
98
+ recorder.session.restore(`retryTo ${tries}`)
99
+ done(null)
100
+ })
106
101
 
107
- recorder.add(`retryTo ${tries}`, () => setTimeout(tryBlock, pollInterval));
102
+ // Catch errors and retry
103
+ recorder.session.catch((err) => {
104
+ recorder.session.restore(`retryTo ${tries}`)
105
+ if (tries <= maxTries) {
106
+ debug(`Error ${err}... Retrying`)
107
+ recorder.add(`retryTo ${tries}`, () => setTimeout(tryBlock, pollInterval))
108
108
  } else {
109
- done(null);
109
+ // if maxTries reached
110
+ handleRetryException(err)
110
111
  }
111
- });
112
- };
112
+ })
113
+ }
114
+
115
+ recorder.add('retryTo', tryBlock).catch((err) => {
116
+ console.error('An error occurred:', err)
117
+ done(null)
118
+ })
119
+ })
120
+ }
113
121
 
114
- recorder.add('retryTo', async () => {
115
- tryBlock();
116
- });
117
- }).then(() => {
118
- if (err) recorder.throw(err);
119
- });
122
+ if (config.registerGlobal) {
123
+ global.retryTo = retryTo
120
124
  }
125
+
126
+ return retryTo
121
127
  }