codeceptjs 4.0.0-beta.1 → 4.0.0-beta.10.esm-aria

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 (207) hide show
  1. package/README.md +133 -120
  2. package/bin/codecept.js +107 -96
  3. package/bin/test-server.js +64 -0
  4. package/docs/webapi/clearCookie.mustache +1 -1
  5. package/docs/webapi/click.mustache +5 -1
  6. package/lib/actor.js +71 -103
  7. package/lib/ai.js +159 -188
  8. package/lib/assert/empty.js +22 -24
  9. package/lib/assert/equal.js +30 -37
  10. package/lib/assert/error.js +14 -14
  11. package/lib/assert/include.js +43 -48
  12. package/lib/assert/throws.js +11 -11
  13. package/lib/assert/truth.js +22 -22
  14. package/lib/assert.js +20 -18
  15. package/lib/codecept.js +238 -162
  16. package/lib/colorUtils.js +50 -52
  17. package/lib/command/check.js +206 -0
  18. package/lib/command/configMigrate.js +56 -51
  19. package/lib/command/definitions.js +96 -109
  20. package/lib/command/dryRun.js +77 -79
  21. package/lib/command/generate.js +234 -194
  22. package/lib/command/gherkin/init.js +42 -33
  23. package/lib/command/gherkin/snippets.js +76 -74
  24. package/lib/command/gherkin/steps.js +20 -17
  25. package/lib/command/info.js +74 -38
  26. package/lib/command/init.js +300 -290
  27. package/lib/command/interactive.js +41 -32
  28. package/lib/command/list.js +28 -27
  29. package/lib/command/run-multiple/chunk.js +51 -48
  30. package/lib/command/run-multiple/collection.js +5 -5
  31. package/lib/command/run-multiple/run.js +5 -1
  32. package/lib/command/run-multiple.js +97 -97
  33. package/lib/command/run-rerun.js +19 -25
  34. package/lib/command/run-workers.js +68 -92
  35. package/lib/command/run.js +39 -27
  36. package/lib/command/utils.js +80 -64
  37. package/lib/command/workers/runTests.js +388 -226
  38. package/lib/config.js +124 -50
  39. package/lib/container.js +751 -260
  40. package/lib/data/context.js +60 -61
  41. package/lib/data/dataScenarioConfig.js +47 -47
  42. package/lib/data/dataTableArgument.js +32 -32
  43. package/lib/data/table.js +22 -22
  44. package/lib/effects.js +307 -0
  45. package/lib/element/WebElement.js +327 -0
  46. package/lib/els.js +160 -0
  47. package/lib/event.js +173 -163
  48. package/lib/globals.js +141 -0
  49. package/lib/heal.js +89 -85
  50. package/lib/helper/AI.js +131 -41
  51. package/lib/helper/ApiDataFactory.js +107 -75
  52. package/lib/helper/Appium.js +542 -404
  53. package/lib/helper/FileSystem.js +100 -79
  54. package/lib/helper/GraphQL.js +44 -43
  55. package/lib/helper/GraphQLDataFactory.js +52 -52
  56. package/lib/helper/JSONResponse.js +126 -88
  57. package/lib/helper/Mochawesome.js +54 -29
  58. package/lib/helper/Playwright.js +2547 -1316
  59. package/lib/helper/Puppeteer.js +1578 -1181
  60. package/lib/helper/REST.js +209 -68
  61. package/lib/helper/WebDriver.js +1482 -1342
  62. package/lib/helper/errors/ConnectionRefused.js +6 -6
  63. package/lib/helper/errors/ElementAssertion.js +11 -16
  64. package/lib/helper/errors/ElementNotFound.js +5 -9
  65. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +5 -5
  66. package/lib/helper/extras/Console.js +11 -11
  67. package/lib/helper/extras/PlaywrightLocator.js +110 -0
  68. package/lib/helper/extras/PlaywrightPropEngine.js +18 -18
  69. package/lib/helper/extras/PlaywrightReactVueLocator.js +17 -8
  70. package/lib/helper/extras/PlaywrightRestartOpts.js +25 -11
  71. package/lib/helper/extras/Popup.js +22 -22
  72. package/lib/helper/extras/React.js +27 -28
  73. package/lib/helper/network/actions.js +36 -42
  74. package/lib/helper/network/utils.js +78 -84
  75. package/lib/helper/scripts/blurElement.js +5 -5
  76. package/lib/helper/scripts/focusElement.js +5 -5
  77. package/lib/helper/scripts/highlightElement.js +8 -8
  78. package/lib/helper/scripts/isElementClickable.js +34 -34
  79. package/lib/helper.js +2 -3
  80. package/lib/history.js +23 -19
  81. package/lib/hooks.js +8 -8
  82. package/lib/html.js +94 -104
  83. package/lib/index.js +38 -27
  84. package/lib/listener/config.js +30 -23
  85. package/lib/listener/emptyRun.js +54 -0
  86. package/lib/listener/enhancedGlobalRetry.js +110 -0
  87. package/lib/listener/exit.js +16 -18
  88. package/lib/listener/globalRetry.js +70 -0
  89. package/lib/listener/globalTimeout.js +181 -0
  90. package/lib/listener/helpers.js +76 -51
  91. package/lib/listener/mocha.js +10 -11
  92. package/lib/listener/result.js +11 -0
  93. package/lib/listener/retryEnhancer.js +85 -0
  94. package/lib/listener/steps.js +71 -59
  95. package/lib/listener/store.js +20 -0
  96. package/lib/locator.js +214 -197
  97. package/lib/mocha/asyncWrapper.js +274 -0
  98. package/lib/mocha/bdd.js +167 -0
  99. package/lib/mocha/cli.js +341 -0
  100. package/lib/mocha/factory.js +163 -0
  101. package/lib/mocha/featureConfig.js +89 -0
  102. package/lib/mocha/gherkin.js +231 -0
  103. package/lib/mocha/hooks.js +121 -0
  104. package/lib/mocha/index.js +21 -0
  105. package/lib/mocha/inject.js +46 -0
  106. package/lib/{interfaces → mocha}/scenarioConfig.js +58 -34
  107. package/lib/mocha/suite.js +89 -0
  108. package/lib/mocha/test.js +184 -0
  109. package/lib/mocha/types.d.ts +42 -0
  110. package/lib/mocha/ui.js +242 -0
  111. package/lib/output.js +141 -71
  112. package/lib/parser.js +47 -44
  113. package/lib/pause.js +173 -145
  114. package/lib/plugin/analyze.js +403 -0
  115. package/lib/plugin/{autoLogin.js → auth.js} +178 -79
  116. package/lib/plugin/autoDelay.js +36 -40
  117. package/lib/plugin/coverage.js +131 -78
  118. package/lib/plugin/customLocator.js +22 -21
  119. package/lib/plugin/customReporter.js +53 -0
  120. package/lib/plugin/enhancedRetryFailedStep.js +99 -0
  121. package/lib/plugin/heal.js +101 -110
  122. package/lib/plugin/htmlReporter.js +3648 -0
  123. package/lib/plugin/pageInfo.js +140 -0
  124. package/lib/plugin/pauseOnFail.js +12 -11
  125. package/lib/plugin/retryFailedStep.js +82 -47
  126. package/lib/plugin/screenshotOnFail.js +111 -92
  127. package/lib/plugin/stepByStepReport.js +159 -101
  128. package/lib/plugin/stepTimeout.js +20 -25
  129. package/lib/plugin/subtitles.js +38 -38
  130. package/lib/recorder.js +193 -130
  131. package/lib/rerun.js +94 -49
  132. package/lib/result.js +238 -0
  133. package/lib/retryCoordinator.js +207 -0
  134. package/lib/secret.js +20 -18
  135. package/lib/session.js +95 -89
  136. package/lib/step/base.js +239 -0
  137. package/lib/step/comment.js +10 -0
  138. package/lib/step/config.js +50 -0
  139. package/lib/step/func.js +46 -0
  140. package/lib/step/helper.js +50 -0
  141. package/lib/step/meta.js +99 -0
  142. package/lib/step/record.js +74 -0
  143. package/lib/step/retry.js +11 -0
  144. package/lib/step/section.js +55 -0
  145. package/lib/step.js +18 -329
  146. package/lib/steps.js +54 -0
  147. package/lib/store.js +38 -7
  148. package/lib/template/heal.js +3 -12
  149. package/lib/template/prompts/generatePageObject.js +31 -0
  150. package/lib/template/prompts/healStep.js +13 -0
  151. package/lib/template/prompts/writeStep.js +9 -0
  152. package/lib/test-server.js +334 -0
  153. package/lib/timeout.js +60 -0
  154. package/lib/transform.js +8 -8
  155. package/lib/translation.js +34 -21
  156. package/lib/utils/mask_data.js +47 -0
  157. package/lib/utils.js +411 -228
  158. package/lib/workerStorage.js +37 -34
  159. package/lib/workers.js +532 -296
  160. package/package.json +115 -95
  161. package/translations/de-DE.js +5 -3
  162. package/translations/fr-FR.js +5 -4
  163. package/translations/index.js +22 -12
  164. package/translations/it-IT.js +4 -3
  165. package/translations/ja-JP.js +4 -3
  166. package/translations/nl-NL.js +76 -0
  167. package/translations/pl-PL.js +4 -3
  168. package/translations/pt-BR.js +4 -3
  169. package/translations/ru-RU.js +4 -3
  170. package/translations/utils.js +10 -0
  171. package/translations/zh-CN.js +4 -3
  172. package/translations/zh-TW.js +4 -3
  173. package/typings/index.d.ts +546 -185
  174. package/typings/promiseBasedTypes.d.ts +150 -879
  175. package/typings/types.d.ts +547 -996
  176. package/lib/cli.js +0 -249
  177. package/lib/dirname.js +0 -5
  178. package/lib/helper/Expect.js +0 -425
  179. package/lib/helper/ExpectHelper.js +0 -399
  180. package/lib/helper/MockServer.js +0 -223
  181. package/lib/helper/Nightmare.js +0 -1411
  182. package/lib/helper/Protractor.js +0 -1835
  183. package/lib/helper/SoftExpectHelper.js +0 -381
  184. package/lib/helper/TestCafe.js +0 -1410
  185. package/lib/helper/clientscripts/nightmare.js +0 -213
  186. package/lib/helper/testcafe/testControllerHolder.js +0 -42
  187. package/lib/helper/testcafe/testcafe-utils.js +0 -63
  188. package/lib/interfaces/bdd.js +0 -98
  189. package/lib/interfaces/featureConfig.js +0 -69
  190. package/lib/interfaces/gherkin.js +0 -195
  191. package/lib/listener/artifacts.js +0 -19
  192. package/lib/listener/retry.js +0 -68
  193. package/lib/listener/timeout.js +0 -109
  194. package/lib/mochaFactory.js +0 -110
  195. package/lib/plugin/allure.js +0 -15
  196. package/lib/plugin/commentStep.js +0 -136
  197. package/lib/plugin/debugErrors.js +0 -67
  198. package/lib/plugin/eachElement.js +0 -127
  199. package/lib/plugin/fakerTransform.js +0 -49
  200. package/lib/plugin/retryTo.js +0 -121
  201. package/lib/plugin/selenoid.js +0 -371
  202. package/lib/plugin/standardActingHelpers.js +0 -9
  203. package/lib/plugin/tryTo.js +0 -105
  204. package/lib/plugin/wdio.js +0 -246
  205. package/lib/scenario.js +0 -222
  206. package/lib/ui.js +0 -238
  207. package/lib/within.js +0 -70
package/bin/codecept.js CHANGED
@@ -1,26 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { Command } from 'commander';
3
- import { version } from '../lib/codecept.js';
4
- import * as outputLib from '../lib/output.js';
5
- import { printError } from '../lib/command/utils.js';
6
- import * as init from '../lib/command/init.js';
7
- import * as configMigrate from '../lib/command/configMigrate.js';
8
- import * as interactive from '../lib/command/interactive.js';
9
- import * as definitions from '../lib/command/definitions.js';
10
- import * as list from '../lib/command/list.js';
11
- import * as gherkinInit from '../lib/command/gherkin/init.js';
12
- import * as gherkinSteps from '../lib/command/gherkin/steps.js';
13
- import * as gherkinSnippets from '../lib/command/gherkin/snippets.js';
14
- import * as generate from '../lib/command/generate.js';
15
- import * as run from '../lib/command/run.js';
16
- import * as runWorkers from '../lib/command/run-workers.js';
17
- import * as runMultiple from '../lib/command/run-multiple.js';
18
- import { runRerun } from '../lib/command/run-rerun.js';
19
- import * as dryRun from '../lib/command/dryRun.js';
20
- import * as info from '../lib/command/info.js';
21
- import { heal } from "../lib/command/generate.js";
22
-
23
- const program = new Command();
2
+ import { Command } from 'commander'
3
+ const program = new Command()
4
+ import Codecept from '../lib/codecept.js'
5
+ import output from '../lib/output.js'
6
+ const { print, error } = output
7
+ import { printError } from '../lib/command/utils.js'
24
8
 
25
9
  const commandFlags = {
26
10
  ai: {
@@ -47,104 +31,124 @@ const commandFlags = {
47
31
  flag: '--steps',
48
32
  description: 'show step-by-step execution',
49
33
  },
50
- };
51
-
52
- const errorHandler = (fn) => async (...args) => {
53
- try {
54
- await fn.default(...args);
55
- } catch (e) {
56
- printError(e);
57
- process.exitCode = 1;
34
+ }
35
+
36
+ const errorHandler =
37
+ fn =>
38
+ async (...args) => {
39
+ try {
40
+ await fn(...args)
41
+ } catch (e) {
42
+ printError(e)
43
+ process.exitCode = 1
44
+ }
58
45
  }
59
- };
46
+
47
+ const dynamicImport = async modulePath => {
48
+ const module = await import(modulePath)
49
+ return module.default || module
50
+ }
51
+
52
+ const commandHandler = modulePath =>
53
+ errorHandler(async (...args) => {
54
+ const handler = await dynamicImport(modulePath)
55
+ return handler(...args)
56
+ })
57
+
58
+ const commandHandlerWithProperty = (modulePath, property) =>
59
+ errorHandler(async (...args) => {
60
+ const module = await dynamicImport(modulePath)
61
+ return module[property](...args)
62
+ })
60
63
 
61
64
  if (process.versions.node && process.versions.node.split('.') && process.versions.node.split('.')[0] < 12) {
62
- outputLib.output.output.error('NodeJS >= 12 is required to run.');
63
- outputLib.print();
64
- outputLib.print('Please upgrade your NodeJS engine');
65
- outputLib.print(`Current NodeJS version: ${process.version}`);
66
- process.exit(1);
65
+ error('NodeJS >= 12 is required to run.')
66
+ print()
67
+ print('Please upgrade your NodeJS engine')
68
+ print(`Current NodeJS version: ${process.version}`)
69
+ process.exit(1)
67
70
  }
68
71
 
69
- program.usage('<command> [options]');
70
- program.version(version());
72
+ program.usage('<command> [options]')
73
+ program.version(Codecept.version())
74
+
75
+ program.command('init [path]').description('Creates dummy config in current dir or [path]').action(commandHandler('../lib/command/init.js'))
71
76
 
72
- program.command('init [path]')
73
- .description('Creates dummy config in current dir or [path]')
74
- .action(errorHandler(init));
77
+ program
78
+ .command('check')
79
+ .option(commandFlags.config.flag, commandFlags.config.description)
80
+ .description('Checks configuration and environment before running tests')
81
+ .option('-t, --timeout [ms]', 'timeout for checks in ms, 50000 by default')
82
+ .action(commandHandler('../lib/command/check.js'))
75
83
 
76
- program.command('migrate [path]')
77
- .description('Migrate json config to js config in current dir or [path]')
78
- .action(errorHandler(configMigrate));
84
+ program.command('migrate [path]').description('Migrate json config to js config in current dir or [path]').action(commandHandler('../lib/command/configMigrate.js'))
79
85
 
80
- program.command('shell [path]')
86
+ program
87
+ .command('shell [path]')
81
88
  .alias('sh')
82
89
  .description('Interactive shell')
83
90
  .option(commandFlags.verbose.flag, commandFlags.verbose.description)
84
91
  .option(commandFlags.profile.flag, commandFlags.profile.description)
85
92
  .option(commandFlags.ai.flag, commandFlags.ai.description)
86
93
  .option(commandFlags.config.flag, commandFlags.config.description)
87
- .action(errorHandler(interactive));
94
+ .action(commandHandler('../lib/command/interactive.js'))
88
95
 
89
- program.command('list [path]')
90
- .alias('l')
91
- .description('List all actions for I.')
92
- .action(errorHandler(list));
96
+ program.command('list [path]').alias('l').description('List all actions for I.').action(commandHandler('../lib/command/list.js'))
93
97
 
94
- program.command('def [path]')
98
+ program
99
+ .command('def [path]')
95
100
  .description('Generates TypeScript definitions for all I actions.')
96
101
  .option(commandFlags.config.flag, commandFlags.config.description)
97
102
  .option('-o, --output [folder]', 'target folder to paste definitions')
98
- .action(errorHandler(definitions));
103
+ .action(commandHandler('../lib/command/definitions.js'))
99
104
 
100
- program.command('gherkin:init [path]')
105
+ program
106
+ .command('gherkin:init [path]')
101
107
  .alias('bdd:init')
102
108
  .description('Prepare CodeceptJS to run feature files.')
103
109
  .option(commandFlags.config.flag, commandFlags.config.description)
104
- .action(errorHandler(gherkinInit));
110
+ .action(commandHandler('../lib/command/gherkin/init.js'))
105
111
 
106
- program.command('gherkin:steps [path]')
112
+ program
113
+ .command('gherkin:steps [path]')
107
114
  .alias('bdd:steps')
108
115
  .description('Prints all defined gherkin steps.')
109
116
  .option(commandFlags.config.flag, commandFlags.config.description)
110
- .action(errorHandler(gherkinSteps));
117
+ .action(commandHandler('../lib/command/gherkin/steps.js'))
111
118
 
112
- program.command('gherkin:snippets [path]')
119
+ program
120
+ .command('gherkin:snippets [path]')
113
121
  .alias('bdd:snippets')
114
122
  .description('Generate step definitions from steps.')
115
123
  .option('--dry-run', "don't save snippets to file")
116
124
  .option(commandFlags.config.flag, commandFlags.config.description)
117
125
  .option('--feature [file]', 'feature files(s) to scan')
118
126
  .option('--path [file]', 'file in which to place the new snippets')
119
- .action(errorHandler(gherkinSnippets));
127
+ .action(commandHandler('../lib/command/gherkin/snippets.js'))
120
128
 
121
- program.command('generate:test [path]')
122
- .alias('gt')
123
- .description('Generates an empty test')
124
- .action(errorHandler(generate.test));
129
+ program.command('generate:test [path]').alias('gt').description('Generates an empty test').action(commandHandlerWithProperty('../lib/command/generate.js', 'test'))
125
130
 
126
- program.command('generate:pageobject [path]')
127
- .alias('gpo')
128
- .description('Generates an empty page object')
129
- .action(errorHandler(generate.pageObject));
131
+ program.command('generate:pageobject [path]').alias('gpo').description('Generates an empty page object').action(commandHandlerWithProperty('../lib/command/generate.js', 'pageObject'))
130
132
 
131
- program.command('generate:object [path]')
133
+ program
134
+ .command('generate:object [path]')
132
135
  .alias('go')
133
136
  .option('--type, -t [kind]', 'type of object to be created')
134
137
  .description('Generates an empty support object (page/step/fragment)')
135
- .action(errorHandler(generate.pageObject));
138
+ .action(commandHandlerWithProperty('../lib/command/generate.js', 'pageObject'))
139
+
140
+ program.command('generate:helper [path]').alias('gh').description('Generates a new helper').action(commandHandlerWithProperty('../lib/command/generate.js', 'helper'))
136
141
 
137
- program.command('generate:helper [path]')
138
- .alias('gh')
139
- .description('Generates a new helper')
140
- .action(errorHandler(generate.helper));
142
+ program.command('generate:heal [path]').alias('gr').description('Generates basic heal recipes').action(commandHandlerWithProperty('../lib/command/generate.js', 'heal'))
141
143
 
142
- program.command('generate:heal [path]')
143
- .alias('gr')
144
- .description('Generates basic heal recipes')
145
- .action(errorHandler(heal));
144
+ program
145
+ .command('generate:prompt <promptName> [path]')
146
+ .alias('gp')
147
+ .description('Generates AI prompt template (writeStep, healStep, generatePageObject)')
148
+ .action(commandHandlerWithProperty('../lib/command/generate.js', 'prompt'))
146
149
 
147
- program.command('run [test]')
150
+ program
151
+ .command('run [test]')
148
152
  .description('Executes tests')
149
153
 
150
154
  // codecept-only options
@@ -159,6 +163,8 @@ program.command('run [test]')
159
163
  .option('--tests', 'run only JS test files and skip features')
160
164
  .option('--no-timeouts', 'disable all timeouts')
161
165
  .option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
166
+ .option('--shuffle', 'Shuffle the order in which test files run')
167
+ .option('--shard <index/total>', 'run only a fraction of tests (e.g., --shard 1/4)')
162
168
 
163
169
  // mocha options
164
170
  .option('--colors', 'force enabling of colors')
@@ -180,15 +186,17 @@ program.command('run [test]')
180
186
  .option('--recursive', 'include sub directories')
181
187
  .option('--trace', 'trace function calls')
182
188
  .option('--child <string>', 'option for child processes')
183
- .action(errorHandler(run));
189
+ .action(commandHandler('../lib/command/run.js'))
184
190
 
185
- program.command('run-workers <workers> [selectedRuns...]')
191
+ program
192
+ .command('run-workers <workers> [selectedRuns...]')
186
193
  .description('Executes tests in workers')
187
194
  .option(commandFlags.config.flag, commandFlags.config.description)
188
195
  .option('-g, --grep <pattern>', 'only run tests matching <pattern>')
189
196
  .option('-i, --invert', 'inverts --grep matches')
190
197
  .option('-o, --override [value]', 'override current config options')
191
198
  .option('--suites', 'parallel execution of suites not single tests')
199
+ .option('--by <strategy>', 'test distribution strategy: "test" (pre-assign individual tests), "suite" (pre-assign test suites), or "pool" (dynamic distribution for optimal load balancing, recommended)')
192
200
  .option(commandFlags.debug.flag, commandFlags.debug.description)
193
201
  .option(commandFlags.verbose.flag, commandFlags.verbose.description)
194
202
  .option('--features', 'run only *.feature files and skip tests')
@@ -198,9 +206,10 @@ program.command('run-workers <workers> [selectedRuns...]')
198
206
  .option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
199
207
  .option('-O, --reporter-options <k=v,k2=v2,...>', 'reporter-specific options')
200
208
  .option('-R, --reporter <name>', 'specify the reporter to use')
201
- .action(errorHandler(runWorkers));
209
+ .action(commandHandler('../lib/command/run-workers.js'))
202
210
 
203
- program.command('run-multiple [suites...]')
211
+ program
212
+ .command('run-multiple [suites...]')
204
213
  .description('Executes tests multiple')
205
214
  .option(commandFlags.config.flag, commandFlags.config.description)
206
215
  .option(commandFlags.profile.flag, commandFlags.profile.description)
@@ -223,14 +232,12 @@ program.command('run-multiple [suites...]')
223
232
  // mocha options
224
233
  .option('--colors', 'force enabling of colors')
225
234
 
226
- .action(errorHandler(runMultiple));
235
+ .action(commandHandler('../lib/command/run-multiple.js'))
227
236
 
228
- program.command('info [path]')
229
- .description('Print debugging information concerning the local environment')
230
- .option('-c, --config', 'your config file path')
231
- .action(errorHandler(info));
237
+ program.command('info [path]').description('Print debugging information concerning the local environment').option('-c, --config', 'your config file path').action(commandHandler('../lib/command/info.js'))
232
238
 
233
- program.command('dry-run [test]')
239
+ program
240
+ .command('dry-run [test]')
234
241
  .description('Prints step-by-step scenario for a test without actually running it')
235
242
  .option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
236
243
  .option('--bootstrap', 'enable bootstrap & teardown scripts for dry-run')
@@ -244,9 +251,10 @@ program.command('dry-run [test]')
244
251
  .option(commandFlags.steps.flag, commandFlags.steps.description)
245
252
  .option(commandFlags.verbose.flag, commandFlags.verbose.description)
246
253
  .option(commandFlags.debug.flag, commandFlags.debug.description)
247
- .action(errorHandler(dryRun));
254
+ .action(commandHandler('../lib/command/dryRun.js'))
248
255
 
249
- program.command('run-rerun [test]')
256
+ program
257
+ .command('run-rerun [test]')
250
258
  .description('Executes tests in more than one test suite run')
251
259
 
252
260
  // codecept-only options
@@ -281,15 +289,18 @@ program.command('run-rerun [test]')
281
289
  .option('--trace', 'trace function calls')
282
290
  .option('--child <string>', 'option for child processes')
283
291
 
284
- .action(runRerun);
292
+ .action(async (...args) => {
293
+ const runRerun = await dynamicImport('../lib/command/run-rerun.js')
294
+ return runRerun(...args)
295
+ })
285
296
 
286
- program.on('command:*', (cmd) => {
287
- console.log(`\nUnknown command ${cmd}\n`);
288
- program.outputHelp();
289
- });
297
+ program.on('command:*', cmd => {
298
+ console.log(`\nUnknown command ${cmd}\n`)
299
+ program.outputHelp()
300
+ })
290
301
 
291
302
  if (process.argv.length <= 2) {
292
- program.outputHelp();
303
+ program.outputHelp()
293
304
  } else {
294
- program.parse(process.argv);
305
+ program.parse(process.argv)
295
306
  }
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Standalone test server script to replace json-server
5
+ */
6
+
7
+ import path from 'path'
8
+ import { fileURLToPath } from 'url'
9
+ import { dirname } from 'path'
10
+ import TestServer from '../lib/test-server.js'
11
+
12
+ const __filename = fileURLToPath(import.meta.url)
13
+ const __dirname = dirname(__filename)
14
+
15
+ // Parse command line arguments
16
+ const args = process.argv.slice(2)
17
+ let dbFile = path.join(__dirname, '../test/data/rest/db.json')
18
+ let port = 8010
19
+ let host = '0.0.0.0'
20
+ let readOnly = false
21
+
22
+ // Simple argument parsing
23
+ for (let i = 0; i < args.length; i++) {
24
+ const arg = args[i]
25
+
26
+ if (arg === '-p' || arg === '--port') {
27
+ port = parseInt(args[++i])
28
+ } else if (arg === '--host') {
29
+ host = args[++i]
30
+ } else if (arg === '--read-only' || arg === '-r') {
31
+ readOnly = true
32
+ } else if (!arg.startsWith('-')) {
33
+ dbFile = path.resolve(arg)
34
+ }
35
+ }
36
+
37
+ // Create and start server
38
+ const server = new TestServer({ port, host, dbFile, readOnly })
39
+
40
+ console.log(`Starting test server with db file: ${dbFile}`)
41
+ if (readOnly) {
42
+ console.log('Running in READ-ONLY mode - changes will not be persisted to disk')
43
+ }
44
+
45
+ server
46
+ .start()
47
+ .then(() => {
48
+ console.log(`Test server is ready and listening on http://${host}:${port}`)
49
+ })
50
+ .catch(err => {
51
+ console.error('Failed to start test server:', err)
52
+ process.exit(1)
53
+ })
54
+
55
+ // Graceful shutdown
56
+ process.on('SIGINT', () => {
57
+ console.log('\nShutting down test server...')
58
+ server.stop().then(() => process.exit(0))
59
+ })
60
+
61
+ process.on('SIGTERM', () => {
62
+ console.log('\nShutting down test server...')
63
+ server.stop().then(() => process.exit(0))
64
+ })
@@ -3,7 +3,7 @@ if none provided clears all cookies.
3
3
 
4
4
  ```js
5
5
  I.clearCookie();
6
- I.clearCookie('test'); // Playwright currently doesn't support clear a particular cookie name
6
+ I.clearCookie('test');
7
7
  ```
8
8
 
9
9
  @param {?string} [cookie=null] (optional, `null` by default) cookie name
@@ -3,9 +3,13 @@ If a fuzzy locator is given, the page will be searched for a button, link, or im
3
3
  For buttons, the "value" attribute, "name" attribute, and inner text are searched. For links, the link text is searched.
4
4
  For images, the "alt" attribute and inner text of any parent links are searched.
5
5
 
6
+ If no locator is provided, defaults to clicking the body element (`'//body'`).
7
+
6
8
  The second parameter is a context (CSS or XPath locator) to narrow the search.
7
9
 
8
10
  ```js
11
+ // click body element (default)
12
+ I.click();
9
13
  // simple link
10
14
  I.click('Logout');
11
15
  // button of form
@@ -20,6 +24,6 @@ I.click('Logout', '#nav');
20
24
  I.click({css: 'nav a.login'});
21
25
  ```
22
26
 
23
- @param {CodeceptJS.LocatorOrString} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
27
+ @param {CodeceptJS.LocatorOrString} [locator='//body'] (optional, `'//body'` by default) clickable link or button located by text, or any element located by CSS|XPath|strict locator.
24
28
  @param {?CodeceptJS.LocatorOrString | null} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
25
29
  @returns {void} automatically synchronized promise through #recorder
package/lib/actor.js CHANGED
@@ -1,16 +1,18 @@
1
- import { Step, MetaStep } from './step.js';
2
- import container from './container.js';
3
- import { methodsOfObject } from './utils.js';
4
- import recorder from './recorder.js';
5
- import * as event from './event.js';
6
- import { store } from './store.js';
7
- import * as output from './output.js';
1
+ import Step, { MetaStep } from './step.js'
2
+ import recordStep from './step/record.js'
3
+ import retryStep from './step/retry.js'
4
+ import { methodsOfObject } from './utils.js'
5
+ import { TIMEOUT_ORDER } from './timeout.js'
6
+ import event from './event.js'
7
+ import store from './store.js'
8
+ import output from './output.js'
9
+ import Container from './container.js'
8
10
 
9
11
  /**
10
12
  * @interface
11
13
  * @alias ActorStatic
12
14
  */
13
- export class Actor {
15
+ class Actor {
14
16
  /**
15
17
  * Print the comment on log. Also, adding a step in the `Test.steps` object
16
18
  * @param {string} msg
@@ -20,13 +22,13 @@ export class Actor {
20
22
  * ⚠️ returns a promise which is synchronized internally by recorder
21
23
  */
22
24
  async say(msg, color = 'cyan') {
23
- const step = new Step('say', 'say');
24
- step.status = 'passed';
25
+ const step = new Step('say', 'say')
26
+ step.status = 'passed'
25
27
  return recordStep(step, [msg]).then(() => {
26
28
  // this is backward compatibility as this event may be used somewhere
27
- event.emit(event.step.comment, msg);
28
- output.say(msg, `${color}`);
29
- });
29
+ event.emit(event.step.comment, msg)
30
+ output.say(msg, `${color}`)
31
+ })
30
32
  }
31
33
 
32
34
  /**
@@ -37,14 +39,16 @@ export class Actor {
37
39
  * @inner
38
40
  */
39
41
  limitTime(timeout) {
40
- if (!store.timeouts) return this;
42
+ if (!store.timeouts) return this
41
43
 
42
- event.dispatcher.prependOnceListener(event.step.before, (step) => {
43
- output.output.log(`Timeout to ${step}: ${timeout}s`);
44
- step.setTimeout(timeout * 1000, Step.TIMEOUT_ORDER.codeLimitTime);
45
- });
44
+ console.log('I.limitTime() is deprecated, use step.timeout() instead')
46
45
 
47
- return this;
46
+ event.dispatcher.prependOnceListener(event.step.before, step => {
47
+ output.log(`Timeout to ${step}: ${timeout}s`)
48
+ step.setTimeout(timeout * 1000, TIMEOUT_ORDER.codeLimitTime)
49
+ })
50
+
51
+ return this
48
52
  }
49
53
 
50
54
  /**
@@ -54,11 +58,9 @@ export class Actor {
54
58
  * @inner
55
59
  */
56
60
  retry(opts) {
57
- if (opts === undefined) opts = 1;
58
- recorder.retry(opts);
59
- // remove retry once the step passed
60
- recorder.add(() => event.dispatcher.once(event.step.finished, () => recorder.retries.pop()));
61
- return this;
61
+ console.log('I.retry() is deprecated, use step.retry() instead')
62
+ retryStep(opts)
63
+ return this
62
64
  }
63
65
  }
64
66
 
@@ -68,94 +70,60 @@ export class Actor {
68
70
  * Wraps helper methods into promises.
69
71
  * @ignore
70
72
  */
71
- // eslint-disable-next-line import/prefer-default-export
72
- export function actor(obj = {}) {
73
- if (!store.actor) {
74
- store.actor = new Actor();
75
- }
76
- const actor = store.actor;
77
-
78
- const translation = container.translation();
79
-
80
- if (Object.keys(obj).length > 0) {
81
- Object.keys(obj)
82
- .forEach(action => {
83
- const actionAlias = translation.actionAliasFor(action);
84
-
85
- const currentMethod = obj[action];
86
- const ms = new MetaStep('I', action);
87
- if (translation.loaded) {
88
- ms.name = actionAlias;
89
- ms.actor = translation.I;
90
- }
91
- ms.setContext(actor);
92
- actor[action] = actor[actionAlias] = ms.run.bind(ms, currentMethod);
93
- });
73
+ export default function (obj = {}, container) {
74
+ // Use global container if none provided
75
+ if (!container) {
76
+ container = Container
94
77
  }
78
+
79
+ const actor = container.actor() || new Actor()
95
80
 
96
- const helpers = container.helpers();
81
+ // load all helpers once container initialized
82
+ container.started(() => {
83
+ const translation = container.translation()
84
+ const helpers = container.helpers()
97
85
 
98
- // add methods from enabled helpers
99
- Object.values(helpers)
100
- .forEach((helper) => {
86
+ // add methods from enabled helpers
87
+ Object.values(helpers).forEach(helper => {
101
88
  methodsOfObject(helper, 'Helper')
102
89
  .filter(method => method !== 'constructor' && method[0] !== '_')
103
- .forEach((action) => {
104
- const actionAlias = translation.actionAliasFor(action);
90
+ .forEach(action => {
91
+ const actionAlias = translation.actionAliasFor(action)
105
92
  if (!actor[action]) {
106
93
  actor[action] = actor[actionAlias] = function () {
107
- const step = new Step(helper, action);
94
+ const step = new Step(helper, action)
108
95
  if (translation.loaded) {
109
- step.name = actionAlias;
110
- step.actor = translation.I;
96
+ step.name = actionAlias
97
+ step.actor = translation.I
111
98
  }
112
99
  // add methods to promise chain
113
- return recordStep(step, Array.from(arguments));
114
- };
100
+ return recordStep(step, Array.from(arguments))
101
+ }
115
102
  }
116
- });
117
- });
118
-
119
- return actor;
120
- }
121
-
122
- export function recordStep(step, args) {
123
- step.status = 'queued';
124
- step.setArguments(args);
125
-
126
- // run async before step hooks
127
- event.emit(event.step.before, step);
128
-
129
- const task = `${step.name}: ${step.humanizeArgs()}`;
130
- let val;
131
-
132
- // run step inside promise
133
- recorder.add(task, () => {
134
- if (!step.startTime) { // step can be retries
135
- event.emit(event.step.started, step);
136
- step.startTime = Date.now();
137
- }
138
- return val = step.run(...args);
139
- }, false, undefined, step.getTimeout());
140
-
141
- event.emit(event.step.after, step);
142
-
143
- recorder.add('step passed', () => {
144
- step.endTime = Date.now();
145
- event.emit(event.step.passed, step, val);
146
- event.emit(event.step.finished, step);
147
- });
148
-
149
- recorder.catchWithoutStop((err) => {
150
- step.status = 'failed';
151
- step.endTime = Date.now();
152
- event.emit(event.step.failed, step);
153
- event.emit(event.step.finished, step);
154
- throw err;
155
- });
156
-
157
- recorder.add('return result', () => val);
158
- // run async after step hooks
159
-
160
- return recorder.promise();
103
+ })
104
+ })
105
+
106
+ // add translated custom steps from actor
107
+ Object.keys(obj).forEach(key => {
108
+ const actionAlias = translation.actionAliasFor(key)
109
+ if (!actor[actionAlias]) {
110
+ actor[actionAlias] = actor[key]
111
+ }
112
+ })
113
+
114
+ container.append({
115
+ support: {
116
+ I: actor,
117
+ },
118
+ })
119
+ })
120
+ // store.actor = actor;
121
+ // add custom steps from actor
122
+ Object.keys(obj).forEach(key => {
123
+ const ms = new MetaStep('I', key)
124
+ ms.setContext(actor)
125
+ actor[key] = ms.run.bind(ms, obj[key])
126
+ })
127
+
128
+ return actor
161
129
  }