codeceptjs 3.6.10 → 3.7.0-beta.10

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 (127) hide show
  1. package/README.md +89 -119
  2. package/bin/codecept.js +9 -2
  3. package/docs/webapi/clearCookie.mustache +1 -1
  4. package/lib/actor.js +66 -102
  5. package/lib/ai.js +130 -121
  6. package/lib/assert/empty.js +3 -5
  7. package/lib/assert/equal.js +4 -7
  8. package/lib/assert/include.js +4 -6
  9. package/lib/assert/throws.js +2 -4
  10. package/lib/assert/truth.js +2 -2
  11. package/lib/codecept.js +87 -83
  12. package/lib/command/check.js +186 -0
  13. package/lib/command/configMigrate.js +2 -4
  14. package/lib/command/definitions.js +8 -26
  15. package/lib/command/generate.js +10 -14
  16. package/lib/command/gherkin/snippets.js +10 -8
  17. package/lib/command/gherkin/steps.js +1 -1
  18. package/lib/command/info.js +1 -3
  19. package/lib/command/init.js +8 -12
  20. package/lib/command/interactive.js +2 -2
  21. package/lib/command/list.js +1 -1
  22. package/lib/command/run-multiple.js +12 -35
  23. package/lib/command/run-workers.js +5 -57
  24. package/lib/command/utils.js +5 -6
  25. package/lib/command/workers/runTests.js +68 -232
  26. package/lib/container.js +354 -237
  27. package/lib/data/context.js +10 -13
  28. package/lib/data/dataScenarioConfig.js +8 -8
  29. package/lib/data/dataTableArgument.js +6 -6
  30. package/lib/data/table.js +5 -11
  31. package/lib/effects.js +218 -0
  32. package/lib/els.js +158 -0
  33. package/lib/event.js +19 -17
  34. package/lib/heal.js +88 -80
  35. package/lib/helper/AI.js +2 -1
  36. package/lib/helper/ApiDataFactory.js +3 -6
  37. package/lib/helper/Appium.js +45 -51
  38. package/lib/helper/FileSystem.js +3 -3
  39. package/lib/helper/GraphQLDataFactory.js +3 -3
  40. package/lib/helper/JSONResponse.js +57 -37
  41. package/lib/helper/Nightmare.js +35 -53
  42. package/lib/helper/Playwright.js +211 -252
  43. package/lib/helper/Protractor.js +54 -77
  44. package/lib/helper/Puppeteer.js +139 -232
  45. package/lib/helper/REST.js +5 -17
  46. package/lib/helper/TestCafe.js +21 -44
  47. package/lib/helper/WebDriver.js +131 -169
  48. package/lib/helper/testcafe/testcafe-utils.js +26 -27
  49. package/lib/listener/emptyRun.js +55 -0
  50. package/lib/listener/exit.js +7 -10
  51. package/lib/listener/{retry.js → globalRetry.js} +5 -5
  52. package/lib/listener/globalTimeout.js +165 -0
  53. package/lib/listener/helpers.js +15 -15
  54. package/lib/listener/mocha.js +1 -1
  55. package/lib/listener/result.js +12 -0
  56. package/lib/listener/steps.js +20 -18
  57. package/lib/listener/store.js +20 -0
  58. package/lib/mocha/asyncWrapper.js +216 -0
  59. package/lib/{interfaces → mocha}/bdd.js +3 -3
  60. package/lib/mocha/cli.js +308 -0
  61. package/lib/mocha/factory.js +104 -0
  62. package/lib/{interfaces → mocha}/featureConfig.js +24 -12
  63. package/lib/{interfaces → mocha}/gherkin.js +26 -28
  64. package/lib/mocha/hooks.js +112 -0
  65. package/lib/mocha/index.js +12 -0
  66. package/lib/mocha/inject.js +29 -0
  67. package/lib/{interfaces → mocha}/scenarioConfig.js +21 -6
  68. package/lib/mocha/suite.js +81 -0
  69. package/lib/mocha/test.js +159 -0
  70. package/lib/mocha/types.d.ts +42 -0
  71. package/lib/mocha/ui.js +219 -0
  72. package/lib/output.js +82 -62
  73. package/lib/pause.js +155 -138
  74. package/lib/plugin/analyze.js +349 -0
  75. package/lib/plugin/autoDelay.js +6 -6
  76. package/lib/plugin/autoLogin.js +6 -7
  77. package/lib/plugin/commentStep.js +6 -1
  78. package/lib/plugin/coverage.js +10 -19
  79. package/lib/plugin/customLocator.js +3 -3
  80. package/lib/plugin/customReporter.js +52 -0
  81. package/lib/plugin/eachElement.js +1 -1
  82. package/lib/plugin/fakerTransform.js +1 -1
  83. package/lib/plugin/heal.js +36 -9
  84. package/lib/plugin/pageInfo.js +140 -0
  85. package/lib/plugin/retryFailedStep.js +4 -4
  86. package/lib/plugin/retryTo.js +18 -118
  87. package/lib/plugin/screenshotOnFail.js +17 -49
  88. package/lib/plugin/selenoid.js +15 -35
  89. package/lib/plugin/standardActingHelpers.js +4 -1
  90. package/lib/plugin/stepByStepReport.js +56 -17
  91. package/lib/plugin/stepTimeout.js +5 -12
  92. package/lib/plugin/subtitles.js +4 -4
  93. package/lib/plugin/tryTo.js +17 -107
  94. package/lib/plugin/wdio.js +8 -10
  95. package/lib/recorder.js +146 -125
  96. package/lib/rerun.js +43 -42
  97. package/lib/result.js +161 -0
  98. package/lib/secret.js +1 -1
  99. package/lib/step/base.js +228 -0
  100. package/lib/step/config.js +50 -0
  101. package/lib/step/func.js +46 -0
  102. package/lib/step/helper.js +50 -0
  103. package/lib/step/meta.js +99 -0
  104. package/lib/step/record.js +74 -0
  105. package/lib/step/retry.js +11 -0
  106. package/lib/step/section.js +55 -0
  107. package/lib/step.js +21 -332
  108. package/lib/steps.js +50 -0
  109. package/lib/store.js +10 -2
  110. package/lib/template/heal.js +2 -11
  111. package/lib/timeout.js +66 -0
  112. package/lib/utils.js +317 -216
  113. package/lib/within.js +73 -55
  114. package/lib/workers.js +259 -275
  115. package/package.json +56 -54
  116. package/typings/index.d.ts +175 -186
  117. package/typings/promiseBasedTypes.d.ts +164 -17
  118. package/typings/types.d.ts +284 -115
  119. package/lib/cli.js +0 -256
  120. package/lib/helper/ExpectHelper.js +0 -391
  121. package/lib/helper/SoftExpectHelper.js +0 -381
  122. package/lib/listener/artifacts.js +0 -19
  123. package/lib/listener/timeout.js +0 -109
  124. package/lib/mochaFactory.js +0 -113
  125. package/lib/plugin/debugErrors.js +0 -67
  126. package/lib/scenario.js +0 -224
  127. package/lib/ui.js +0 -236
@@ -1,291 +1,127 @@
1
- const tty = require('tty');
1
+ const tty = require('tty')
2
2
 
3
3
  if (!tty.getWindowSize) {
4
4
  // this is really old method, long removed from Node, but Mocha
5
5
  // reporters fall back on it if they cannot use `process.stdout.getWindowSize`
6
6
  // we need to polyfill it.
7
- tty.getWindowSize = () => [40, 80];
7
+ tty.getWindowSize = () => [40, 80]
8
8
  }
9
9
 
10
- const { parentPort, workerData } = require('worker_threads');
11
- const event = require('../../event');
12
- const container = require('../../container');
13
- const { getConfig } = require('../utils');
14
- const { tryOrDefault, deepMerge } = require('../../utils');
10
+ const { parentPort, workerData } = require('worker_threads')
11
+ const event = require('../../event')
12
+ const container = require('../../container')
13
+ const { getConfig } = require('../utils')
14
+ const { tryOrDefault, deepMerge } = require('../../utils')
15
15
 
16
- let stdout = '';
16
+ let stdout = ''
17
17
 
18
- const stderr = '';
18
+ const stderr = ''
19
19
 
20
20
  // Requiring of Codecept need to be after tty.getWindowSize is available.
21
- const Codecept = require(process.env.CODECEPT_CLASS_PATH || '../../codecept');
21
+ const Codecept = require(process.env.CODECEPT_CLASS_PATH || '../../codecept')
22
22
 
23
- const {
24
- options, tests, testRoot, workerIndex,
25
- } = workerData;
23
+ const { options, tests, testRoot, workerIndex } = workerData
26
24
 
27
25
  // hide worker output
28
- if (!options.debug && !options.verbose) process.stdout.write = (string) => { stdout += string; return true; };
26
+ if (!options.debug && !options.verbose)
27
+ process.stdout.write = string => {
28
+ stdout += string
29
+ return true
30
+ }
29
31
 
30
- const overrideConfigs = tryOrDefault(() => JSON.parse(options.override), {});
32
+ const overrideConfigs = tryOrDefault(() => JSON.parse(options.override), {})
31
33
 
32
34
  // important deep merge so dynamic things e.g. functions on config are not overridden
33
- const config = deepMerge(getConfig(options.config || testRoot), overrideConfigs);
35
+ const config = deepMerge(getConfig(options.config || testRoot), overrideConfigs)
34
36
 
35
37
  // Load test and run
36
- const codecept = new Codecept(config, options);
37
- codecept.init(testRoot);
38
- codecept.loadTests();
39
- const mocha = container.mocha();
40
- filterTests();
41
-
42
- (async function () {
38
+ const codecept = new Codecept(config, options)
39
+ codecept.init(testRoot)
40
+ codecept.loadTests()
41
+ const mocha = container.mocha()
42
+ filterTests()
43
+
44
+ // run tests
45
+ ;(async function () {
43
46
  if (mocha.suite.total()) {
44
- await runTests();
47
+ await runTests()
45
48
  }
46
- }());
49
+ })()
47
50
 
48
51
  async function runTests() {
49
52
  try {
50
- await codecept.bootstrap();
53
+ await codecept.bootstrap()
51
54
  } catch (err) {
52
- throw new Error(`Error while running bootstrap file :${err}`);
55
+ throw new Error(`Error while running bootstrap file :${err}`)
53
56
  }
54
- listenToParentThread();
55
- initializeListeners();
56
- disablePause();
57
+ listenToParentThread()
58
+ initializeListeners()
59
+ disablePause()
57
60
  try {
58
- await codecept.run();
61
+ await codecept.run()
59
62
  } finally {
60
- await codecept.teardown();
63
+ await codecept.teardown()
61
64
  }
62
65
  }
63
66
 
64
67
  function filterTests() {
65
- const files = codecept.testFiles;
66
- mocha.files = files;
67
- mocha.loadFiles();
68
+ const files = codecept.testFiles
69
+ mocha.files = files
70
+ mocha.loadFiles()
68
71
 
69
72
  for (const suite of mocha.suite.suites) {
70
- suite.tests = suite.tests.filter(test => tests.indexOf(test.uid) >= 0);
73
+ suite.tests = suite.tests.filter(test => tests.indexOf(test.uid) >= 0)
71
74
  }
72
75
  }
73
76
 
74
77
  function initializeListeners() {
75
- function simplifyError(error) {
76
- if (error) {
77
- const {
78
- stack,
79
- uncaught,
80
- message,
81
- actual,
82
- expected,
83
- } = error;
84
-
85
- return {
86
- stack,
87
- uncaught,
88
- message,
89
- actual,
90
- expected,
91
- };
92
- }
93
-
94
- return null;
95
- }
96
- function simplifyTest(test, err = null) {
97
- test = { ...test };
98
-
99
- if (test.start && !test.duration) {
100
- const end = new Date();
101
- test.duration = end - test.start;
102
- }
103
-
104
- if (test.err) {
105
- err = simplifyError(test.err);
106
- test.status = 'failed';
107
- } else if (err) {
108
- err = simplifyError(err);
109
- test.status = 'failed';
110
- }
111
- const parent = {};
112
- if (test.parent) {
113
- parent.title = test.parent.title;
114
- }
115
-
116
- if (test.opts) {
117
- Object.keys(test.opts).forEach(k => {
118
- if (typeof test.opts[k] === 'object') delete test.opts[k];
119
- if (typeof test.opts[k] === 'function') delete test.opts[k];
120
- });
121
- }
122
-
123
- return {
124
- opts: test.opts || {},
125
- tags: test.tags || [],
126
- uid: test.uid,
127
- workerIndex,
128
- retries: test._retries,
129
- title: test.title,
130
- status: test.status,
131
- duration: test.duration || 0,
132
- err,
133
- parent,
134
- steps: test.steps && test.steps.length > 0 ? simplifyStepsInTestObject(test.steps, err) : [],
135
- };
136
- }
137
-
138
- function simplifyStepsInTestObject(steps, err) {
139
- steps = [...steps];
140
- const _steps = [];
141
-
142
- for (step of steps) {
143
- const _args = [];
144
-
145
- if (step.args) {
146
- for (const arg of step.args) {
147
- // check if arg is a JOI object
148
- if (arg && arg.$_root) {
149
- _args.push(JSON.stringify(arg).slice(0, 300));
150
- // check if arg is a function
151
- } else if (arg && typeof arg === 'function') {
152
- _args.push(arg.name);
153
- } else {
154
- _args.push(arg);
155
- }
156
- }
157
- }
158
-
159
- _steps.push({
160
- actor: step.actor,
161
- name: step.name,
162
- status: step.status,
163
- args: JSON.stringify(_args),
164
- startedAt: step.startedAt,
165
- startTime: step.startTime,
166
- endTime: step.endTime,
167
- finishedAt: step.finishedAt,
168
- duration: step.duration,
169
- err,
170
- });
171
- }
172
-
173
- return _steps;
174
- }
175
-
176
- function simplifyStep(step, err = null) {
177
- step = { ...step };
178
-
179
- if (step.startTime && !step.duration) {
180
- const end = new Date();
181
- step.duration = end - step.startTime;
182
- }
183
-
184
- if (step.err) {
185
- err = simplifyError(step.err);
186
- step.status = 'failed';
187
- } else if (err) {
188
- err = simplifyError(err);
189
- step.status = 'failed';
190
- }
191
-
192
- const parent = {};
193
- if (step.metaStep) {
194
- parent.title = step.metaStep.actor;
195
- }
196
-
197
- if (step.opts) {
198
- Object.keys(step.opts).forEach(k => {
199
- if (typeof step.opts[k] === 'object') delete step.opts[k];
200
- if (typeof step.opts[k] === 'function') delete step.opts[k];
201
- });
202
- }
203
-
204
- return {
205
- opts: step.opts || {},
206
- workerIndex,
207
- title: step.name,
208
- status: step.status,
209
- duration: step.duration || 0,
210
- err,
211
- parent,
212
- test: simplifyTest(step.test),
213
- };
214
- }
215
-
216
- collectStats();
217
78
  // suite
218
- event.dispatcher.on(event.suite.before, suite => sendToParentThread({ event: event.suite.before, workerIndex, data: simplifyTest(suite) }));
219
- event.dispatcher.on(event.suite.after, suite => sendToParentThread({ event: event.suite.after, workerIndex, data: simplifyTest(suite) }));
79
+ event.dispatcher.on(event.suite.before, suite => sendToParentThread({ event: event.suite.before, workerIndex, data: suite.simplify() }))
80
+ event.dispatcher.on(event.suite.after, suite => sendToParentThread({ event: event.suite.after, workerIndex, data: suite.simplify() }))
220
81
 
221
82
  // calculate duration
222
- event.dispatcher.on(event.test.started, test => test.start = new Date());
83
+ event.dispatcher.on(event.test.started, test => (test.start = new Date()))
223
84
 
224
85
  // tests
225
- event.dispatcher.on(event.test.before, test => sendToParentThread({ event: event.test.before, workerIndex, data: simplifyTest(test) }));
226
- event.dispatcher.on(event.test.after, test => sendToParentThread({ event: event.test.after, workerIndex, data: simplifyTest(test) }));
86
+ event.dispatcher.on(event.test.before, test => sendToParentThread({ event: event.test.before, workerIndex, data: test.simplify() }))
87
+ event.dispatcher.on(event.test.after, test => sendToParentThread({ event: event.test.after, workerIndex, data: test.simplify() }))
227
88
  // we should force-send correct errors to prevent race condition
228
- event.dispatcher.on(event.test.finished, (test, err) => sendToParentThread({ event: event.test.finished, workerIndex, data: simplifyTest(test, err) }));
229
- event.dispatcher.on(event.test.failed, (test, err) => sendToParentThread({ event: event.test.failed, workerIndex, data: simplifyTest(test, err) }));
230
- event.dispatcher.on(event.test.passed, (test, err) => sendToParentThread({ event: event.test.passed, workerIndex, data: simplifyTest(test, err) }));
231
- event.dispatcher.on(event.test.started, test => sendToParentThread({ event: event.test.started, workerIndex, data: simplifyTest(test) }));
232
- event.dispatcher.on(event.test.skipped, test => sendToParentThread({ event: event.test.skipped, workerIndex, data: simplifyTest(test) }));
89
+ event.dispatcher.on(event.test.finished, (test, err) => sendToParentThread({ event: event.test.finished, workerIndex, data: { ...test.simplify(), err } }))
90
+ event.dispatcher.on(event.test.failed, (test, err) => sendToParentThread({ event: event.test.failed, workerIndex, data: { ...test.simplify(), err } }))
91
+ event.dispatcher.on(event.test.passed, (test, err) => sendToParentThread({ event: event.test.passed, workerIndex, data: { ...test.simplify(), err } }))
92
+ event.dispatcher.on(event.test.started, test => sendToParentThread({ event: event.test.started, workerIndex, data: test.simplify() }))
93
+ event.dispatcher.on(event.test.skipped, test => sendToParentThread({ event: event.test.skipped, workerIndex, data: test.simplify() }))
233
94
 
234
95
  // steps
235
- event.dispatcher.on(event.step.finished, step => sendToParentThread({ event: event.step.finished, workerIndex, data: simplifyStep(step) }));
236
- event.dispatcher.on(event.step.started, step => sendToParentThread({ event: event.step.started, workerIndex, data: simplifyStep(step) }));
237
- event.dispatcher.on(event.step.passed, step => sendToParentThread({ event: event.step.passed, workerIndex, data: simplifyStep(step) }));
238
- event.dispatcher.on(event.step.failed, step => sendToParentThread({ event: event.step.failed, workerIndex, data: simplifyStep(step) }));
96
+ event.dispatcher.on(event.step.finished, step => sendToParentThread({ event: event.step.finished, workerIndex, data: step.simplify() }))
97
+ event.dispatcher.on(event.step.started, step => sendToParentThread({ event: event.step.started, workerIndex, data: step.simplify() }))
98
+ event.dispatcher.on(event.step.passed, step => sendToParentThread({ event: event.step.passed, workerIndex, data: step.simplify() }))
99
+ event.dispatcher.on(event.step.failed, step => sendToParentThread({ event: event.step.failed, workerIndex, data: step.simplify() }))
239
100
 
240
- event.dispatcher.on(event.hook.failed, (test, err) => sendToParentThread({ event: event.hook.failed, workerIndex, data: simplifyTest(test, err) }));
241
- event.dispatcher.on(event.hook.passed, (test, err) => sendToParentThread({ event: event.hook.passed, workerIndex, data: simplifyTest(test, err) }));
242
- event.dispatcher.on(event.all.failures, (data) => sendToParentThread({ event: event.all.failures, workerIndex, data }));
101
+ event.dispatcher.on(event.hook.failed, (hook, err) => sendToParentThread({ event: event.hook.failed, workerIndex, data: { ...hook.simplify(), err } }))
102
+ event.dispatcher.on(event.hook.passed, hook => sendToParentThread({ event: event.hook.passed, workerIndex, data: hook.simplify() }))
103
+ event.dispatcher.on(event.hook.finished, hook => sendToParentThread({ event: event.hook.finished, workerIndex, data: hook.simplify() }))
243
104
 
105
+ event.dispatcher.once(event.all.after, () => {
106
+ sendToParentThread({ event: event.all.after, workerIndex, data: container.result().simplify() })
107
+ })
244
108
  // all
245
- event.dispatcher.once(event.all.result, () => parentPort.close());
109
+ event.dispatcher.once(event.all.result, () => {
110
+ sendToParentThread({ event: event.all.result, workerIndex, data: container.result().simplify() })
111
+ parentPort?.close()
112
+ })
246
113
  }
247
114
 
248
115
  function disablePause() {
249
- global.pause = () => {};
250
- }
251
-
252
- function collectStats() {
253
- const stats = {
254
- passes: 0,
255
- failures: 0,
256
- skipped: 0,
257
- tests: 0,
258
- pending: 0,
259
- };
260
- event.dispatcher.on(event.test.skipped, () => {
261
- stats.skipped++;
262
- });
263
- event.dispatcher.on(event.test.passed, () => {
264
- stats.passes++;
265
- });
266
- event.dispatcher.on(event.test.failed, (test) => {
267
- if (test.ctx._runnable.title.includes('hook: AfterSuite')) {
268
- stats.failedHooks += 1;
269
- }
270
- stats.failures++;
271
- });
272
- event.dispatcher.on(event.test.skipped, () => {
273
- stats.pending++;
274
- });
275
- event.dispatcher.on(event.test.finished, () => {
276
- stats.tests++;
277
- });
278
- event.dispatcher.once(event.all.after, () => {
279
- sendToParentThread({ event: event.all.after, data: stats });
280
- });
116
+ global.pause = () => {}
281
117
  }
282
118
 
283
119
  function sendToParentThread(data) {
284
- parentPort.postMessage(data);
120
+ parentPort?.postMessage(data)
285
121
  }
286
122
 
287
123
  function listenToParentThread() {
288
- parentPort.on('message', (eventData) => {
289
- container.append({ support: eventData.data });
290
- });
124
+ parentPort?.on('message', eventData => {
125
+ container.append({ support: eventData.data })
126
+ })
291
127
  }