codeceptjs 3.4.1 → 3.5.1-2.beta.7

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 (281) hide show
  1. package/README.md +31 -30
  2. package/bin/codecept.js +1 -1
  3. package/lib/actor.js +6 -3
  4. package/lib/ai.js +180 -0
  5. package/lib/cli.js +13 -3
  6. package/lib/codecept.js +8 -0
  7. package/lib/colorUtils.js +10 -0
  8. package/lib/command/definitions.js +2 -7
  9. package/lib/command/dryRun.js +11 -2
  10. package/lib/command/generate.js +46 -3
  11. package/lib/command/info.js +24 -0
  12. package/lib/command/init.js +64 -6
  13. package/lib/command/interactive.js +15 -1
  14. package/lib/command/run-multiple/collection.js +17 -5
  15. package/lib/command/run-multiple.js +4 -2
  16. package/lib/command/run-workers.js +68 -5
  17. package/lib/command/run.js +7 -0
  18. package/lib/command/workers/runTests.js +39 -0
  19. package/lib/container.js +13 -3
  20. package/lib/data/context.js +14 -6
  21. package/lib/event.js +4 -0
  22. package/lib/helper/ApiDataFactory.js +2 -1
  23. package/lib/helper/Appium.js +116 -29
  24. package/lib/helper/Expect.js +422 -0
  25. package/lib/helper/FileSystem.js +1 -1
  26. package/lib/helper/GraphQL.js +25 -0
  27. package/lib/helper/JSONResponse.js +4 -4
  28. package/lib/helper/Nightmare.js +10 -5
  29. package/lib/helper/OpenAI.js +126 -0
  30. package/lib/helper/Playwright.js +1298 -229
  31. package/lib/helper/Protractor.js +12 -7
  32. package/lib/helper/Puppeteer.js +204 -64
  33. package/lib/helper/REST.js +15 -5
  34. package/lib/helper/TestCafe.js +45 -10
  35. package/lib/helper/WebDriver.js +252 -83
  36. package/lib/helper/errors/ElementNotFound.js +2 -1
  37. package/lib/helper/extras/PlaywrightReactVueLocator.js +38 -0
  38. package/lib/helper/scripts/blurElement.js +17 -0
  39. package/lib/helper/scripts/focusElement.js +17 -0
  40. package/lib/helper/scripts/highlightElement.js +20 -0
  41. package/lib/html.js +258 -0
  42. package/lib/interfaces/bdd.js +1 -1
  43. package/lib/interfaces/gherkin.js +37 -3
  44. package/lib/interfaces/scenarioConfig.js +1 -0
  45. package/lib/listener/retry.js +2 -1
  46. package/lib/locator.js +17 -4
  47. package/lib/mochaFactory.js +2 -1
  48. package/lib/output.js +1 -1
  49. package/lib/pause.js +78 -19
  50. package/lib/plugin/autoLogin.js +45 -10
  51. package/lib/plugin/debugErrors.js +67 -0
  52. package/lib/plugin/fakerTransform.js +4 -6
  53. package/lib/plugin/heal.js +209 -0
  54. package/lib/plugin/retryFailedStep.js +10 -1
  55. package/lib/plugin/retryTo.js +2 -4
  56. package/lib/plugin/screenshotOnFail.js +11 -2
  57. package/lib/plugin/selenoid.js +6 -1
  58. package/lib/plugin/standardActingHelpers.js +0 -2
  59. package/lib/plugin/stepByStepReport.js +2 -2
  60. package/lib/plugin/tryTo.js +5 -7
  61. package/lib/plugin/wdio.js +0 -1
  62. package/lib/recorder.js +22 -11
  63. package/lib/secret.js +5 -4
  64. package/lib/session.js +1 -1
  65. package/lib/step.js +36 -12
  66. package/lib/ui.js +5 -3
  67. package/lib/utils.js +22 -1
  68. package/lib/workers.js +83 -10
  69. package/package.json +117 -95
  70. package/translations/de-DE.js +5 -0
  71. package/translations/fr-FR.js +14 -1
  72. package/translations/it-IT.js +1 -0
  73. package/translations/ja-JP.js +14 -9
  74. package/translations/pl-PL.js +5 -0
  75. package/translations/pt-BR.js +1 -0
  76. package/translations/ru-RU.js +1 -0
  77. package/translations/zh-CN.js +5 -0
  78. package/translations/zh-TW.js +5 -0
  79. package/typings/index.d.ts +51 -15
  80. package/typings/promiseBasedTypes.d.ts +864 -802
  81. package/typings/types.d.ts +1339 -744
  82. package/CHANGELOG.md +0 -2427
  83. package/docs/advanced.md +0 -351
  84. package/docs/api.md +0 -323
  85. package/docs/basics.md +0 -980
  86. package/docs/bdd.md +0 -535
  87. package/docs/best.md +0 -237
  88. package/docs/books.md +0 -37
  89. package/docs/bootstrap.md +0 -135
  90. package/docs/build/ApiDataFactory.js +0 -409
  91. package/docs/build/Appium.js +0 -1938
  92. package/docs/build/FileSystem.js +0 -228
  93. package/docs/build/GraphQL.js +0 -204
  94. package/docs/build/GraphQLDataFactory.js +0 -309
  95. package/docs/build/JSONResponse.js +0 -338
  96. package/docs/build/Mochawesome.js +0 -71
  97. package/docs/build/Nightmare.js +0 -2145
  98. package/docs/build/Playwright.js +0 -3986
  99. package/docs/build/Polly.js +0 -42
  100. package/docs/build/Protractor.js +0 -2699
  101. package/docs/build/Puppeteer.js +0 -3710
  102. package/docs/build/REST.js +0 -334
  103. package/docs/build/SeleniumWebdriver.js +0 -76
  104. package/docs/build/TestCafe.js +0 -2057
  105. package/docs/build/WebDriver.js +0 -4017
  106. package/docs/changelog.md +0 -2436
  107. package/docs/commands.md +0 -254
  108. package/docs/community-helpers.md +0 -58
  109. package/docs/configuration.md +0 -157
  110. package/docs/continuous-integration.md +0 -22
  111. package/docs/custom-helpers.md +0 -306
  112. package/docs/data.md +0 -375
  113. package/docs/detox.md +0 -235
  114. package/docs/docker.md +0 -137
  115. package/docs/email.md +0 -183
  116. package/docs/examples.md +0 -149
  117. package/docs/helpers/ApiDataFactory.md +0 -266
  118. package/docs/helpers/Appium.md +0 -1312
  119. package/docs/helpers/Detox.md +0 -586
  120. package/docs/helpers/FileSystem.md +0 -152
  121. package/docs/helpers/GraphQL.md +0 -130
  122. package/docs/helpers/GraphQLDataFactory.md +0 -226
  123. package/docs/helpers/JSONResponse.md +0 -254
  124. package/docs/helpers/Mochawesome.md +0 -8
  125. package/docs/helpers/MockRequest.md +0 -377
  126. package/docs/helpers/Nightmare.md +0 -1256
  127. package/docs/helpers/Playwright.md +0 -2208
  128. package/docs/helpers/Polly.md +0 -44
  129. package/docs/helpers/Puppeteer-firefox.md +0 -86
  130. package/docs/helpers/Puppeteer.md +0 -2141
  131. package/docs/helpers/REST.md +0 -217
  132. package/docs/helpers/TestCafe.md +0 -1222
  133. package/docs/helpers/WebDriver.md +0 -2319
  134. package/docs/hooks.md +0 -340
  135. package/docs/index.md +0 -111
  136. package/docs/installation.md +0 -75
  137. package/docs/internal-api.md +0 -265
  138. package/docs/locators.md +0 -331
  139. package/docs/mobile-react-native-locators.md +0 -67
  140. package/docs/mobile.md +0 -297
  141. package/docs/nightmare.md +0 -223
  142. package/docs/pageobjects.md +0 -291
  143. package/docs/parallel.md +0 -232
  144. package/docs/playwright.md +0 -609
  145. package/docs/plugins.md +0 -1171
  146. package/docs/puppeteer.md +0 -316
  147. package/docs/quickstart.md +0 -163
  148. package/docs/react.md +0 -69
  149. package/docs/reports.md +0 -392
  150. package/docs/secrets.md +0 -30
  151. package/docs/shadow.md +0 -68
  152. package/docs/shared/keys.mustache +0 -31
  153. package/docs/shared/react.mustache +0 -1
  154. package/docs/testcafe.md +0 -174
  155. package/docs/translation.md +0 -247
  156. package/docs/tutorial.md +0 -271
  157. package/docs/typescript.md +0 -180
  158. package/docs/ui.md +0 -59
  159. package/docs/videos.md +0 -28
  160. package/docs/visual.md +0 -202
  161. package/docs/vue.md +0 -121
  162. package/docs/webapi/amOnPage.mustache +0 -11
  163. package/docs/webapi/appendField.mustache +0 -9
  164. package/docs/webapi/attachFile.mustache +0 -12
  165. package/docs/webapi/checkOption.mustache +0 -13
  166. package/docs/webapi/clearCookie.mustache +0 -10
  167. package/docs/webapi/clearField.mustache +0 -9
  168. package/docs/webapi/click.mustache +0 -25
  169. package/docs/webapi/clickLink.mustache +0 -8
  170. package/docs/webapi/closeCurrentTab.mustache +0 -7
  171. package/docs/webapi/closeOtherTabs.mustache +0 -8
  172. package/docs/webapi/dontSee.mustache +0 -11
  173. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  174. package/docs/webapi/dontSeeCookie.mustache +0 -8
  175. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  176. package/docs/webapi/dontSeeElement.mustache +0 -8
  177. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  178. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  179. package/docs/webapi/dontSeeInField.mustache +0 -11
  180. package/docs/webapi/dontSeeInSource.mustache +0 -8
  181. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  182. package/docs/webapi/doubleClick.mustache +0 -13
  183. package/docs/webapi/downloadFile.mustache +0 -12
  184. package/docs/webapi/dragAndDrop.mustache +0 -9
  185. package/docs/webapi/dragSlider.mustache +0 -11
  186. package/docs/webapi/executeAsyncScript.mustache +0 -24
  187. package/docs/webapi/executeScript.mustache +0 -26
  188. package/docs/webapi/fillField.mustache +0 -16
  189. package/docs/webapi/forceClick.mustache +0 -28
  190. package/docs/webapi/forceRightClick.mustache +0 -18
  191. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  192. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  193. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  194. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  195. package/docs/webapi/grabCookie.mustache +0 -11
  196. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  197. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  198. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  199. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  200. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  201. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  202. package/docs/webapi/grabGeoLocation.mustache +0 -8
  203. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  204. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  205. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  206. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  207. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  208. package/docs/webapi/grabPopupText.mustache +0 -5
  209. package/docs/webapi/grabSource.mustache +0 -8
  210. package/docs/webapi/grabTextFrom.mustache +0 -10
  211. package/docs/webapi/grabTextFromAll.mustache +0 -9
  212. package/docs/webapi/grabTitle.mustache +0 -8
  213. package/docs/webapi/grabValueFrom.mustache +0 -9
  214. package/docs/webapi/grabValueFromAll.mustache +0 -8
  215. package/docs/webapi/moveCursorTo.mustache +0 -12
  216. package/docs/webapi/openNewTab.mustache +0 -7
  217. package/docs/webapi/pressKey.mustache +0 -12
  218. package/docs/webapi/pressKeyDown.mustache +0 -12
  219. package/docs/webapi/pressKeyUp.mustache +0 -12
  220. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  221. package/docs/webapi/refreshPage.mustache +0 -6
  222. package/docs/webapi/resizeWindow.mustache +0 -6
  223. package/docs/webapi/rightClick.mustache +0 -14
  224. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  225. package/docs/webapi/saveScreenshot.mustache +0 -12
  226. package/docs/webapi/say.mustache +0 -10
  227. package/docs/webapi/scrollIntoView.mustache +0 -11
  228. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  229. package/docs/webapi/scrollPageToTop.mustache +0 -6
  230. package/docs/webapi/scrollTo.mustache +0 -12
  231. package/docs/webapi/see.mustache +0 -11
  232. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  233. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  234. package/docs/webapi/seeCookie.mustache +0 -8
  235. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  236. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  237. package/docs/webapi/seeElement.mustache +0 -8
  238. package/docs/webapi/seeElementInDOM.mustache +0 -8
  239. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  240. package/docs/webapi/seeInField.mustache +0 -12
  241. package/docs/webapi/seeInPopup.mustache +0 -8
  242. package/docs/webapi/seeInSource.mustache +0 -7
  243. package/docs/webapi/seeInTitle.mustache +0 -8
  244. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  245. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  246. package/docs/webapi/seeTextEquals.mustache +0 -9
  247. package/docs/webapi/seeTitleEquals.mustache +0 -8
  248. package/docs/webapi/selectOption.mustache +0 -21
  249. package/docs/webapi/setCookie.mustache +0 -16
  250. package/docs/webapi/setGeoLocation.mustache +0 -12
  251. package/docs/webapi/switchTo.mustache +0 -9
  252. package/docs/webapi/switchToNextTab.mustache +0 -10
  253. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  254. package/docs/webapi/type.mustache +0 -18
  255. package/docs/webapi/uncheckOption.mustache +0 -13
  256. package/docs/webapi/wait.mustache +0 -8
  257. package/docs/webapi/waitForClickable.mustache +0 -11
  258. package/docs/webapi/waitForDetached.mustache +0 -10
  259. package/docs/webapi/waitForElement.mustache +0 -11
  260. package/docs/webapi/waitForEnabled.mustache +0 -6
  261. package/docs/webapi/waitForFunction.mustache +0 -17
  262. package/docs/webapi/waitForInvisible.mustache +0 -10
  263. package/docs/webapi/waitForText.mustache +0 -13
  264. package/docs/webapi/waitForValue.mustache +0 -10
  265. package/docs/webapi/waitForVisible.mustache +0 -10
  266. package/docs/webapi/waitInUrl.mustache +0 -9
  267. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  268. package/docs/webapi/waitToHide.mustache +0 -10
  269. package/docs/webapi/waitUrlEquals.mustache +0 -10
  270. package/docs/webdriver.md +0 -657
  271. package/docs/wiki/Books-&-Posts.md +0 -27
  272. package/docs/wiki/Community-Helpers-&-Plugins.md +0 -49
  273. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -29
  274. package/docs/wiki/Examples.md +0 -139
  275. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
  276. package/docs/wiki/Home.md +0 -16
  277. package/docs/wiki/Release-Process.md +0 -24
  278. package/docs/wiki/Roadmap.md +0 -23
  279. package/docs/wiki/Tests.md +0 -1393
  280. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
  281. package/docs/wiki/Videos.md +0 -19
@@ -1,409 +0,0 @@
1
- const path = require('path');
2
-
3
- const Helper = require('@codeceptjs/helper');
4
- const REST = require('./REST');
5
-
6
- /**
7
- * Helper for managing remote data using REST API.
8
- * Uses data generators like [rosie](https://github.com/rosiejs/rosie) or factory girl to create new record.
9
- *
10
- * By defining a factory you set the rules of how data is generated.
11
- * This data will be saved on server via REST API and deleted in the end of a test.
12
- *
13
- * ## Use Case
14
- *
15
- * Acceptance tests interact with a websites using UI and real browser.
16
- * There is no way to create data for a specific test other than from user interface.
17
- * That makes tests slow and fragile. Instead of testing a single feature you need to follow all creation/removal process.
18
- *
19
- * This helper solves this problem.
20
- * Most of web application have API, and it can be used to create and delete test records.
21
- * By combining REST API with Factories you can easily create records for tests:
22
- *
23
- * ```js
24
- * I.have('user', { login: 'davert', email: 'davert@mail.com' });
25
- * let id = await I.have('post', { title: 'My first post'});
26
- * I.haveMultiple('comment', 3, {post_id: id});
27
- * ```
28
- *
29
- * To make this work you need
30
- *
31
- * 1. REST API endpoint which allows to perform create / delete requests and
32
- * 2. define data generation rules
33
- *
34
- * ### Setup
35
- *
36
- * Install [Rosie](https://github.com/rosiejs/rosie) and [Faker](https://www.npmjs.com/package/faker) libraries.
37
- *
38
- * ```sh
39
- * npm i rosie @faker-js/faker --save-dev
40
- * ```
41
- *
42
- * Create a factory file for a resource.
43
- *
44
- * See the example for Posts factories:
45
- *
46
- * ```js
47
- * // tests/factories/posts.js
48
- *
49
- * const { Factory } = require('rosie');
50
- * const { faker } = require('@faker-js/faker');
51
- *
52
- * module.exports = new Factory()
53
- * // no need to set id, it will be set by REST API
54
- * .attr('author', () => faker.name.findName())
55
- * .attr('title', () => faker.lorem.sentence())
56
- * .attr('body', () => faker.lorem.paragraph());
57
- * ```
58
- * For more options see [rosie documentation](https://github.com/rosiejs/rosie).
59
- *
60
- * Then configure ApiDataHelper to match factories and REST API:
61
-
62
- * ### Configuration
63
- *
64
- * ApiDataFactory has following config options:
65
- *
66
- * * `endpoint`: base URL for the API to send requests to.
67
- * * `cleanup` (default: true): should inserted records be deleted up after tests
68
- * * `factories`: list of defined factories
69
- * * `returnId` (default: false): return id instead of a complete response when creating items.
70
- * * `headers`: list of headers
71
- * * `REST`: configuration for REST requests
72
- *
73
- * See the example:
74
- *
75
- * ```js
76
- * ApiDataFactory: {
77
- * endpoint: "http://user.com/api",
78
- * cleanup: true,
79
- * headers: {
80
- * 'Content-Type': 'application/json',
81
- * 'Accept': 'application/json',
82
- * },
83
- * factories: {
84
- * post: {
85
- * uri: "/posts",
86
- * factory: "./factories/post",
87
- * },
88
- * comment: {
89
- * factory: "./factories/comment",
90
- * create: { post: "/comments/create" },
91
- * delete: { post: "/comments/delete/{id}" },
92
- * fetchId: (data) => data.result.id
93
- * }
94
- * }
95
- * }
96
- * ```
97
-
98
- * It is required to set REST API `endpoint` which is the baseURL for all API requests.
99
- * Factory file is expected to be passed via `factory` option.
100
- *
101
- * This Helper uses [REST](http://codecept.io/helpers/REST/) helper and accepts its configuration in "REST" section.
102
- * For instance, to set timeout you should add:
103
- *
104
- * ```js
105
- * "ApiDataFactory": {
106
- * "REST": {
107
- * "timeout": "100000",
108
- * }
109
- * }
110
- * ```
111
- *
112
- * ### Requests
113
- *
114
- * By default to create a record ApiDataFactory will use endpoint and plural factory name:
115
- *
116
- * * create: `POST {endpoint}/{resource} data`
117
- * * delete: `DELETE {endpoint}/{resource}/id`
118
- *
119
- * Example (`endpoint`: `http://app.com/api`):
120
- *
121
- * * create: POST request to `http://app.com/api/users`
122
- * * delete: DELETE request to `http://app.com/api/users/1`
123
- *
124
- * This behavior can be configured with following options:
125
- *
126
- * * `uri`: set different resource uri. Example: `uri: account` => `http://app.com/api/account`.
127
- * * `create`: override create options. Expected format: `{ method: uri }`. Example: `{ "post": "/users/create" }`
128
- * * `delete`: override delete options. Expected format: `{ method: uri }`. Example: `{ "post": "/users/delete/{id}" }`
129
- *
130
- * Requests can also be overridden with a function which returns [axois request config](https://github.com/axios/axios#request-config).
131
- *
132
- * ```js
133
- * create: (data) => ({ method: 'post', url: '/posts', data }),
134
- * delete: (id) => ({ method: 'delete', url: '/posts', data: { id } })
135
- *
136
- * ```
137
- *
138
- * Requests can be updated on the fly by using `onRequest` function. For instance, you can pass in current session from a cookie.
139
- *
140
- * ```js
141
- * onRequest: async (request) => {
142
- * // using global codeceptjs instance
143
- * let cookie = await codeceptjs.container.helpers('WebDriver').grabCookie('session');
144
- * request.headers = { Cookie: `session=${cookie.value}` };
145
- * }
146
- * ```
147
- *
148
- * ### Responses
149
- *
150
- * By default `I.have()` returns a promise with a created data:
151
- *
152
- * ```js
153
- * let client = await I.have('client');
154
- * ```
155
- *
156
- * Ids of created records are collected and used in the end of a test for the cleanup.
157
- * If you need to receive `id` instead of full response enable `returnId` in a helper config:
158
- *
159
- * ```js
160
- * // returnId: false
161
- * let clientId = await I.have('client');
162
- * // clientId == 1
163
- *
164
- * // returnId: true
165
- * let clientId = await I.have('client');
166
- * // client == { name: 'John', email: 'john@snow.com' }
167
- * ```
168
- *
169
- * By default `id` property of response is taken. This behavior can be changed by setting `fetchId` function in a factory config.
170
- *
171
- *
172
- * ```js
173
- * factories: {
174
- * post: {
175
- * uri: "/posts",
176
- * factory: "./factories/post",
177
- * fetchId: (data) => data.result.posts[0].id
178
- * }
179
- * }
180
- * ```
181
- *
182
- *
183
- * ## Methods
184
- */
185
- class ApiDataFactory extends Helper {
186
- constructor(config) {
187
- super(config);
188
-
189
- const defaultConfig = {
190
- cleanup: true,
191
- REST: {},
192
- factories: {},
193
- returnId: false,
194
- };
195
- this.config = Object.assign(defaultConfig, this.config);
196
-
197
- if (this.config.headers) this.config.REST.defaultHeaders = this.config.headers;
198
- if (this.config.onRequest) this.config.REST.onRequest = this.config.onRequest;
199
- this.restHelper = new REST(Object.assign(this.config.REST, { endpoint: this.config.endpoint }));
200
- this.factories = this.config.factories;
201
-
202
- for (const factory in this.factories) {
203
- const factoryConfig = this.factories[factory];
204
- if (!factoryConfig.uri && !factoryConfig.create) {
205
- throw new Error(`Uri for factory "${factory}" is not defined. Please set "uri" parameter:
206
-
207
- "factories": {
208
- "${factory}": {
209
- "uri": ...
210
- `);
211
- }
212
-
213
- if (!factoryConfig.create) factoryConfig.create = { post: factoryConfig.uri };
214
- if (!factoryConfig.delete) factoryConfig.delete = { delete: `${factoryConfig.uri}/{id}` };
215
-
216
- this.factories[factory] = factoryConfig;
217
- }
218
-
219
- this.created = {};
220
- Object.keys(this.factories).forEach(f => this.created[f] = []);
221
- }
222
-
223
- static _checkRequirements() {
224
- try {
225
- require('axios');
226
- require('rosie');
227
- } catch (e) {
228
- return ['axios', 'rosie'];
229
- }
230
- }
231
-
232
- _after() {
233
- if (!this.config.cleanup || this.config.cleanup === false) {
234
- return Promise.resolve();
235
- }
236
- const promises = [];
237
-
238
- // clean up all created items
239
- for (const factoryName in this.created) {
240
- const createdItems = this.created[factoryName];
241
- if (!createdItems.length) continue;
242
- this.debug(`Deleting ${createdItems.length} ${factoryName}(s)`);
243
- for (const id in createdItems) {
244
- promises.push(this._requestDelete(factoryName, createdItems[id]));
245
- }
246
- }
247
- return Promise.all(promises);
248
- }
249
-
250
- /**
251
- * Generates a new record using factory and saves API request to store it.
252
- *
253
- * ```js
254
- * // create a user
255
- * I.have('user');
256
- * // create user with defined email
257
- * // and receive it when inside async function
258
- * const user = await I.have('user', { email: 'user@user.com'});
259
- * // create a user with options that will not be included in the final request
260
- * I.have('user', { }, { age: 33, height: 55 })
261
- * ```
262
- *
263
- * @param {*} factory factory to use
264
- * @param {*} [params] predefined parameters
265
- * @param {*} [options] options for programmatically generate the attributes
266
- * @returns {Promise<*>}
267
- */
268
- have(factory, params, options) {
269
- const item = this._createItem(factory, params, options);
270
- this.debug(`Creating ${factory} ${JSON.stringify(item)}`);
271
- return this._requestCreate(factory, item);
272
- }
273
-
274
- /**
275
- * Generates bunch of records and saves multiple API requests to store them.
276
- *
277
- * ```js
278
- * // create 3 posts
279
- * I.haveMultiple('post', 3);
280
- *
281
- * // create 3 posts by one author
282
- * I.haveMultiple('post', 3, { author: 'davert' });
283
- *
284
- * // create 3 posts by one author with options
285
- * I.haveMultiple('post', 3, { author: 'davert' }, { publish_date: '01.01.1997' });
286
- * ```
287
- *
288
- * @param {*} factory
289
- * @param {*} times
290
- * @param {*} [params]
291
- * @param {*} [options]
292
- */
293
- haveMultiple(factory, times, params, options) {
294
- const promises = [];
295
- for (let i = 0; i < times; i++) {
296
- promises.push(this.have(factory, params, options));
297
- }
298
- return Promise.all(promises);
299
- }
300
-
301
- _createItem(model, data, options) {
302
- if (!this.factories[model]) {
303
- throw new Error(`Factory ${model} is not defined in config`);
304
- }
305
- let modulePath = this.factories[model].factory;
306
- try {
307
- try {
308
- require.resolve(modulePath);
309
- } catch (e) {
310
- modulePath = path.join(global.codecept_dir, modulePath);
311
- }
312
- const builder = require(modulePath);
313
- return builder.build(data, options);
314
- } catch (err) {
315
- throw new Error(`Couldn't load factory file from ${modulePath}, check that
316
-
317
- "factories": {
318
- "${model}": {
319
- "factory": "./path/to/factory"
320
-
321
- points to valid factory file.
322
- Factory file should export an object with build method.
323
-
324
- Current file error: ${err.message}`);
325
- }
326
- }
327
-
328
- _fetchId(body, factory) {
329
- if (this.config.factories[factory].fetchId) {
330
- return this.config.factories[factory].fetchId(body);
331
- }
332
- if (body.id) return body.id;
333
- if (body[factory] && body[factory].id) return body[factory].id;
334
- return null;
335
- }
336
-
337
- /**
338
- * Executes request to create a record in API.
339
- * Can be replaced from a in custom helper.
340
- *
341
- * @param {*} factory
342
- * @param {*} data
343
- */
344
- _requestCreate(factory, data) {
345
- let request = createRequestFromFunction(this.factories[factory].create, data);
346
-
347
- if (!request) {
348
- const method = Object.keys(this.factories[factory].create)[0];
349
- const url = this.factories[factory].create[method];
350
- request = {
351
- method,
352
- url,
353
- data,
354
- };
355
- }
356
-
357
- request.baseURL = this.config.endpoint;
358
-
359
- return this.restHelper._executeRequest(request).then((resp) => {
360
- const id = this._fetchId(resp.data, factory);
361
- this.created[factory].push(id);
362
- this.debugSection('Created', `Id: ${id}`);
363
- if (this.config.returnId) return id;
364
- return resp.data;
365
- });
366
- }
367
-
368
- /**
369
- * Executes request to delete a record in API
370
- * Can be replaced from a custom helper.
371
- *
372
- * @param {*} factory
373
- * @param {*} id
374
- */
375
- _requestDelete(factory, id) {
376
- if (!this.factories[factory].delete) return;
377
- let request = createRequestFromFunction(this.factories[factory].delete, id);
378
-
379
- if (!request) {
380
- const method = Object.keys(this.factories[factory].delete)[0];
381
-
382
- const url = this.factories[factory].delete[method].replace('{id}', id);
383
-
384
- request = {
385
- method,
386
- url,
387
- };
388
- }
389
-
390
- request.baseURL = this.config.endpoint;
391
-
392
- if (request.url.match(/^undefined/)) {
393
- return this.debugSection('Please configure the delete request in your ApiDataFactory helper', 'delete: () => ({ method: \'DELETE\', url: \'/api/users\' })');
394
- }
395
-
396
- return this.restHelper._executeRequest(request).then(() => {
397
- const idx = this.created[factory].indexOf(id);
398
- this.debugSection('Deleted Id', `Id: ${id}`);
399
- this.created[factory].splice(idx, 1);
400
- });
401
- }
402
- }
403
-
404
- module.exports = ApiDataFactory;
405
-
406
- function createRequestFromFunction(param, data) {
407
- if (typeof param !== 'function') return;
408
- return param(data);
409
- }