codeceptjs 3.5.11 → 3.5.12-beta.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 (221) hide show
  1. package/README.md +3 -3
  2. package/lib/command/run-multiple.js +3 -1
  3. package/lib/command/run-workers.js +32 -1
  4. package/lib/command/workers/runTests.js +2 -2
  5. package/lib/helper/Playwright.js +21 -2
  6. package/lib/helper/Puppeteer.js +18 -0
  7. package/lib/helper/WebDriver.js +140 -31
  8. package/lib/locator.js +17 -4
  9. package/lib/plugin/retryFailedStep.js +5 -1
  10. package/lib/plugin/retryTo.js +2 -2
  11. package/package.json +14 -11
  12. package/typings/index.d.ts +9 -6
  13. package/typings/promiseBasedTypes.d.ts +84 -1
  14. package/typings/types.d.ts +102 -2
  15. package/docs/advanced.md +0 -351
  16. package/docs/ai.md +0 -248
  17. package/docs/api.md +0 -323
  18. package/docs/basics.md +0 -979
  19. package/docs/bdd.md +0 -539
  20. package/docs/best.md +0 -237
  21. package/docs/books.md +0 -37
  22. package/docs/bootstrap.md +0 -135
  23. package/docs/build/ApiDataFactory.js +0 -410
  24. package/docs/build/Appium.js +0 -2027
  25. package/docs/build/Expect.js +0 -422
  26. package/docs/build/FileSystem.js +0 -228
  27. package/docs/build/GraphQL.js +0 -229
  28. package/docs/build/GraphQLDataFactory.js +0 -309
  29. package/docs/build/JSONResponse.js +0 -338
  30. package/docs/build/Mochawesome.js +0 -71
  31. package/docs/build/Nightmare.js +0 -2152
  32. package/docs/build/OpenAI.js +0 -126
  33. package/docs/build/Playwright.js +0 -5082
  34. package/docs/build/Protractor.js +0 -2706
  35. package/docs/build/Puppeteer.js +0 -3878
  36. package/docs/build/REST.js +0 -344
  37. package/docs/build/TestCafe.js +0 -2125
  38. package/docs/build/WebDriver.js +0 -4122
  39. package/docs/changelog.md +0 -2572
  40. package/docs/commands.md +0 -266
  41. package/docs/community-helpers.md +0 -58
  42. package/docs/configuration.md +0 -157
  43. package/docs/continuous-integration.md +0 -22
  44. package/docs/custom-helpers.md +0 -306
  45. package/docs/data.md +0 -379
  46. package/docs/detox.md +0 -235
  47. package/docs/docker.md +0 -136
  48. package/docs/email.md +0 -183
  49. package/docs/examples.md +0 -149
  50. package/docs/helpers/ApiDataFactory.md +0 -266
  51. package/docs/helpers/Appium.md +0 -1374
  52. package/docs/helpers/Detox.md +0 -586
  53. package/docs/helpers/Expect.md +0 -275
  54. package/docs/helpers/FileSystem.md +0 -152
  55. package/docs/helpers/GraphQL.md +0 -151
  56. package/docs/helpers/GraphQLDataFactory.md +0 -226
  57. package/docs/helpers/JSONResponse.md +0 -254
  58. package/docs/helpers/Mochawesome.md +0 -8
  59. package/docs/helpers/MockRequest.md +0 -377
  60. package/docs/helpers/Nightmare.md +0 -1305
  61. package/docs/helpers/OpenAI.md +0 -70
  62. package/docs/helpers/Playwright.md +0 -2744
  63. package/docs/helpers/Polly.md +0 -44
  64. package/docs/helpers/Protractor.md +0 -1769
  65. package/docs/helpers/Puppeteer-firefox.md +0 -86
  66. package/docs/helpers/Puppeteer.md +0 -2302
  67. package/docs/helpers/REST.md +0 -218
  68. package/docs/helpers/TestCafe.md +0 -1321
  69. package/docs/helpers/WebDriver.md +0 -2473
  70. package/docs/hooks.md +0 -340
  71. package/docs/index.md +0 -111
  72. package/docs/installation.md +0 -75
  73. package/docs/internal-api.md +0 -266
  74. package/docs/locators.md +0 -331
  75. package/docs/mobile-react-native-locators.md +0 -67
  76. package/docs/mobile.md +0 -338
  77. package/docs/pageobjects.md +0 -291
  78. package/docs/parallel.md +0 -400
  79. package/docs/playwright.md +0 -632
  80. package/docs/plugins.md +0 -1259
  81. package/docs/puppeteer.md +0 -316
  82. package/docs/quickstart.md +0 -162
  83. package/docs/react.md +0 -70
  84. package/docs/reports.md +0 -392
  85. package/docs/secrets.md +0 -36
  86. package/docs/shadow.md +0 -68
  87. package/docs/shared/keys.mustache +0 -31
  88. package/docs/shared/react.mustache +0 -1
  89. package/docs/testcafe.md +0 -174
  90. package/docs/translation.md +0 -247
  91. package/docs/tutorial.md +0 -271
  92. package/docs/typescript.md +0 -180
  93. package/docs/ui.md +0 -59
  94. package/docs/videos.md +0 -28
  95. package/docs/visual.md +0 -202
  96. package/docs/vue.md +0 -143
  97. package/docs/webapi/amOnPage.mustache +0 -11
  98. package/docs/webapi/appendField.mustache +0 -11
  99. package/docs/webapi/attachFile.mustache +0 -12
  100. package/docs/webapi/blur.mustache +0 -18
  101. package/docs/webapi/checkOption.mustache +0 -13
  102. package/docs/webapi/clearCookie.mustache +0 -9
  103. package/docs/webapi/clearField.mustache +0 -9
  104. package/docs/webapi/click.mustache +0 -25
  105. package/docs/webapi/clickLink.mustache +0 -8
  106. package/docs/webapi/closeCurrentTab.mustache +0 -7
  107. package/docs/webapi/closeOtherTabs.mustache +0 -8
  108. package/docs/webapi/dontSee.mustache +0 -11
  109. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  110. package/docs/webapi/dontSeeCookie.mustache +0 -8
  111. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  112. package/docs/webapi/dontSeeElement.mustache +0 -8
  113. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  114. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  115. package/docs/webapi/dontSeeInField.mustache +0 -11
  116. package/docs/webapi/dontSeeInSource.mustache +0 -8
  117. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  118. package/docs/webapi/doubleClick.mustache +0 -13
  119. package/docs/webapi/downloadFile.mustache +0 -12
  120. package/docs/webapi/dragAndDrop.mustache +0 -9
  121. package/docs/webapi/dragSlider.mustache +0 -11
  122. package/docs/webapi/executeAsyncScript.mustache +0 -24
  123. package/docs/webapi/executeScript.mustache +0 -26
  124. package/docs/webapi/fillField.mustache +0 -16
  125. package/docs/webapi/focus.mustache +0 -13
  126. package/docs/webapi/forceClick.mustache +0 -28
  127. package/docs/webapi/forceRightClick.mustache +0 -18
  128. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  129. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  130. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  131. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  132. package/docs/webapi/grabCookie.mustache +0 -11
  133. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  134. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  135. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  136. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  137. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  138. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  139. package/docs/webapi/grabGeoLocation.mustache +0 -8
  140. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  141. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  142. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  143. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  144. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  145. package/docs/webapi/grabPopupText.mustache +0 -5
  146. package/docs/webapi/grabSource.mustache +0 -8
  147. package/docs/webapi/grabTextFrom.mustache +0 -10
  148. package/docs/webapi/grabTextFromAll.mustache +0 -9
  149. package/docs/webapi/grabTitle.mustache +0 -8
  150. package/docs/webapi/grabValueFrom.mustache +0 -9
  151. package/docs/webapi/grabValueFromAll.mustache +0 -8
  152. package/docs/webapi/grabWebElement.mustache +0 -9
  153. package/docs/webapi/grabWebElements.mustache +0 -9
  154. package/docs/webapi/moveCursorTo.mustache +0 -12
  155. package/docs/webapi/openNewTab.mustache +0 -7
  156. package/docs/webapi/pressKey.mustache +0 -12
  157. package/docs/webapi/pressKeyDown.mustache +0 -12
  158. package/docs/webapi/pressKeyUp.mustache +0 -12
  159. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  160. package/docs/webapi/refreshPage.mustache +0 -6
  161. package/docs/webapi/resizeWindow.mustache +0 -6
  162. package/docs/webapi/rightClick.mustache +0 -14
  163. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  164. package/docs/webapi/saveScreenshot.mustache +0 -12
  165. package/docs/webapi/say.mustache +0 -10
  166. package/docs/webapi/scrollIntoView.mustache +0 -11
  167. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  168. package/docs/webapi/scrollPageToTop.mustache +0 -6
  169. package/docs/webapi/scrollTo.mustache +0 -12
  170. package/docs/webapi/see.mustache +0 -11
  171. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  172. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  173. package/docs/webapi/seeCookie.mustache +0 -8
  174. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  175. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  176. package/docs/webapi/seeElement.mustache +0 -8
  177. package/docs/webapi/seeElementInDOM.mustache +0 -8
  178. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  179. package/docs/webapi/seeInField.mustache +0 -12
  180. package/docs/webapi/seeInPopup.mustache +0 -8
  181. package/docs/webapi/seeInSource.mustache +0 -7
  182. package/docs/webapi/seeInTitle.mustache +0 -8
  183. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  184. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  185. package/docs/webapi/seeTextEquals.mustache +0 -9
  186. package/docs/webapi/seeTitleEquals.mustache +0 -8
  187. package/docs/webapi/selectOption.mustache +0 -21
  188. package/docs/webapi/setCookie.mustache +0 -16
  189. package/docs/webapi/setGeoLocation.mustache +0 -12
  190. package/docs/webapi/switchTo.mustache +0 -9
  191. package/docs/webapi/switchToNextTab.mustache +0 -10
  192. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  193. package/docs/webapi/type.mustache +0 -21
  194. package/docs/webapi/uncheckOption.mustache +0 -13
  195. package/docs/webapi/wait.mustache +0 -8
  196. package/docs/webapi/waitForClickable.mustache +0 -11
  197. package/docs/webapi/waitForDetached.mustache +0 -10
  198. package/docs/webapi/waitForElement.mustache +0 -11
  199. package/docs/webapi/waitForEnabled.mustache +0 -6
  200. package/docs/webapi/waitForFunction.mustache +0 -17
  201. package/docs/webapi/waitForInvisible.mustache +0 -10
  202. package/docs/webapi/waitForText.mustache +0 -13
  203. package/docs/webapi/waitForValue.mustache +0 -10
  204. package/docs/webapi/waitForVisible.mustache +0 -10
  205. package/docs/webapi/waitInUrl.mustache +0 -9
  206. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  207. package/docs/webapi/waitToHide.mustache +0 -10
  208. package/docs/webapi/waitUrlEquals.mustache +0 -10
  209. package/docs/webdriver.md +0 -655
  210. package/docs/wiki/Books-&-Posts.md +0 -27
  211. package/docs/wiki/Community-Helpers-&-Plugins.md +0 -53
  212. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -61
  213. package/docs/wiki/Examples.md +0 -145
  214. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
  215. package/docs/wiki/Home.md +0 -16
  216. package/docs/wiki/Migration-to-Appium-v2---CodeceptJS.md +0 -83
  217. package/docs/wiki/Release-Process.md +0 -24
  218. package/docs/wiki/Roadmap.md +0 -23
  219. package/docs/wiki/Tests.md +0 -1393
  220. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
  221. package/docs/wiki/Videos.md +0 -19
@@ -1,229 +0,0 @@
1
- const axios = require('axios').default;
2
- const Helper = require('@codeceptjs/helper');
3
-
4
- /**
5
- * GraphQL helper allows to send additional requests to a GraphQl endpoint during acceptance tests.
6
- * [Axios](https://github.com/axios/axios) library is used to perform requests.
7
- *
8
- * ## Configuration
9
- *
10
- * * endpoint: GraphQL base URL
11
- * * timeout: timeout for requests in milliseconds. 10000ms by default
12
- * * defaultHeaders: a list of default headers
13
- * * onRequest: a async function which can update request object.
14
- *
15
- * ## Example
16
- *
17
- * ```js
18
- * GraphQL: {
19
- * endpoint: 'http://site.com/graphql/',
20
- * onRequest: (request) => {
21
- * request.headers.auth = '123';
22
- * }
23
- * }
24
- * ```
25
- *
26
- * ## Access From Helpers
27
- *
28
- * Send GraphQL requests by accessing `_executeQuery` method:
29
- *
30
- * ```js
31
- * this.helpers['GraphQL']._executeQuery({
32
- * url,
33
- * data,
34
- * });
35
- * ```
36
- *
37
- * ## Methods
38
- */
39
- class GraphQL extends Helper {
40
- constructor(config) {
41
- super(config);
42
- this.axios = axios.create();
43
- this.headers = {};
44
- this.options = {
45
- timeout: 10000,
46
- defaultHeaders: {},
47
- endpoint: '',
48
- };
49
- this.options = Object.assign(this.options, config);
50
- this.headers = { ...this.options.defaultHeaders };
51
- this.axios.defaults.headers = this.options.defaultHeaders;
52
- }
53
-
54
- static _checkRequirements() {
55
- try {
56
- require('axios');
57
- } catch (e) {
58
- return ['axios'];
59
- }
60
- }
61
-
62
- static _config() {
63
- return [
64
- { name: 'endpoint', message: 'Endpoint of API you are going to test', default: 'http://localhost:3000/graphql' },
65
- ];
66
- }
67
-
68
- /**
69
- * Executes query via axios call
70
- *
71
- * @param {object} request
72
- */
73
- async _executeQuery(request) {
74
- this.axios.defaults.timeout = request.timeout || this.options.timeout;
75
-
76
- if (this.headers && this.headers.auth) {
77
- request.auth = this.headers.auth;
78
- }
79
-
80
- request.headers = Object.assign(request.headers, {
81
- 'Content-Type': 'application/json',
82
- });
83
-
84
- request.headers = { ...this.headers, ...request.headers };
85
-
86
- if (this.config.onRequest) {
87
- await this.config.onRequest(request);
88
- }
89
-
90
- this.debugSection('Request', JSON.stringify(request));
91
-
92
- let response;
93
- try {
94
- response = await this.axios(request);
95
- } catch (err) {
96
- if (!err.response) throw err;
97
- this.debugSection(
98
- 'Response',
99
- `Response error. Status code: ${err.response.status}`,
100
- );
101
- response = err.response;
102
- }
103
-
104
- if (this.config.onResponse) {
105
- await this.config.onResponse(response);
106
- }
107
-
108
- this.debugSection('Response', JSON.stringify(response.data));
109
- return response;
110
- }
111
-
112
- /**
113
- * Prepares request for axios call
114
- *
115
- * @param {object} operation
116
- * @param {object} headers
117
- * @return {object} graphQLRequest
118
- */
119
- _prepareGraphQLRequest(operation, headers) {
120
- return {
121
- baseURL: this.options.endpoint,
122
- method: 'POST',
123
- data: operation,
124
- headers,
125
- };
126
- }
127
-
128
- /**
129
- * Send query to GraphQL endpoint over http.
130
- * Returns a response as a promise.
131
- *
132
- * ```js
133
- *
134
- * const response = await I.sendQuery('{ users { name email }}');
135
- * // with variables
136
- * const response = await I.sendQuery(
137
- * 'query getUser($id: ID) { user(id: $id) { name email }}',
138
- * { id: 1 },
139
- * )
140
- * const user = response.data.data;
141
- * ```
142
- *
143
- * @param {String} query
144
- * @param {object} [variables] that may go along with the query
145
- * @param {object} [options] are additional query options
146
- * @param {object} [headers]
147
- * @return Promise<any>
148
- */
149
- async sendQuery(query, variables, options = {}, headers = {}) {
150
- if (typeof query !== 'string') {
151
- throw new Error(`query expected to be a String, instead received ${typeof query}`);
152
- }
153
- const operation = {
154
- query,
155
- variables,
156
- ...options,
157
- };
158
- const request = this._prepareGraphQLRequest(operation, headers);
159
- return this._executeQuery(request);
160
- }
161
-
162
- /**
163
- * Send query to GraphQL endpoint over http
164
- *
165
- * ```js
166
- * I.sendMutation(`
167
- * mutation createUser($user: UserInput!) {
168
- * createUser(user: $user) {
169
- * id
170
- * name
171
- * email
172
- * }
173
- * }
174
- * `,
175
- * { user: {
176
- * name: 'John Doe',
177
- * email: 'john@xmail.com'
178
- * }
179
- * },
180
- * });
181
- * ```
182
- *
183
- * @param {String} mutation
184
- * @param {object} [variables] that may go along with the mutation
185
- * @param {object} [options] are additional query options
186
- * @param {object} [headers]
187
- * @return Promise<any>
188
- */
189
- async sendMutation(mutation, variables, options = {}, headers = {}) {
190
- if (typeof mutation !== 'string') {
191
- throw new Error(`mutation expected to be a String, instead received ${typeof mutation}`);
192
- }
193
- const operation = {
194
- query: mutation,
195
- variables,
196
- ...options,
197
- };
198
- const request = this._prepareGraphQLRequest(operation, headers);
199
- return this._executeQuery(request);
200
- }
201
-
202
- _setRequestTimeout(newTimeout) {
203
- this.options.timeout = newTimeout;
204
- }
205
-
206
- /**
207
- * Sets request headers for all requests of this test
208
- *
209
- * @param {object} headers headers list
210
- */
211
- haveRequestHeaders(headers) {
212
- this.headers = { ...this.headers, ...headers };
213
- }
214
-
215
- /**
216
- * Adds a header for Bearer authentication
217
- *
218
- * ```js
219
- * // we use secret function to hide token from logs
220
- * I.amBearerAuthenticated(secret('heregoestoken'))
221
- * ```
222
- *
223
- * @param {string | CodeceptJS.Secret} accessToken Bearer access token
224
- */
225
- amBearerAuthenticated(accessToken) {
226
- this.haveRequestHeaders({ Authorization: `Bearer ${accessToken}` });
227
- }
228
- }
229
- module.exports = GraphQL;
@@ -1,309 +0,0 @@
1
- const path = require('path');
2
-
3
- const Helper = require('@codeceptjs/helper');
4
- const GraphQL = require('./GraphQL');
5
-
6
- /**
7
- * Helper for managing remote data using GraphQL queries.
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 GraphQL queries 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
- * If a web application has GraphQL support, it can be used to create and delete test records.
21
- * By combining GraphQL with Factories you can easily create records for tests:
22
- *
23
- * ```js
24
- * I.mutateData('createUser', { name: 'davert', email: 'davert@mail.com' });
25
- * let user = await I.mutateData('createUser', { name: 'davert'});
26
- * I.mutateMultiple('createPost', 3, {post_id: user.id});
27
- * ```
28
- *
29
- * To make this work you need
30
- *
31
- * 1. GraphQL 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 Users factories:
45
- *
46
- * ```js
47
- * // tests/factories/users.js
48
- *
49
- * const { Factory } = require('rosie').Factory;
50
- * const { faker } = require('@faker-js/faker');
51
- *
52
- * // Used with a constructor function passed to Factory, so that the final build
53
- * // object matches the necessary pattern to be sent as the variables object.
54
- * module.exports = new Factory((buildObj) => ({
55
- * input: { ...buildObj },
56
- * }))
57
- * // 'attr'-id can be left out depending on the GraphQl resolvers
58
- * .attr('name', () => faker.name.findName())
59
- * .attr('email', () => faker.interact.email())
60
- * ```
61
- * For more options see [rosie documentation](https://github.com/rosiejs/rosie).
62
- *
63
- * Then configure GraphQLDataHelper to match factories and GraphQL schema:
64
-
65
- * ### Configuration
66
- *
67
- * GraphQLDataFactory has following config options:
68
- *
69
- * * `endpoint`: URL for the GraphQL server.
70
- * * `cleanup` (default: true): should inserted records be deleted up after tests
71
- * * `factories`: list of defined factories
72
- * * `headers`: list of headers
73
- * * `GraphQL`: configuration for GraphQL requests.
74
- *
75
- *
76
- * See the example:
77
- *
78
- * ```js
79
- * GraphQLDataFactory: {
80
- * endpoint: "http://user.com/graphql",
81
- * cleanup: true,
82
- * headers: {
83
- * 'Content-Type': 'application/json',
84
- * 'Accept': 'application/json',
85
- * },
86
- * factories: {
87
- * createUser: {
88
- * query: 'mutation createUser($input: UserInput!) { createUser(input: $input) { id name }}',
89
- * factory: './factories/users',
90
- * revert: (data) => ({
91
- * query: 'mutation deleteUser($id: ID!) { deleteUser(id: $id) }',
92
- * variables: { id : data.id},
93
- * }),
94
- * },
95
- * }
96
- * }
97
- * ```
98
-
99
- * It is required to set GraphQL `endpoint` which is the URL to which all the queries go to.
100
- * Factory file is expected to be passed via `factory` option.
101
- *
102
- * This Helper uses [GraphQL](http://codecept.io/helpers/GraphQL/) helper and accepts its configuration in "GraphQL" section.
103
- * For instance, to set timeout you should add:
104
- *
105
- * ```js
106
- * "GraphQLDataFactory": {
107
- * "GraphQL": {
108
- * "timeout": "100000",
109
- * }
110
- * }
111
- * ```
112
- *
113
- * ### Factory
114
- *
115
- * Factory contains operations -
116
- *
117
- * * `operation`: The operation/mutation that needs to be performed for creating a record in the backend.
118
- *
119
- * Each operation must have the following:
120
- *
121
- * * `query`: The mutation(query) string. It is expected to use variables to send data with the query.
122
- * * `factory`: The path to factory file. The object built by the factory in this file will be passed
123
- * as the 'variables' object to go along with the mutation.
124
- * * `revert`: A function called with the data returned when an item is created. The object returned by
125
- * this function is will be used to later delete the items created. So, make sure RELEVANT DATA IS RETURNED
126
- * when a record is created by a mutation.
127
- *
128
- * ### Requests
129
- *
130
- * Requests can be updated on the fly by using `onRequest` function. For instance, you can pass in current session from a cookie.
131
- *
132
- * ```js
133
- * onRequest: async (request) => {
134
- * // using global codeceptjs instance
135
- * let cookie = await codeceptjs.container.helpers('WebDriver').grabCookie('session');
136
- * request.headers = { Cookie: `session=${cookie.value}` };
137
- * }
138
- * ```
139
- *
140
- * ### Responses
141
- *
142
- * By default `I.mutateData()` returns a promise with created data as specified in operation query string:
143
- *
144
- * ```js
145
- * let client = await I.mutateData('createClient');
146
- * ```
147
- *
148
- * Data of created records are collected and used in the end of a test for the cleanup.
149
- *
150
- * ## Methods
151
- */
152
- class GraphQLDataFactory extends Helper {
153
- constructor(config) {
154
- super(config);
155
-
156
- const defaultConfig = {
157
- cleanup: true,
158
- GraphQL: {},
159
- factories: {},
160
- };
161
- this.config = Object.assign(defaultConfig, this.config);
162
-
163
- if (this.config.headers) {
164
- this.config.GraphQL.defaultHeaders = this.config.headers;
165
- }
166
- if (this.config.onRequest) {
167
- this.config.GraphQL.onRequest = this.config.onRequest;
168
- }
169
- this.graphqlHelper = new GraphQL(Object.assign(this.config.GraphQL, { endpoint: this.config.endpoint }));
170
- this.factories = this.config.factories;
171
-
172
- this.created = {};
173
- Object.keys(this.factories).forEach(f => (this.created[f] = []));
174
- }
175
-
176
- static _checkRequirements() {
177
- try {
178
- require('axios');
179
- require('rosie');
180
- } catch (e) {
181
- return ['axios', 'rosie'];
182
- }
183
- }
184
-
185
- _after() {
186
- if (!this.config.cleanup) {
187
- return Promise.resolve();
188
- }
189
- const promises = [];
190
- // clean up all created items
191
- for (const mutationName in this.created) {
192
- const createdItems = this.created[mutationName];
193
- if (!createdItems.length) continue;
194
- this.debug(`Deleting ${createdItems.length} ${mutationName}(s)`);
195
- for (const itemData of createdItems) {
196
- promises.push(this._requestDelete(mutationName, itemData));
197
- }
198
- }
199
- return Promise.all(promises);
200
- }
201
-
202
- /**
203
- * Generates a new record using factory, sends a GraphQL mutation to store it.
204
- *
205
- * ```js
206
- * // create a user
207
- * I.mutateData('createUser');
208
- * // create user with defined email
209
- * // and receive it when inside async function
210
- * const user = await I.mutateData('createUser', { email: 'user@user.com'});
211
- * ```
212
- *
213
- * @param {string} operation to be performed
214
- * @param {*} params predefined parameters
215
- */
216
- mutateData(operation, params) {
217
- const variables = this._createItem(operation, params);
218
- this.debug(`Creating ${operation} ${JSON.stringify(variables)}`);
219
- return this._requestCreate(operation, variables);
220
- }
221
-
222
- /**
223
- * Generates bunch of records and sends multiple GraphQL mutation requests to store them.
224
- *
225
- * ```js
226
- * // create 3 users
227
- * I.mutateMultiple('createUser', 3);
228
- *
229
- * // create 3 users of same age
230
- * I.mutateMultiple('createUser', 3, { age: 25 });
231
- * ```
232
- *
233
- * @param {string} operation
234
- * @param {number} times
235
- * @param {*} params
236
- */
237
- mutateMultiple(operation, times, params) {
238
- const promises = [];
239
- for (let i = 0; i < times; i++) {
240
- promises.push(this.mutateData(operation, params));
241
- }
242
- return Promise.all(promises);
243
- }
244
-
245
- _createItem(operation, data) {
246
- if (!this.factories[operation]) {
247
- throw new Error(`Mutation ${operation} is not defined in config.factories`);
248
- }
249
- let modulePath = this.factories[operation].factory;
250
- try {
251
- try {
252
- require.resolve(modulePath);
253
- } catch (e) {
254
- modulePath = path.join(global.codecept_dir, modulePath);
255
- }
256
- const builder = require(modulePath);
257
- return builder.build(data);
258
- } catch (err) {
259
- throw new Error(`Couldn't load factory file from ${modulePath}, check that
260
-
261
- "factories": {
262
- "${operation}": {
263
- "factory": "./path/to/factory"
264
-
265
- points to valid factory file.
266
- Factory file should export an object with build method.
267
-
268
- Current file error: ${err.message}`);
269
- }
270
- }
271
-
272
- /**
273
- * Executes request to create a record to the GraphQL endpoint.
274
- * Can be replaced from a custom helper.
275
- *
276
- * @param {string} operation
277
- * @param {*} variables to be sent along with the query
278
- */
279
- _requestCreate(operation, variables) {
280
- const { query } = this.factories[operation];
281
- return this.graphqlHelper.sendMutation(query, variables).then((response) => {
282
- const data = response.data.data[operation];
283
- this.created[operation].push(data);
284
- this.debugSection('Created', `record: ${data}`);
285
- return data;
286
- });
287
- }
288
-
289
- /**
290
- * Executes request to delete a record to the GraphQL endpoint.
291
- * Can be replaced from a custom helper.
292
- *
293
- * @param {string} operation
294
- * @param {*} data of the record to be deleted.
295
- */
296
- _requestDelete(operation, data) {
297
- const deleteOperation = this.factories[operation].revert(data);
298
- const { query, variables } = deleteOperation;
299
-
300
- return this.graphqlHelper.sendMutation(query, variables)
301
- .then((response) => {
302
- const idx = this.created[operation].indexOf(data);
303
- this.debugSection('Deleted', `record: ${response.data.data}`);
304
- this.created[operation].splice(idx, 1);
305
- });
306
- }
307
- }
308
-
309
- module.exports = GraphQLDataFactory;