codeceptjs 4.0.0-beta.3 → 4.0.0-beta.5

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 (155) hide show
  1. package/README.md +134 -119
  2. package/bin/codecept.js +12 -2
  3. package/bin/test-server.js +53 -0
  4. package/docs/webapi/clearCookie.mustache +1 -1
  5. package/lib/actor.js +66 -102
  6. package/lib/ai.js +130 -121
  7. package/lib/assert/empty.js +3 -5
  8. package/lib/assert/equal.js +4 -7
  9. package/lib/assert/include.js +4 -6
  10. package/lib/assert/throws.js +2 -4
  11. package/lib/assert/truth.js +2 -2
  12. package/lib/codecept.js +141 -86
  13. package/lib/command/check.js +201 -0
  14. package/lib/command/configMigrate.js +2 -4
  15. package/lib/command/definitions.js +8 -26
  16. package/lib/command/dryRun.js +30 -35
  17. package/lib/command/generate.js +10 -14
  18. package/lib/command/gherkin/snippets.js +75 -73
  19. package/lib/command/gherkin/steps.js +1 -1
  20. package/lib/command/info.js +42 -8
  21. package/lib/command/init.js +13 -12
  22. package/lib/command/interactive.js +10 -2
  23. package/lib/command/list.js +1 -1
  24. package/lib/command/run-multiple/chunk.js +48 -45
  25. package/lib/command/run-multiple.js +12 -35
  26. package/lib/command/run-workers.js +21 -58
  27. package/lib/command/utils.js +5 -6
  28. package/lib/command/workers/runTests.js +263 -222
  29. package/lib/container.js +386 -238
  30. package/lib/data/context.js +10 -13
  31. package/lib/data/dataScenarioConfig.js +8 -8
  32. package/lib/data/dataTableArgument.js +6 -6
  33. package/lib/data/table.js +5 -11
  34. package/lib/effects.js +223 -0
  35. package/lib/element/WebElement.js +327 -0
  36. package/lib/els.js +158 -0
  37. package/lib/event.js +21 -17
  38. package/lib/heal.js +88 -80
  39. package/lib/helper/AI.js +2 -1
  40. package/lib/helper/ApiDataFactory.js +4 -7
  41. package/lib/helper/Appium.js +50 -57
  42. package/lib/helper/FileSystem.js +3 -3
  43. package/lib/helper/GraphQLDataFactory.js +4 -4
  44. package/lib/helper/JSONResponse.js +75 -37
  45. package/lib/helper/Mochawesome.js +31 -9
  46. package/lib/helper/Nightmare.js +37 -58
  47. package/lib/helper/Playwright.js +267 -272
  48. package/lib/helper/Protractor.js +56 -87
  49. package/lib/helper/Puppeteer.js +247 -264
  50. package/lib/helper/REST.js +29 -17
  51. package/lib/helper/TestCafe.js +22 -47
  52. package/lib/helper/WebDriver.js +157 -368
  53. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  54. package/lib/helper/extras/Popup.js +22 -22
  55. package/lib/helper/network/utils.js +1 -1
  56. package/lib/helper/testcafe/testcafe-utils.js +27 -28
  57. package/lib/listener/emptyRun.js +55 -0
  58. package/lib/listener/exit.js +7 -10
  59. package/lib/listener/{retry.js → globalRetry.js} +5 -5
  60. package/lib/listener/globalTimeout.js +165 -0
  61. package/lib/listener/helpers.js +15 -15
  62. package/lib/listener/mocha.js +1 -1
  63. package/lib/listener/result.js +12 -0
  64. package/lib/listener/retryEnhancer.js +85 -0
  65. package/lib/listener/steps.js +32 -18
  66. package/lib/listener/store.js +20 -0
  67. package/lib/locator.js +1 -1
  68. package/lib/mocha/asyncWrapper.js +231 -0
  69. package/lib/{interfaces → mocha}/bdd.js +3 -3
  70. package/lib/mocha/cli.js +308 -0
  71. package/lib/mocha/factory.js +104 -0
  72. package/lib/{interfaces → mocha}/featureConfig.js +32 -12
  73. package/lib/{interfaces → mocha}/gherkin.js +26 -28
  74. package/lib/mocha/hooks.js +112 -0
  75. package/lib/mocha/index.js +12 -0
  76. package/lib/mocha/inject.js +29 -0
  77. package/lib/{interfaces → mocha}/scenarioConfig.js +31 -7
  78. package/lib/mocha/suite.js +82 -0
  79. package/lib/mocha/test.js +181 -0
  80. package/lib/mocha/types.d.ts +42 -0
  81. package/lib/mocha/ui.js +232 -0
  82. package/lib/output.js +93 -65
  83. package/lib/pause.js +160 -138
  84. package/lib/plugin/analyze.js +396 -0
  85. package/lib/plugin/auth.js +435 -0
  86. package/lib/plugin/autoDelay.js +8 -8
  87. package/lib/plugin/autoLogin.js +3 -338
  88. package/lib/plugin/commentStep.js +6 -1
  89. package/lib/plugin/coverage.js +10 -22
  90. package/lib/plugin/customLocator.js +3 -3
  91. package/lib/plugin/customReporter.js +52 -0
  92. package/lib/plugin/eachElement.js +1 -1
  93. package/lib/plugin/fakerTransform.js +1 -1
  94. package/lib/plugin/heal.js +36 -9
  95. package/lib/plugin/htmlReporter.js +1947 -0
  96. package/lib/plugin/pageInfo.js +140 -0
  97. package/lib/plugin/retryFailedStep.js +17 -18
  98. package/lib/plugin/retryTo.js +2 -113
  99. package/lib/plugin/screenshotOnFail.js +17 -58
  100. package/lib/plugin/selenoid.js +15 -35
  101. package/lib/plugin/standardActingHelpers.js +4 -1
  102. package/lib/plugin/stepByStepReport.js +56 -17
  103. package/lib/plugin/stepTimeout.js +5 -12
  104. package/lib/plugin/subtitles.js +4 -4
  105. package/lib/plugin/tryTo.js +3 -102
  106. package/lib/plugin/wdio.js +8 -10
  107. package/lib/recorder.js +155 -124
  108. package/lib/rerun.js +43 -42
  109. package/lib/result.js +161 -0
  110. package/lib/secret.js +1 -2
  111. package/lib/step/base.js +239 -0
  112. package/lib/step/comment.js +10 -0
  113. package/lib/step/config.js +50 -0
  114. package/lib/step/func.js +46 -0
  115. package/lib/step/helper.js +50 -0
  116. package/lib/step/meta.js +99 -0
  117. package/lib/step/record.js +74 -0
  118. package/lib/step/retry.js +11 -0
  119. package/lib/step/section.js +55 -0
  120. package/lib/step.js +21 -332
  121. package/lib/steps.js +50 -0
  122. package/lib/store.js +37 -5
  123. package/lib/template/heal.js +2 -11
  124. package/lib/test-server.js +323 -0
  125. package/lib/timeout.js +66 -0
  126. package/lib/utils.js +351 -218
  127. package/lib/within.js +75 -55
  128. package/lib/workerStorage.js +2 -1
  129. package/lib/workers.js +386 -277
  130. package/package.json +81 -75
  131. package/translations/de-DE.js +5 -3
  132. package/translations/fr-FR.js +5 -4
  133. package/translations/index.js +1 -0
  134. package/translations/it-IT.js +4 -3
  135. package/translations/ja-JP.js +4 -3
  136. package/translations/nl-NL.js +76 -0
  137. package/translations/pl-PL.js +4 -3
  138. package/translations/pt-BR.js +4 -3
  139. package/translations/ru-RU.js +4 -3
  140. package/translations/utils.js +9 -0
  141. package/translations/zh-CN.js +4 -3
  142. package/translations/zh-TW.js +4 -3
  143. package/typings/index.d.ts +197 -187
  144. package/typings/promiseBasedTypes.d.ts +53 -903
  145. package/typings/types.d.ts +372 -1042
  146. package/lib/cli.js +0 -257
  147. package/lib/helper/ExpectHelper.js +0 -391
  148. package/lib/helper/MockServer.js +0 -221
  149. package/lib/helper/SoftExpectHelper.js +0 -381
  150. package/lib/listener/artifacts.js +0 -19
  151. package/lib/listener/timeout.js +0 -109
  152. package/lib/mochaFactory.js +0 -113
  153. package/lib/plugin/debugErrors.js +0 -67
  154. package/lib/scenario.js +0 -224
  155. package/lib/ui.js +0 -236
@@ -0,0 +1,74 @@
1
+ const event = require('../event')
2
+ const recorder = require('../recorder')
3
+ const StepConfig = require('./config')
4
+ const { debug } = require('../output')
5
+ const store = require('../store')
6
+ const { TIMEOUT_ORDER } = require('../timeout')
7
+ const retryStep = require('./retry')
8
+ function recordStep(step, args) {
9
+ step.status = 'queued'
10
+
11
+ // apply step configuration
12
+ const lastArg = args[args.length - 1]
13
+ if (lastArg instanceof StepConfig) {
14
+ const stepConfig = args.pop()
15
+ const { opts, timeout, retry } = stepConfig.getConfig()
16
+
17
+ if (opts) {
18
+ debug(`Step ${step.name}: options applied ${JSON.stringify(opts)}`)
19
+ store.stepOptions = opts
20
+ step.opts = opts
21
+ }
22
+ if (timeout) {
23
+ debug(`Step ${step.name} timeout ${timeout}s`)
24
+ step.setTimeout(timeout * 1000, TIMEOUT_ORDER.codeLimitTime)
25
+ }
26
+ if (retry) retryStep(retry)
27
+ }
28
+
29
+ step.setArguments(args)
30
+ // run async before step hooks
31
+ event.emit(event.step.before, step)
32
+
33
+ const task = `${step.name}: ${step.humanizeArgs()}`
34
+ let val
35
+
36
+ // run step inside promise
37
+ recorder.add(
38
+ task,
39
+ () => {
40
+ if (!step.startTime) {
41
+ // step can be retries
42
+ event.emit(event.step.started, step)
43
+ step.startTime = +Date.now()
44
+ }
45
+ return (val = step.run(...args))
46
+ },
47
+ false,
48
+ undefined,
49
+ step.timeout,
50
+ )
51
+
52
+ event.emit(event.step.after, step)
53
+
54
+ recorder.add('step passed', () => {
55
+ step.endTime = +Date.now()
56
+ event.emit(event.step.passed, step, val)
57
+ event.emit(event.step.finished, step)
58
+ })
59
+
60
+ recorder.catchWithoutStop(err => {
61
+ step.status = 'failed'
62
+ step.endTime = +Date.now()
63
+ event.emit(event.step.failed, step, err)
64
+ event.emit(event.step.finished, step)
65
+ throw err
66
+ })
67
+
68
+ recorder.add('return result', () => val)
69
+ // run async after step hooks
70
+
71
+ return recorder.promise()
72
+ }
73
+
74
+ module.exports = recordStep
@@ -0,0 +1,11 @@
1
+ const recorder = require('../recorder')
2
+ const event = require('../event')
3
+
4
+ function retryStep(opts) {
5
+ if (opts === undefined) opts = 1
6
+ recorder.retry(opts)
7
+ // remove retry once the step passed
8
+ recorder.add(() => event.dispatcher.once(event.step.finished, () => recorder.retries.pop()))
9
+ }
10
+
11
+ module.exports = retryStep
@@ -0,0 +1,55 @@
1
+ const MetaStep = require('./meta')
2
+ const event = require('../event')
3
+
4
+ let currentSection
5
+
6
+ class Section {
7
+ constructor(name = '') {
8
+ this.name = name
9
+
10
+ this.metaStep = new MetaStep(null, name)
11
+
12
+ this.attachMetaStep = step => {
13
+ if (currentSection !== this) return
14
+ if (!step) return
15
+ const metaStep = getRootMetaStep(step)
16
+
17
+ if (metaStep !== this.metaStep) {
18
+ metaStep.metaStep = this.metaStep
19
+ }
20
+ }
21
+ }
22
+
23
+ hidden() {
24
+ this.metaStep.collapsed = true
25
+ return this
26
+ }
27
+
28
+ start() {
29
+ if (currentSection) currentSection.end()
30
+ currentSection = this
31
+ event.dispatcher.prependListener(event.step.before, this.attachMetaStep)
32
+ event.dispatcher.once(event.test.finished, () => this.end())
33
+ return this
34
+ }
35
+
36
+ end() {
37
+ currentSection = null
38
+ event.dispatcher.off(event.step.started, this.attachMetaStep)
39
+ return this
40
+ }
41
+
42
+ /**
43
+ * @returns {Section}
44
+ */
45
+ static current() {
46
+ return currentSection
47
+ }
48
+ }
49
+
50
+ function getRootMetaStep(step) {
51
+ if (step.metaStep) return getRootMetaStep(step.metaStep)
52
+ return step
53
+ }
54
+
55
+ module.exports = Section
package/lib/step.js CHANGED
@@ -1,337 +1,26 @@
1
- // TODO: place MetaStep in other file, disable rule
2
- /* eslint-disable max-classes-per-file */
3
- const store = require('./store');
4
- const Secret = require('./secret');
5
- const event = require('./event');
6
-
7
- const STACK_LINE = 4;
8
-
1
+ // refactored step class, moved to helper
9
2
  /**
10
- * Each command in test executed through `I.` object is wrapped in Step.
11
- * Step allows logging executed commands and triggers hook before and after step execution.
12
- * @param {CodeceptJS.Helper} helper
13
- * @param {string} name
3
+ * Step is wrapper around a helper method.
4
+ * It is used to create a new step that is a combination of other steps.
14
5
  */
15
- class Step {
16
- static get TIMEOUT_ORDER() {
17
- return {
18
- /**
19
- * timeouts set with order below zero only override timeouts of higher order if their value is smaller
20
- */
21
- testOrSuite: -5,
22
- /**
23
- * 0-9 - designated for override of timeouts set from code, 5 is used by stepTimeout plugin when stepTimeout.config.overrideStepLimits=true
24
- */
25
- stepTimeoutHard: 5,
26
- /**
27
- * 10-19 - designated for timeouts set from code, 15 is order of I.setTimeout(t) operation
28
- */
29
- codeLimitTime: 15,
30
- /**
31
- * 20-29 - designated for timeout settings which could be overriden in tests code, 25 is used by stepTimeout plugin when stepTimeout.config.overrideStepLimits=false
32
- */
33
- stepTimeoutSoft: 25,
34
- };
35
- }
36
-
37
- constructor(helper, name) {
38
- /** @member {string} */
39
- this.actor = 'I'; // I = actor
40
- /** @member {CodeceptJS.Helper} */
41
- this.helper = helper; // corresponding helper
42
- /** @member {string} */
43
- this.name = name; // name of a step console
44
- /** @member {string} */
45
- this.helperMethod = name; // helper method
46
- /** @member {string} */
47
- this.status = 'pending';
48
- /**
49
- * @member {string} suffix
50
- * @memberof CodeceptJS.Step#
51
- */
52
- /** @member {string} */
53
- this.prefix = this.suffix = '';
54
- /** @member {string} */
55
- this.comment = '';
56
- /** @member {Array<*>} */
57
- this.args = [];
58
- /** @member {MetaStep} */
59
- this.metaStep = undefined;
60
- /** @member {string} */
61
- this.stack = '';
62
-
63
- const timeouts = new Map();
64
- /**
65
- * @method
66
- * @returns {number|undefined}
67
- */
68
- this.getTimeout = function () {
69
- let totalTimeout;
70
- // iterate over all timeouts starting from highest values of order
71
- new Map([...timeouts.entries()].sort().reverse()).forEach((timeout, order) => {
72
- if (timeout !== undefined && (
73
- // when orders >= 0 - timeout value overrides those set with higher order elements
74
- order >= 0
75
-
76
- // when `order < 0 && totalTimeout === undefined` - timeout is used when nothing is set by elements with higher order
77
- || totalTimeout === undefined
78
-
79
- // when `order < 0` - timeout overrides higher values of timeout or 'no timeout' (totalTimeout === 0) set by elements with higher order
80
- || timeout > 0 && (timeout < totalTimeout || totalTimeout === 0)
81
- )) {
82
- totalTimeout = timeout;
83
- }
84
- });
85
- return totalTimeout;
86
- };
87
- /**
88
- * @method
89
- * @param {number} timeout - timeout in milliseconds or 0 if no timeout
90
- * @param {number} order - order defines the priority of timeout, timeouts set with lower order override those set with higher order.
91
- * When order below 0 value of timeout only override if new value is lower
92
- */
93
- this.setTimeout = function (timeout, order) {
94
- timeouts.set(order, timeout);
95
- };
96
-
97
- this.setTrace();
98
- }
99
-
100
- /** @function */
101
- setTrace() {
102
- Error.captureStackTrace(this);
103
- }
104
-
105
- /** @param {Array<*>} args */
106
- setArguments(args) {
107
- this.args = args;
108
- }
109
-
110
- /**
111
- * @param {...any} args
112
- * @return {*}
113
- */
114
- run() {
115
- this.args = Array.prototype.slice.call(arguments);
116
- if (store.dryRun) {
117
- this.setStatus('success');
118
- return Promise.resolve(new Proxy({}, dryRunResolver()));
119
- }
120
- let result;
121
- try {
122
- if (this.helperMethod !== 'say') {
123
- result = this.helper[this.helperMethod].apply(this.helper, this.args);
124
- }
125
- this.setStatus('success');
126
- } catch (err) {
127
- this.setStatus('failed');
128
- throw err;
129
- }
130
- return result;
131
- }
132
-
133
- /** @param {string} status */
134
- setStatus(status) {
135
- this.status = status;
136
- if (this.metaStep) {
137
- this.metaStep.setStatus(status);
138
- }
139
- }
140
-
141
- /** @return {string} */
142
- humanize() {
143
- return humanizeString(this.name);
144
- }
145
-
146
- /** @return {string} */
147
- humanizeArgs() {
148
- return this.args.map((arg) => {
149
- if (!arg) {
150
- return '';
151
- }
152
- if (typeof arg === 'string') {
153
- return `"${arg}"`;
154
- }
155
- if (Array.isArray(arg)) {
156
- try {
157
- const res = JSON.stringify(arg);
158
- return res;
159
- } catch (err) {
160
- return `[${arg.toString()}]`;
161
- }
162
- } else if (typeof arg === 'function') {
163
- return arg.toString();
164
- } else if (typeof arg === 'undefined') {
165
- return `${arg}`;
166
- } else if (arg instanceof Secret) {
167
- return arg.getMasked();
168
- } else if (arg.toString && arg.toString() !== '[object Object]') {
169
- return arg.toString();
170
- } else if (typeof arg === 'object') {
171
- const returnedArg = {};
172
- for (const [key, value] of Object.entries(arg)) {
173
- returnedArg[key] = value;
174
- if (value instanceof Secret) returnedArg[key] = value.getMasked();
175
- }
176
- return JSON.stringify(returnedArg);
177
- }
178
- return arg;
179
- }).join(', ');
180
- }
181
-
182
- /** @return {string} */
183
- line() {
184
- const lines = this.stack.split('\n');
185
- if (lines[STACK_LINE]) {
186
- return lines[STACK_LINE].trim().replace(global.codecept_dir || '', '.').trim();
187
- }
188
- return '';
189
- }
190
-
191
- /** @return {string} */
192
- toString() {
193
- return `${this.prefix}${this.actor} ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`;
194
- }
195
-
196
- /** @return {string} */
197
- toCode() {
198
- return `${this.prefix}${this.actor}.${this.name}(${this.humanizeArgs()})${this.suffix}`;
199
- }
200
-
201
- isMetaStep() {
202
- return this.constructor.name === 'MetaStep';
203
- }
204
-
205
- /** @return {boolean} */
206
- hasBDDAncestor() {
207
- let hasBDD = false;
208
- let processingStep;
209
- processingStep = this;
210
-
211
- while (processingStep.metaStep) {
212
- if (processingStep.metaStep.actor.match(/^(Given|When|Then|And)/)) {
213
- hasBDD = true;
214
- break;
215
- } else {
216
- processingStep = processingStep.metaStep;
217
- }
218
- }
219
- return hasBDD;
220
- }
221
- }
222
-
223
- /** @extends Step */
224
- class MetaStep extends Step {
225
- constructor(obj, method) {
226
- super(null, method);
227
- this.actor = obj;
228
- }
6
+ const BaseStep = require('./step/base')
7
+ const StepConfig = require('./step/config')
8
+ const Step = require('./step/helper')
229
9
 
230
- /** @return {boolean} */
231
- isBDD() {
232
- if (this.actor && this.actor.match && this.actor.match(/^(Given|When|Then|And)/)) {
233
- return true;
234
- }
235
- return false;
236
- }
237
-
238
- isWithin() {
239
- if (this.actor && this.actor.match && this.actor.match(/^(Within)/)) {
240
- return true;
241
- }
242
- return false;
243
- }
244
-
245
- toString() {
246
- const actorText = this.actor;
247
-
248
- if (this.isBDD() || this.isWithin()) {
249
- return `${this.prefix}${actorText} ${this.name} "${this.humanizeArgs()}${this.suffix}"`;
250
- }
251
-
252
- if (actorText === 'I') {
253
- return `${this.prefix}${actorText} ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`;
254
- }
255
-
256
- return `On ${this.prefix}${actorText}: ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`;
257
- }
258
-
259
- humanize() {
260
- return humanizeString(this.name);
261
- }
262
-
263
- setTrace() {
264
- }
265
-
266
- setContext(context) {
267
- this.context = context;
268
- }
269
-
270
- /** @return {*} */
271
- run(fn) {
272
- this.status = 'queued';
273
- this.setArguments(Array.from(arguments).slice(1));
274
- let result;
275
-
276
- const registerStep = (step) => {
277
- this.metaStep = null;
278
- step.metaStep = this;
279
- };
280
- event.dispatcher.prependListener(event.step.before, registerStep);
281
- // Handle async and sync methods.
282
- if (fn.constructor.name === 'AsyncFunction') {
283
- result = fn.apply(this.context, this.args).then((result) => {
284
- return result;
285
- }).catch((error) => {
286
- this.setStatus('failed');
287
- throw error;
288
- }).finally(() => {
289
- this.endTime = Date.now();
290
- event.dispatcher.removeListener(event.step.before, registerStep);
291
- });
292
- } else {
293
- try {
294
- this.startTime = Date.now();
295
- result = fn.apply(this.context, this.args);
296
- } catch (error) {
297
- this.setStatus('failed');
298
- throw error;
299
- } finally {
300
- this.endTime = Date.now();
301
- event.dispatcher.removeListener(event.step.before, registerStep);
302
- }
303
- }
304
-
305
- return result;
306
- }
307
- }
308
-
309
- Step.TIMEOUTS = {};
310
-
311
- /** @type {Class<MetaStep>} */
312
- Step.MetaStep = MetaStep;
313
-
314
- module.exports = Step;
315
-
316
- function dryRunResolver() {
317
- return {
318
- get(target, prop) {
319
- if (prop === 'toString') return () => '<VALUE>';
320
- return new Proxy({}, dryRunResolver());
321
- },
322
- };
323
- }
324
-
325
- function humanizeString(string) {
326
- // split strings by words, then make them all lowercase
327
- const _result = string.replace(/([a-z](?=[A-Z]))/g, '$1 ')
328
- .split(' ')
329
- .map(word => word.toLowerCase());
10
+ /**
11
+ * MetaStep is a step that is used to wrap other steps.
12
+ * It is used to create a new step that is a combination of other steps.
13
+ * It is used to create a new step that is a combination of other steps.
14
+ */
15
+ const MetaStep = require('./step/meta')
330
16
 
331
- _result[0] = _result[0] === 'i' ? capitalizeFLetter(_result[0]) : _result[0];
332
- return _result.join(' ').trim();
333
- }
17
+ /**
18
+ * Step used to execute a single function
19
+ */
20
+ const FuncStep = require('./step/func')
334
21
 
335
- function capitalizeFLetter(string) {
336
- return (string[0].toUpperCase() + string.slice(1));
337
- }
22
+ module.exports = Step
23
+ module.exports.MetaStep = MetaStep
24
+ module.exports.BaseStep = BaseStep
25
+ module.exports.StepConfig = StepConfig
26
+ module.exports.FuncStep = FuncStep
package/lib/steps.js ADDED
@@ -0,0 +1,50 @@
1
+ const StepConfig = require('./step/config')
2
+ const Section = require('./step/section')
3
+ function stepOpts(opts = {}) {
4
+ return new StepConfig(opts)
5
+ }
6
+
7
+ function stepTimeout(timeout) {
8
+ return new StepConfig().timeout(timeout)
9
+ }
10
+
11
+ function stepRetry(retry) {
12
+ return new StepConfig().retry(retry)
13
+ }
14
+
15
+ function section(name) {
16
+ if (!name) return endSection()
17
+ return new Section(name).start()
18
+ }
19
+
20
+ function endSection() {
21
+ return Section.current().end()
22
+ }
23
+
24
+ // Section function to be added here
25
+
26
+ const step = {
27
+ // steps.opts syntax
28
+ opts: stepOpts,
29
+ timeout: stepTimeout,
30
+ retry: stepRetry,
31
+
32
+ // one-function syntax
33
+ stepTimeout,
34
+ stepRetry,
35
+ stepOpts,
36
+
37
+ // sections
38
+ section,
39
+ endSection,
40
+
41
+ Section: section,
42
+ EndSection: endSection,
43
+
44
+ // shortcuts
45
+ Given: () => section('Given'),
46
+ When: () => section('When'),
47
+ Then: () => section('Then'),
48
+ }
49
+
50
+ module.exports = step
package/lib/store.js CHANGED
@@ -3,12 +3,44 @@
3
3
  * @namespace
4
4
  */
5
5
  const store = {
6
- /** @type {boolean} */
6
+ /**
7
+ * If we are in --debug mode
8
+ * @type {boolean}
9
+ */
7
10
  debugMode: false,
8
- /** @type {boolean} */
11
+
12
+ /**
13
+ * Is timeouts enabled
14
+ * @type {boolean}
15
+ */
9
16
  timeouts: true,
10
- /** @type {boolean} */
17
+
18
+ /**
19
+ * If auto-retries are enabled by retryFailedStep plugin
20
+ * tryTo effect disables them
21
+ * @type {boolean}
22
+ */
23
+ autoRetries: false,
24
+
25
+ /**
26
+ * Tests are executed via dry-run
27
+ * @type {boolean}
28
+ */
11
29
  dryRun: false,
12
- };
30
+ /**
31
+ * If we are in pause mode
32
+ * @type {boolean}
33
+ */
34
+ onPause: false,
35
+
36
+ // current object states
37
+
38
+ /** @type {CodeceptJS.Test | null} */
39
+ currentTest: null,
40
+ /** @type {CodeceptJS.Step | null} */
41
+ currentStep: null,
42
+ /** @type {CodeceptJS.Suite | null} */
43
+ currentSuite: null,
44
+ }
13
45
 
14
- module.exports = store;
46
+ module.exports = store
@@ -6,17 +6,8 @@ heal.addRecipe('ai', {
6
6
  html: ({ I }) => I.grabHTMLFrom('body'),
7
7
  },
8
8
  suggest: true,
9
- steps: [
10
- 'click',
11
- 'fillField',
12
- 'appendField',
13
- 'selectOption',
14
- 'attachFile',
15
- 'checkOption',
16
- 'uncheckOption',
17
- 'doubleClick',
18
- ],
19
- fn: async (args) => {
9
+ steps: ['click', 'fillField', 'appendField', 'selectOption', 'attachFile', 'checkOption', 'uncheckOption', 'doubleClick'],
10
+ fn: async args => {
20
11
  return ai.healFailedStep(args)
21
12
  },
22
13
  })