codeceptjs 2.3.4 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +28 -6
  3. package/bin/codecept.js +42 -0
  4. package/docs/advanced.md +45 -1
  5. package/docs/angular.md +3 -3
  6. package/docs/basics.md +162 -118
  7. package/docs/bdd.md +30 -5
  8. package/docs/best.md +8 -6
  9. package/docs/books.md +6 -1
  10. package/docs/build/Appium.js +95 -85
  11. package/docs/build/FileSystem.js +48 -3
  12. package/docs/build/GraphQL.js +3 -2
  13. package/docs/build/GraphQLDataFactory.js +1 -0
  14. package/docs/build/Mochawesome.js +3 -2
  15. package/docs/build/MockRequest.js +23 -5
  16. package/docs/build/Nightmare.js +87 -128
  17. package/docs/build/Protractor.js +107 -155
  18. package/docs/build/Puppeteer.js +190 -174
  19. package/docs/build/REST.js +13 -9
  20. package/docs/build/SeleniumWebdriver.js +0 -17
  21. package/docs/build/TestCafe.js +164 -158
  22. package/docs/build/WebDriver.js +236 -211
  23. package/docs/build/WebDriverIO.js +218 -187
  24. package/docs/changelog.md +57 -1
  25. package/docs/commands.md +41 -2
  26. package/docs/community-helpers.md +12 -1
  27. package/docs/configuration.md +5 -2
  28. package/docs/continuous-integration.md +22 -0
  29. package/docs/{helpers.md → custom-helpers.md} +16 -10
  30. package/docs/data.md +7 -6
  31. package/docs/detox.md +6 -6
  32. package/docs/email.md +4 -2
  33. package/docs/examples.md +22 -3
  34. package/docs/helpers/ApiDataFactory.md +15 -13
  35. package/docs/helpers/Appium.md +1011 -468
  36. package/docs/helpers/Detox.md +33 -26
  37. package/docs/helpers/FileSystem.md +43 -13
  38. package/docs/helpers/GraphQL.md +17 -15
  39. package/docs/helpers/GraphQLDataFactory.md +15 -13
  40. package/docs/helpers/Mochawesome.md +3 -1
  41. package/docs/helpers/MockRequest.md +37 -19
  42. package/docs/helpers/Nightmare.md +129 -240
  43. package/docs/helpers/Polly.md +1 -1
  44. package/docs/helpers/Protractor.md +157 -298
  45. package/docs/helpers/Puppeteer.md +216 -335
  46. package/docs/helpers/REST.md +29 -24
  47. package/docs/helpers/TestCafe.md +137 -235
  48. package/docs/helpers/WebDriver.md +250 -347
  49. package/docs/hooks.md +14 -10
  50. package/docs/index.md +112 -0
  51. package/docs/installation.md +3 -1
  52. package/docs/locators.md +19 -8
  53. package/docs/mobile-react-native-locators.md +2 -2
  54. package/docs/mobile.md +5 -3
  55. package/docs/nightmare.md +2 -1
  56. package/docs/pageobjects.md +4 -2
  57. package/docs/parallel.md +4 -2
  58. package/docs/plugins.md +41 -15
  59. package/docs/puppeteer.md +8 -6
  60. package/docs/quickstart.md +130 -0
  61. package/docs/react.md +4 -2
  62. package/docs/reports.md +6 -4
  63. package/docs/testcafe.md +10 -8
  64. package/docs/translation.md +4 -2
  65. package/docs/ui.md +56 -0
  66. package/docs/videos.md +11 -2
  67. package/docs/visual.md +7 -5
  68. package/docs/vue.md +121 -0
  69. package/docs/webapi/appendField.mustache +1 -1
  70. package/docs/webapi/attachFile.mustache +1 -1
  71. package/docs/webapi/checkOption.mustache +2 -2
  72. package/docs/webapi/clearCookie.mustache +1 -1
  73. package/docs/webapi/click.mustache +2 -2
  74. package/docs/webapi/clickLink.mustache +2 -2
  75. package/docs/webapi/dontSee.mustache +1 -2
  76. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
  77. package/docs/webapi/dontSeeElement.mustache +1 -1
  78. package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
  79. package/docs/webapi/dontSeeInField.mustache +1 -1
  80. package/docs/webapi/doubleClick.mustache +2 -2
  81. package/docs/webapi/downloadFile.mustache +1 -1
  82. package/docs/webapi/dragSlider.mustache +1 -1
  83. package/docs/webapi/executeAsyncScript.mustache +2 -1
  84. package/docs/webapi/executeScript.mustache +2 -1
  85. package/docs/webapi/fillField.mustache +1 -1
  86. package/docs/webapi/grabAttributeFrom.mustache +1 -1
  87. package/docs/webapi/grabBrowserLogs.mustache +1 -1
  88. package/docs/webapi/grabCookie.mustache +2 -2
  89. package/docs/webapi/grabCssPropertyFrom.mustache +1 -1
  90. package/docs/webapi/grabHTMLFrom.mustache +1 -1
  91. package/docs/webapi/grabNumberOfVisibleElements.mustache +1 -1
  92. package/docs/webapi/grabPageScrollPosition.mustache +1 -1
  93. package/docs/webapi/grabTextFrom.mustache +2 -2
  94. package/docs/webapi/grabValueFrom.mustache +1 -1
  95. package/docs/webapi/moveCursorTo.mustache +3 -3
  96. package/docs/webapi/pressKey.mustache +1 -1
  97. package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
  98. package/docs/webapi/rightClick.mustache +2 -2
  99. package/docs/webapi/saveScreenshot.mustache +1 -1
  100. package/docs/webapi/scrollIntoView.mustache +10 -0
  101. package/docs/webapi/scrollTo.mustache +3 -3
  102. package/docs/webapi/see.mustache +1 -1
  103. package/docs/webapi/seeAttributesOnElements.mustache +1 -1
  104. package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
  105. package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
  106. package/docs/webapi/seeElement.mustache +1 -1
  107. package/docs/webapi/seeElementInDOM.mustache +1 -1
  108. package/docs/webapi/seeInField.mustache +1 -1
  109. package/docs/webapi/seeNumberOfElements.mustache +1 -1
  110. package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
  111. package/docs/webapi/seeTextEquals.mustache +8 -0
  112. package/docs/webapi/selectOption.mustache +2 -2
  113. package/docs/webapi/switchTo.mustache +1 -1
  114. package/docs/webapi/uncheckOption.mustache +2 -2
  115. package/docs/webapi/waitForClickable.mustache +10 -0
  116. package/docs/webapi/waitForDetached.mustache +2 -2
  117. package/docs/webapi/waitForElement.mustache +2 -2
  118. package/docs/webapi/waitForEnabled.mustache +2 -2
  119. package/docs/webapi/waitForFunction.mustache +2 -2
  120. package/docs/webapi/waitForInvisible.mustache +2 -2
  121. package/docs/webapi/waitForText.mustache +2 -2
  122. package/docs/webapi/waitForValue.mustache +1 -1
  123. package/docs/webapi/waitForVisible.mustache +2 -2
  124. package/docs/webapi/waitInUrl.mustache +1 -1
  125. package/docs/webapi/waitNumberOfVisibleElements.mustache +2 -2
  126. package/docs/webapi/waitToHide.mustache +2 -2
  127. package/docs/webapi/waitUntil.mustache +3 -2
  128. package/docs/webapi/waitUrlEquals.mustache +1 -1
  129. package/docs/webdriver.md +20 -18
  130. package/docs/wiki/.git/FETCH_HEAD +1 -0
  131. package/docs/wiki/.git/HEAD +1 -0
  132. package/docs/wiki/.git/ORIG_HEAD +1 -0
  133. package/docs/wiki/.git/config +11 -0
  134. package/docs/wiki/.git/description +1 -0
  135. package/docs/wiki/.git/hooks/applypatch-msg.sample +15 -0
  136. package/docs/wiki/.git/hooks/commit-msg.sample +24 -0
  137. package/docs/wiki/.git/hooks/fsmonitor-watchman.sample +114 -0
  138. package/docs/wiki/.git/hooks/post-update.sample +8 -0
  139. package/docs/wiki/.git/hooks/pre-applypatch.sample +14 -0
  140. package/docs/wiki/.git/hooks/pre-commit.sample +49 -0
  141. package/docs/wiki/.git/hooks/pre-push.sample +53 -0
  142. package/docs/wiki/.git/hooks/pre-rebase.sample +169 -0
  143. package/docs/wiki/.git/hooks/pre-receive.sample +24 -0
  144. package/docs/wiki/.git/hooks/prepare-commit-msg.sample +42 -0
  145. package/docs/wiki/.git/hooks/update.sample +128 -0
  146. package/docs/wiki/.git/index +0 -0
  147. package/docs/wiki/.git/info/exclude +6 -0
  148. package/docs/wiki/.git/logs/HEAD +4 -0
  149. package/docs/wiki/.git/logs/refs/heads/master +4 -0
  150. package/docs/wiki/.git/logs/refs/remotes/origin/HEAD +1 -0
  151. package/docs/wiki/.git/logs/refs/remotes/origin/master +3 -0
  152. package/docs/wiki/.git/objects/00/d216b0774d15db2d0a2a0d4ce249b5251acc55 +3 -0
  153. package/docs/wiki/.git/objects/09/01d87c5241905fdfe3493cfe8f04df4a2685ea +0 -0
  154. package/docs/wiki/.git/objects/0d/bdd0c20c4deb6a8cc81dbbf32ecf8c09238983 +2 -0
  155. package/docs/wiki/.git/objects/1a/c29e4fa82422c52392f22f0f2b8d1a759535bf +0 -0
  156. package/docs/wiki/.git/objects/27/12f92898d3e8f68e229b6cda76570d6c66d781 +0 -0
  157. package/docs/wiki/.git/objects/2d/dbe22c257166b648928eeb9460ecfb71ba702d +0 -0
  158. package/docs/wiki/.git/objects/2f/c942ec3773efd2678d9ff98035c61fcded81a1 +0 -0
  159. package/docs/wiki/.git/objects/40/a2856342c67796b48911a256b764fb06888b94 +5 -0
  160. package/docs/wiki/.git/objects/47/53181844fc4dc563cf3aa5e80462243cb58d38 +0 -0
  161. package/docs/wiki/.git/objects/4e/24a95fb2e4f8ffef51f19b694451a205c06f10 +3 -0
  162. package/docs/wiki/.git/objects/73/31ebd96f3c7e08a9f63f05a25f939afa0d4de1 +0 -0
  163. package/docs/wiki/.git/objects/86/19cbb2289caa502e33fccf0ed14eecf6ba2ba0 +0 -0
  164. package/docs/wiki/.git/objects/a4/72f797d9d74b87c9f71a2b1539d75bb07d1e35 +0 -0
  165. package/docs/wiki/.git/objects/c9/9f3e4bd227d6b050b2e416f9876df49583dbf6 +0 -0
  166. package/docs/wiki/.git/objects/ca/e609b4ef3e0ef85fcbe0d68d1a58246584b915 +0 -0
  167. package/docs/wiki/.git/objects/d5/8386ca72f6d550548f3d71d74e3ac73d5ad488 +0 -0
  168. package/docs/wiki/.git/objects/d9/c6874a6de524bdafeb563a20d847f4fdd59a86 +0 -0
  169. package/docs/wiki/.git/objects/f1/c944675bb38b40ae553b0be36c14674c79af54 +0 -0
  170. package/docs/wiki/.git/objects/pack/pack-28da0fc7e6c08d4c5350717bfbb7b1c53e8198ad.idx +0 -0
  171. package/docs/wiki/.git/objects/pack/pack-28da0fc7e6c08d4c5350717bfbb7b1c53e8198ad.pack +0 -0
  172. package/docs/wiki/.git/packed-refs +2 -0
  173. package/docs/wiki/.git/refs/heads/master +1 -0
  174. package/docs/wiki/.git/refs/remotes/origin/HEAD +1 -0
  175. package/docs/wiki/.git/refs/remotes/origin/master +1 -0
  176. package/docs/wiki/Books-&-Posts.md +27 -0
  177. package/docs/wiki/Community-Helpers.md +41 -0
  178. package/docs/wiki/Examples.md +138 -0
  179. package/docs/wiki/Home.md +11 -0
  180. package/docs/wiki/Release-process.md +25 -0
  181. package/docs/wiki/Roadmap.md +23 -0
  182. package/docs/wiki/Videos.md +19 -0
  183. package/lib/actor.js +18 -1
  184. package/lib/assert/error.js +3 -3
  185. package/lib/codecept.js +9 -6
  186. package/lib/command/configMigrate.js +7 -6
  187. package/lib/command/definitions.js +98 -350
  188. package/lib/command/generate.js +22 -17
  189. package/lib/command/gherkin/init.js +2 -1
  190. package/lib/command/gherkin/snippets.js +6 -6
  191. package/lib/command/gherkin/steps.js +0 -1
  192. package/lib/command/info.js +40 -0
  193. package/lib/command/init.js +54 -41
  194. package/lib/command/run-multiple.js +5 -4
  195. package/lib/command/run-rerun.js +39 -0
  196. package/lib/command/run-workers.js +4 -6
  197. package/lib/command/run.js +8 -18
  198. package/lib/command/utils.js +23 -2
  199. package/lib/command/workers/runTests.js +1 -2
  200. package/lib/config.js +10 -4
  201. package/lib/container.js +31 -6
  202. package/lib/data/dataTableArgument.js +31 -0
  203. package/lib/data/table.js +4 -0
  204. package/lib/event.js +65 -1
  205. package/lib/helper/Appium.js +52 -38
  206. package/lib/helper/FileSystem.js +48 -3
  207. package/lib/helper/GraphQL.js +3 -2
  208. package/lib/helper/GraphQLDataFactory.js +1 -0
  209. package/lib/helper/Mochawesome.js +3 -2
  210. package/lib/helper/MockRequest.js +23 -5
  211. package/lib/helper/Nightmare.js +5 -6
  212. package/lib/helper/Protractor.js +7 -8
  213. package/lib/helper/Puppeteer.js +76 -20
  214. package/lib/helper/REST.js +13 -9
  215. package/lib/helper/SeleniumWebdriver.js +0 -17
  216. package/lib/helper/TestCafe.js +84 -36
  217. package/lib/helper/WebDriver.js +113 -59
  218. package/lib/helper/WebDriverIO.js +43 -59
  219. package/lib/helper/clientscripts/nightmare.js +66 -4
  220. package/lib/helper/scripts/isElementClickable.js +24 -0
  221. package/lib/helper.js +34 -10
  222. package/lib/history.js +1 -1
  223. package/lib/hooks.js +2 -1
  224. package/lib/index.js +19 -0
  225. package/lib/interfaces/bdd.js +4 -0
  226. package/lib/interfaces/featureConfig.js +10 -3
  227. package/lib/interfaces/gherkin.js +6 -2
  228. package/lib/interfaces/scenarioConfig.js +17 -6
  229. package/lib/listener/config.js +1 -1
  230. package/lib/listener/exit.js +6 -0
  231. package/lib/listener/steps.js +0 -1
  232. package/lib/listener/trace.js +0 -1
  233. package/lib/locator.js +67 -2
  234. package/lib/output.js +53 -0
  235. package/lib/parser.js +2 -71
  236. package/lib/pause.js +3 -2
  237. package/lib/plugin/allure.js +41 -22
  238. package/lib/plugin/autoLogin.js +4 -1
  239. package/lib/plugin/pauseOnFail.js +38 -0
  240. package/lib/plugin/puppeteerCoverage.js +8 -7
  241. package/lib/plugin/screenshotOnFail.js +13 -8
  242. package/lib/plugin/stepByStepReport.js +7 -6
  243. package/lib/plugin/wdio.js +2 -1
  244. package/lib/recorder.js +85 -7
  245. package/lib/rerun.js +81 -0
  246. package/lib/secret.js +6 -0
  247. package/lib/session.js +9 -2
  248. package/lib/step.js +37 -2
  249. package/lib/store.js +5 -1
  250. package/lib/ui.js +34 -8
  251. package/lib/utils.js +6 -13
  252. package/lib/within.js +5 -0
  253. package/package.json +49 -29
  254. package/typings/Mocha.d.ts +21 -0
  255. package/typings/Protractor.d.ts +16 -0
  256. package/typings/index.d.ts +169 -0
  257. package/typings/jsdoc.conf.js +34 -0
  258. package/typings/jsdoc.namespace.js +29 -0
  259. package/typings/types.d.ts +9827 -0
  260. package/typings/utils.d.ts +7 -0
  261. package/docs/acceptance.md +0 -409
  262. package/docs/api/codecept.md +0 -75
  263. package/docs/api/config.md +0 -49
  264. package/docs/api/container.md +0 -66
  265. package/docs/api/helper.md +0 -116
  266. package/docs/api/output.md +0 -67
  267. package/docs/api/recorder.md +0 -63
  268. package/docs/helpers/SeleniumWebdriver.md +0 -92
  269. package/docs/helpers/WebDriverIO.md +0 -1671
@@ -1,301 +1,29 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
1
4
  const getConfig = require('./utils').getConfig;
2
5
  const getTestRoot = require('./utils').getTestRoot;
3
6
  const Codecept = require('../codecept');
4
7
  const container = require('../container');
5
- const methodsOfObject = require('../utils').methodsOfObject;
6
8
  const output = require('../output');
7
- const { toTypeDef } = require('../parser');
8
- const fs = require('fs');
9
- const path = require('path');
10
-
11
- const template = `
12
- type ICodeceptCallback = (i?: CodeceptJS.{{I}}, current?:any{{callbackParams}}) => void;
13
-
14
- declare class FeatureConfig {
15
- retry(times: number): FeatureConfig
16
- timeout(seconds: number): FeatureConfig
17
- config(config: object): FeatureConfig
18
- config(helperName: string, config: object): FeatureConfig
19
- tag(tagName: string): FeatureConfig
20
- }
21
-
22
- declare class ScenarioConfig {
23
- throws(err: any): ScenarioConfig;
24
- fails(): ScenarioConfig;
25
- retry(times: number): ScenarioConfig
26
- timeout(timeout: number): ScenarioConfig
27
- inject(inject: object): ScenarioConfig
28
- config(config: object): ScenarioConfig
29
- config(helperName: string, config: object): ScenarioConfig
30
- tag(tagName: string): ScenarioConfig
31
- injectDependencies(dependencies: { [key: string]: any }): ScenarioConfig
32
- }
33
-
34
- interface ILocator {
35
- id?: string;
36
- xpath?: string;
37
- css?: string;
38
- name?: string;
39
- frame?: string;
40
- android?: string;
41
- ios?: string;
42
- }
43
-
44
- type LocatorOrString = string | ILocator | Locator;
45
-
46
- declare class Container {
47
- create(config: Object, opts: Object): void
48
- plugins(name?: string): Object
49
- support(name?: string): Object
50
- helpers(name?: string): Object
51
- translation(): Object
52
- mocha(): Object
53
- append(newContainer: Object): void
54
- clear(newHelpers: Object, newSupport: Object, newPlugins: Object): void
55
- }
56
-
57
- declare class RecorderSession {
58
- running: boolean
59
- start(name: string): void
60
- restore(name: string): void
61
- catch(fn: CallableFunction): void
62
- }
63
-
64
- declare class Recorder {
65
- retries: Object[]
66
- start(): void
67
- isRunning(): boolean
68
- startUnlessRunning(): void
69
- errHandler(fn: CallableFunction): void
70
- reset(): void
71
- session: RecorderSession
72
- add(taskName: string, fn?: CallableFunction, force?: boolean, retry?: boolean): Promise<any>
73
- retry(opts: Object): Promise<any>
74
- catch(customErrFn: CallableFunction): Promise<any>
75
- catchWithoutStop(customErrFn: CallableFunction ): Promise<any>
76
- throw(err: Error): Promise<any>
77
- saveFirstAsyncError(err: Error): void
78
- getAsyncErr(): Promise<Error>
79
- cleanAsyncErr(): void
80
- stop():void
81
- promise(): Promise<any>
82
- scheduled(): string[]
83
- toString(): string
84
- add(hookName: string, fn: CallableFunction, force?: boolean): void
85
- catch(customErrFn: CallableFunction): void
86
- }
87
-
88
- declare class CodeceptJSEvent {
89
- dispatcher: NodeJS.EventEmitter
90
- test: {
91
- started: string
92
- before: string
93
- after: string
94
- passed: string
95
- failed: string
96
- finished: string
97
- }
98
- suite: {
99
- before: string,
100
- after: string,
101
- }
102
- hook: {
103
- started: string,
104
- passed: string,
105
- }
106
- step: {
107
- before: string,
108
- after: string,
109
- started: string,
110
- passed: string,
111
- failed: string,
112
- finished: string,
113
- }
114
- all: {
115
- before: string,
116
- after: string,
117
- result: string,
118
- }
119
- multiple: {
120
- before: string,
121
- after: string,
122
- }
123
- emit(event: string, param: string): void
124
- cleanDispatcher(): void
125
- }
126
-
127
- declare class Output {
128
- colors: any
129
- styles: {
130
- error: any,
131
- success: any,
132
- scenario: any,
133
- basic: any,
134
- debug: any,
135
- log: any,
136
- }
137
-
138
- print(msg: string): void
139
- stepShift: number
140
- level(level: number): number
141
- process(process: string): string
142
- debug(msg: string): void
143
- log(msg: string): void
144
- error(msg: string): void
145
- success(msg: string): void
146
- plugin(name: string, msg: string): void
147
- step(step: any): void
148
- suite: {
149
- started: Function
150
- }
151
- test: {
152
- started(test: string): void
153
- passed(test: string): void
154
- failed(test: string): void
155
- skipped(test: string): void
156
- }
157
- scenario: {
158
- started(test: string): void
159
- passed(test: string): void
160
- failed(test: string): void
161
- }
162
- say(message: string, color?: string): void
163
- result(passed: number, failed: number, skipped: number, duration: string): void
164
- }
165
-
166
- declare class Config {
167
- create(newConfig: Object): Object
168
- load(configFile: string): Config
169
- get(key: string, val: any): any
170
- append(additionalConfig: Object): Object
171
- reset(): Object
172
- }
173
-
174
- declare class Helper {
175
- /** Abstract method to provide required config options */
176
- static _config(): any;
177
- /** Abstract method to validate config */
178
- _validateConfig<T>(config: T): T;
179
- /** Sets config for current test */
180
- _setConfig(opts: any): void;
181
- /** Hook executed before all tests */
182
- _init(): void
183
- /** Hook executed before each test. */
184
- _before(): void
185
- /** Hook executed after each test */
186
- _after(): void
187
- /**
188
- * Hook provides a test details
189
- * Executed in the very beginning of a test
190
- */
191
- _test(test: () => void): void
192
- /** Hook executed after each passed test */
193
- _passed(test: () => void): void
194
- /** Hook executed after each failed test */
195
- _failed(test: () => void): void
196
- /** Hook executed before each step */
197
- _beforeStep(step: () => void): void
198
- /** Hook executed after each step */
199
- _afterStep(step: () => void): void
200
- /** Hook executed before each suite */
201
- _beforeSuite(suite: () => void): void
202
- /** Hook executed after each suite */
203
- _afterSuite(suite: () => void): void
204
- /** Hook executed after all tests are executed */
205
- _finishTest(suite: () => void): void
206
- /**Access another configured helper: this.helpers['AnotherHelper'] */
207
- readonly helpers: any
208
- /** Print debug message to console (outputs only in debug mode) */
209
- debug(msg: string): void
210
9
 
211
- debugSection(section: string, msg: string): void
212
- }
213
-
214
- declare class Locator {
215
- constructor(locator: LocatorOrString, defaultType?: string);
216
-
217
- or(locator: LocatorOrString): Locator;
218
- find(locator: LocatorOrString): Locator;
219
- withChild(locator: LocatorOrString): Locator;
220
- withDescendant(locator: LocatorOrString): Locator;
221
- at(position: number): Locator;
222
- first(): Locator;
223
- last(): Locator;
224
- inside(locator: LocatorOrString): Locator;
225
- before(locator: LocatorOrString): Locator;
226
- after(locator: LocatorOrString): Locator;
227
- withText(text: string): Locator;
228
- withAttr(attrs: object): Locator;
229
- as(output: string): Locator;
230
- }
231
-
232
-
233
- declare function actor(customSteps?: {
234
- [action: string]: (this: CodeceptJS.I, ...args: any[]) => void
235
- }): CodeceptJS.{{I}};
236
- declare function actor(customSteps?: {}): CodeceptJS.{{I}};
237
- declare function Feature(title: string, opts?: {}): FeatureConfig;
238
- declare const Scenario: {
239
- (title: string, callback: ICodeceptCallback): ScenarioConfig;
240
- (title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig;
241
- only(title: string, callback: ICodeceptCallback): ScenarioConfig;
242
- only(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig;
243
- }
244
- declare interface IScenario {
245
- Scenario(title: string, callback: ICodeceptCallback): ScenarioConfig;
246
- Scenario(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig;
247
- }
248
- declare function xScenario(title: string, callback: ICodeceptCallback): ScenarioConfig;
249
- declare function xScenario(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig;
250
- declare interface IData {
251
- Scenario(title: string, callback: ICodeceptCallback): ScenarioConfig;
252
- Scenario(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig;
253
- only: IScenario;
254
- }
255
- declare function Data(data: any): IData;
256
- declare function xData(data: any): IData;
257
- declare function Before(callback: ICodeceptCallback): void;
258
- declare function BeforeSuite(callback: ICodeceptCallback): void;
259
- declare function After(callback: ICodeceptCallback): void;
260
- declare function AfterSuite(callback: ICodeceptCallback): void;
261
-
262
- declare function inject(): {
263
- {{injectPageObjects}}
264
- };
265
- declare function locate(selector: LocatorOrString): Locator;
266
- declare function within(selector: LocatorOrString, callback: Function): Promise<any>;
267
- declare function session(selector: LocatorOrString, callback: Function): Promise<any>;
268
- declare function session(selector: LocatorOrString, config: any, callback: Function): Promise<any>;
269
- declare function pause(): void;
270
- declare function secret(secret: any): string;
271
-
272
- declare const codeceptjs: any;
10
+ const template = ({
11
+ helperNames, supportObject, importPaths, translations, hasCustomStepsFile,
12
+ }) => `/// <reference types='codeceptjs' />
13
+ ${importPaths.join('\n')}
273
14
 
274
15
  declare namespace CodeceptJS {
275
- export const container: Container
276
- export const recorder: Recorder
277
- export const event: CodeceptJSEvent
278
- export const output: Output
279
- export const config: Config
280
-
281
- export interface {{I}} {
282
- {{methods}}
16
+ interface SupportObject ${convertMapToType(supportObject)}
17
+ interface CallbackOrder { ${convertMapToIndexedInterface(supportObject)} }
18
+ ${helperNames.length > 0 ? `interface Methods extends ${helperNames.join(', ')} {}` : ''}
19
+ interface I extends ${hasCustomStepsFile ? 'ReturnType<steps_file>' : 'WithTranslation<Methods>'} {}
20
+ namespace Translation {
21
+ interface Actions ${JSON.stringify(translations.vocabulary.actions, null, 2)}
283
22
  }
284
- {{exportPageObjects}}
285
- }
286
-
287
- declare module "codeceptjs" {
288
- export = CodeceptJS;
289
23
  }
290
24
  `;
291
25
 
292
- const injectSupportTemplate = ' {{name}}: CodeceptJS.{{name}}';
293
-
294
- const pageObjectTemplate = `
295
- export interface {{name}} {
296
- {{methods}}
297
- }
298
- `;
26
+ const helperNames = [];
299
27
 
300
28
  module.exports = function (genPath, options) {
301
29
  const configFile = options.config || genPath;
@@ -303,89 +31,109 @@ module.exports = function (genPath, options) {
303
31
  const config = getConfig(configFile);
304
32
  if (!config) return;
305
33
 
34
+ /** @type {Object<string, string>} */
35
+ const helperPaths = {};
36
+ /** @type {Object<string, string>} */
37
+ const supportPaths = {};
38
+ let hasCustomStepsFile = false;
39
+
306
40
  const targetFolderPath = options.output && getTestRoot(options.output) || testsPath;
307
41
 
308
42
  const codecept = new Codecept(config, {});
309
43
  codecept.init(testsPath);
310
44
 
311
45
  const helpers = container.helpers();
312
- const suppportI = container.support('I');
313
46
  const translations = container.translation();
314
- let methods = [];
315
- const actions = [];
316
47
  for (const name in helpers) {
317
- const helper = helpers[name];
318
- methods = addAllMethodsInObject(helper, actions, methods, translations);
48
+ const require = codecept.config.helpers[name].require;
49
+ if (require) {
50
+ helperPaths[name] = require;
51
+ helperNames.push(name);
52
+ } else {
53
+ helperNames.push(`CodeceptJS.${name}`);
54
+ }
319
55
  }
320
- methods = addAllNamesInObject(suppportI, actions, methods);
321
56
 
322
- const supports = container.support(); // return all support objects
323
- const exportPageObjects = [];
324
- const injectPageObjects = [];
325
- // "I" should be always, because it contains I.say
326
- injectPageObjects.push(injectSupportTemplate.replace(/{{name}}/g, String('I')));
327
- const callbackParams = [];
328
- // See #1795 and #1799, there's no obvious way to use for-in with Proxies
329
- Reflect.ownKeys(supports).forEach((name) => {
330
- if (name === 'I') {
331
- return;
57
+ const supportObject = new Map();
58
+ supportObject.set('I', 'CodeceptJS.I');
59
+ for (const name in codecept.config.include) {
60
+ const includePath = codecept.config.include[name];
61
+ if (name === 'I' || name === translations.I) {
62
+ hasCustomStepsFile = true;
63
+ supportPaths.steps_file = includePath;
64
+ continue;
332
65
  }
333
- callbackParams.push(`${String(name)}?:CodeceptJS.${String(name)}`);
334
- const pageObject = supports[name];
335
- const pageMethods = addAllMethodsInObject(pageObject, {}, []);
336
- let pageObjectExport = pageObjectTemplate.replace('{{methods}}', pageMethods.join(''));
337
- pageObjectExport = pageObjectExport.replace('{{name}}', String(name));
338
- injectPageObjects.push(injectSupportTemplate.replace(/{{name}}/g, String(name)));
339
- exportPageObjects.push(pageObjectExport);
340
- });
341
-
342
- let definitionsTemplate = template.replace('{{methods}}', methods.join(''));
343
- definitionsTemplate = definitionsTemplate.replace('{{exportPageObjects}}', exportPageObjects.join('\n'));
344
- definitionsTemplate = definitionsTemplate.replace('{{injectPageObjects}}', injectPageObjects.join('\n'));
345
- definitionsTemplate = definitionsTemplate.replace('{{callbackParams}}', `, ${[...callbackParams, '...args: any'].join(', ')}`);
346
- if (translations) {
347
- definitionsTemplate = definitionsTemplate.replace(/\{\{I\}\}/g, translations.I);
66
+ supportPaths[name] = includePath;
67
+ supportObject.set(name, name);
348
68
  }
349
69
 
70
+ const definitionsTemplate = template({
71
+ helperNames,
72
+ supportObject,
73
+ importPaths: getImportString(testsPath, targetFolderPath, supportPaths, helperPaths),
74
+ translations,
75
+ hasCustomStepsFile,
76
+ });
77
+
350
78
  fs.writeFileSync(path.join(targetFolderPath, 'steps.d.ts'), definitionsTemplate);
351
79
  output.print('TypeScript Definitions provide autocompletion in Visual Studio Code and other IDEs');
352
80
  output.print('Definitions were generated in steps.d.ts');
353
81
  };
354
82
 
355
- function addAllMethodsInObject(supportObj, actions, methods, translations) {
356
- for (const action of methodsOfObject(supportObj)) {
357
- const fn = supportObj[action];
358
- if (!fn.name) {
359
- Object.defineProperty(fn, 'name', { value: action });
360
- }
361
- const actionAlias = translations ? translations.actionAliasFor(action) : action;
362
- if (!actions[actionAlias]) {
363
- methods.push(toTypeDef(fn));
364
- actions[actionAlias] = 1;
365
- }
366
- }
367
- return methods;
83
+ /**
84
+ * Returns the relative path from the to the targeted folder.
85
+ * @param {string} originalPath
86
+ * @param { string} targetFolderPath
87
+ * @param { string} testsPath
88
+ */
89
+ function getPath(originalPath, targetFolderPath, testsPath) {
90
+ const parsedPath = path.parse(originalPath);
91
+
92
+ // Remove typescript extension if exists.
93
+ if (parsedPath.base.endsWith('.d.ts')) parsedPath.base = parsedPath.base.substring(0, parsedPath.base.length - 5);
94
+ else if (parsedPath.ext === '.ts') parsedPath.base = parsedPath.name;
95
+
96
+ if (!parsedPath.dir.startsWith('.')) return path.join(parsedPath.dir, parsedPath.base);
97
+ const relativePath = path.relative(targetFolderPath, path.join(testsPath, parsedPath.dir, parsedPath.base));
98
+
99
+ return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
368
100
  }
369
101
 
370
- function addAllNamesInObject(supportObj, actions, methods) {
371
- for (const name in supportObj) {
372
- if (actions[name]) {
373
- continue;
374
- }
375
- const actor = supportObj[name];
376
- let params = toTypeDef(actor);
377
- if (params !== undefined) {
378
- if (params.indexOf(' : ') > 0) {
379
- if (params.indexOf(' (') > 0) {
380
- params = params.trim();
381
- methods.push(` ${(name)}${params}\n`);
382
- } else {
383
- methods.push(`${params}`);
384
- }
385
- } else {
386
- methods.push(` ${(name)}: (${params}) => any; \n`);
387
- }
388
- }
102
+ /**
103
+ *
104
+ *
105
+ * @param {string} testsPath
106
+ * @param {string} targetFolderPath
107
+ * @param {Object<string, string>} pathsToType
108
+ * @param {Object<string, string>} pathsToValue
109
+ * @returns
110
+ */
111
+ function getImportString(testsPath, targetFolderPath, pathsToType, pathsToValue) {
112
+ const importStrings = [];
113
+
114
+ for (const name in pathsToType) {
115
+ const relativePath = getPath(pathsToType[name], targetFolderPath, testsPath);
116
+ importStrings.push(`type ${name} = typeof import('${relativePath}');`);
389
117
  }
390
- return methods;
118
+
119
+ for (const name in pathsToValue) {
120
+ const relativePath = getPath(pathsToValue[name], targetFolderPath, testsPath);
121
+ importStrings.push(`type ${name} = import('${relativePath}');`);
122
+ }
123
+
124
+ return importStrings;
125
+ }
126
+
127
+ /**
128
+ * @param {Map} map
129
+ */
130
+ function convertMapToIndexedInterface(map) {
131
+ return [...map.values()].map((value, i) => `[${i}]: ${value}`).join('; ');
132
+ }
133
+
134
+ /**
135
+ * @param {Map} map
136
+ */
137
+ function convertMapToType(map) {
138
+ return `{ ${Array.from(map).map(([key, value]) => `${key}: ${value}`).join(', ')} }`;
391
139
  }
@@ -1,16 +1,16 @@
1
- const output = require('../output');
2
- const inquirer = require('inquirer');
1
+ const colors = require('chalk');
3
2
  const fs = require('fs');
3
+ const inquirer = require('inquirer');
4
+ const mkdirp = require('mkdirp');
4
5
  const path = require('path');
5
- const colors = require('chalk');
6
+
6
7
  const { fileExists, ucfirst, lcfirst } = require('../utils');
7
- const mkdirp = require('mkdirp');
8
+ const output = require('../output');
8
9
  const {
9
- getConfig, getTestRoot, updateConfig, safeFileWrite,
10
+ getConfig, getTestRoot, safeFileWrite,
10
11
  } = require('./utils');
11
12
 
12
- const testTemplate = `
13
- Feature('{{feature}}');
13
+ const testTemplate = `Feature('{{feature}}');
14
14
 
15
15
  Scenario('test something', ({{actor}}) => {
16
16
 
@@ -28,18 +28,18 @@ module.exports.test = function (genPath) {
28
28
 
29
29
  const defaultExt = config.tests.match(/([^\*/]*?)$/[1])[0] || '_test.js';
30
30
 
31
- inquirer.prompt([
31
+ return inquirer.prompt([
32
32
  {
33
33
  type: 'input',
34
- message: 'Filename of the test',
35
- name: 'filename',
34
+ name: 'feature',
35
+ message: 'Feature which is being tested',
36
36
  },
37
37
  {
38
38
  type: 'input',
39
- name: 'feature',
40
- message: 'Feature which is being tested',
39
+ message: 'Filename of a test',
40
+ name: 'filename',
41
41
  default(answers) {
42
- return ucfirst(answers.filename).replace('_', ' ').replace('-', ' ');
42
+ return (answers.feature).replace(' ', '_').toLowerCase() + defaultExt;
43
43
  },
44
44
  },
45
45
  ]).then((result) => {
@@ -81,7 +81,7 @@ module.exports.pageObject = function (genPath, opts) {
81
81
  output.print(`Creating a new ${kind} object`);
82
82
  output.print('--------------------------');
83
83
 
84
- inquirer.prompt([{
84
+ return inquirer.prompt([{
85
85
  type: 'input',
86
86
  name: 'name',
87
87
  message: `Name of a ${kind} object`,
@@ -118,16 +118,21 @@ module.exports.pageObject = function (genPath, opts) {
118
118
  });
119
119
  };
120
120
 
121
- const helperTemplate = `
122
- const Helper = codeceptjs.helper;
121
+ const helperTemplate = `const { Helper } = codeceptjs;
123
122
 
124
123
  class {{name}} extends Helper {
125
124
 
126
125
  // before/after hooks
126
+ /**
127
+ * @protected
128
+ */
127
129
  _before() {
128
130
  // remove if not used
129
131
  }
130
132
 
133
+ /**
134
+ * @protected
135
+ */
131
136
  _after() {
132
137
  // remove if not used
133
138
  }
@@ -148,7 +153,7 @@ module.exports.helper = function (genPath) {
148
153
  output.print('Creating a new helper');
149
154
  output.print('--------------------------');
150
155
 
151
- inquirer.prompt([{
156
+ return inquirer.prompt([{
152
157
  type: 'input',
153
158
  name: 'name',
154
159
  message: 'Name of a Helper',
@@ -1,8 +1,9 @@
1
- const output = require('../../output');
2
1
  const inquirer = require('inquirer');
3
2
  const fs = require('fs');
4
3
  const path = require('path');
5
4
  const mkdirp = require('mkdirp');
5
+
6
+ const output = require('../../output');
6
7
  const { fileExists, ucfirst, lcfirst } = require('../../utils');
7
8
  const {
8
9
  getConfig, getTestRoot, updateConfig, safeFileWrite,
@@ -1,14 +1,14 @@
1
+ const escapeStringRegexp = require('escape-string-regexp');
2
+ const fs = require('fs');
3
+ const { Parser } = require('gherkin');
4
+ const glob = require('glob');
5
+ const fsPath = require('path');
6
+
1
7
  const getConfig = require('../utils').getConfig;
2
8
  const getTestRoot = require('../utils').getTestRoot;
3
9
  const Codecept = require('../../codecept');
4
- const container = require('../../container');
5
10
  const output = require('../../output');
6
11
  const { matchStep } = require('../../interfaces/bdd');
7
- const { Parser } = require('gherkin');
8
- const glob = require('glob');
9
- const fsPath = require('path');
10
- const fs = require('fs');
11
- const escapeStringRegexp = require('escape-string-regexp');
12
12
 
13
13
  const parser = new Parser();
14
14
  parser.stopAtFirstError = false;
@@ -25,4 +25,3 @@ module.exports = function (genPath, options) {
25
25
  output.error('No Gherkin steps defined');
26
26
  }
27
27
  };
28
-
@@ -0,0 +1,40 @@
1
+ const envinfo = require('envinfo');
2
+
3
+ const getConfig = require('./utils').getConfig;
4
+ const getTestRoot = require('./utils').getTestRoot;
5
+ const Codecept = require('../codecept');
6
+ const output = require('../output');
7
+
8
+ module.exports = async function (path) {
9
+ const testsPath = getTestRoot(path);
10
+ const config = getConfig(testsPath);
11
+ const codecept = new Codecept(config, {});
12
+ codecept.init(testsPath);
13
+
14
+ output.print('\n Environment information:-\n');
15
+ const info = {};
16
+ info.codeceptVersion = Codecept.version();
17
+ info.nodeInfo = await envinfo.helpers.getNodeInfo();
18
+ info.osInfo = await envinfo.helpers.getOSInfo();
19
+ info.cpuInfo = await envinfo.helpers.getCPUInfo();
20
+ info.chromeInfo = await envinfo.helpers.getChromeInfo();
21
+ info.edgeInfo = await envinfo.helpers.getEdgeInfo();
22
+ info.firefoxInfo = await envinfo.helpers.getFirefoxInfo();
23
+ info.safariInfo = await envinfo.helpers.getSafariInfo();
24
+ const { helpers, plugins } = config;
25
+ info.helpers = helpers || "You don't use any helpers";
26
+ info.plugins = plugins || "You don't have any enabled plugins";
27
+
28
+ for (const [key, value] of Object.entries(info)) {
29
+ if (Array.isArray(value)) {
30
+ output.print(`${key}: ${value[1]}`);
31
+ } else {
32
+ output.print(`${key}: ${JSON.stringify(value, null, ' ')}`);
33
+ }
34
+ }
35
+ output.print('***************************************');
36
+ output.print('If you have questions ask them in our Slack: shorturl.at/cuKU8');
37
+ output.print('Or ask them on our discussion board: https://codecept.discourse.group/');
38
+ output.print('Please copy environment info when you report issues on GitHub: https://github.com/Codeception/CodeceptJS/issues');
39
+ output.print('***************************************');
40
+ };