codeceptjs 3.5.0 → 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 (273) hide show
  1. package/README.md +24 -25
  2. package/lib/actor.js +6 -3
  3. package/lib/ai.js +12 -3
  4. package/lib/cli.js +12 -2
  5. package/lib/codecept.js +4 -0
  6. package/lib/colorUtils.js +10 -0
  7. package/lib/command/definitions.js +2 -7
  8. package/lib/command/dryRun.js +2 -1
  9. package/lib/command/info.js +24 -0
  10. package/lib/command/init.js +51 -5
  11. package/lib/command/run-multiple/collection.js +17 -5
  12. package/lib/command/run-multiple.js +4 -2
  13. package/lib/command/run-workers.js +66 -4
  14. package/lib/command/run.js +7 -0
  15. package/lib/command/workers/runTests.js +39 -0
  16. package/lib/data/context.js +14 -6
  17. package/lib/event.js +4 -0
  18. package/lib/helper/ApiDataFactory.js +2 -1
  19. package/lib/helper/Appium.js +73 -24
  20. package/lib/helper/Expect.js +422 -0
  21. package/lib/helper/FileSystem.js +1 -1
  22. package/lib/helper/GraphQL.js +25 -0
  23. package/lib/helper/Nightmare.js +9 -4
  24. package/lib/helper/OpenAI.js +14 -10
  25. package/lib/helper/Playwright.js +1205 -288
  26. package/lib/helper/Protractor.js +11 -6
  27. package/lib/helper/Puppeteer.js +173 -61
  28. package/lib/helper/TestCafe.js +44 -9
  29. package/lib/helper/WebDriver.js +231 -82
  30. package/lib/helper/errors/ElementNotFound.js +2 -1
  31. package/lib/helper/extras/PlaywrightReactVueLocator.js +38 -0
  32. package/lib/helper/scripts/blurElement.js +17 -0
  33. package/lib/helper/scripts/focusElement.js +17 -0
  34. package/lib/helper/scripts/highlightElement.js +2 -2
  35. package/lib/html.js +3 -3
  36. package/lib/interfaces/bdd.js +1 -1
  37. package/lib/interfaces/gherkin.js +37 -3
  38. package/lib/interfaces/scenarioConfig.js +1 -0
  39. package/lib/locator.js +17 -4
  40. package/lib/mochaFactory.js +2 -1
  41. package/lib/output.js +1 -1
  42. package/lib/pause.js +12 -9
  43. package/lib/plugin/autoLogin.js +45 -10
  44. package/lib/plugin/heal.js +47 -17
  45. package/lib/plugin/retryFailedStep.js +10 -1
  46. package/lib/plugin/retryTo.js +2 -4
  47. package/lib/plugin/selenoid.js +6 -1
  48. package/lib/plugin/standardActingHelpers.js +0 -2
  49. package/lib/plugin/stepByStepReport.js +2 -2
  50. package/lib/plugin/tryTo.js +5 -7
  51. package/lib/plugin/wdio.js +0 -1
  52. package/lib/recorder.js +20 -9
  53. package/lib/session.js +1 -1
  54. package/lib/step.js +30 -11
  55. package/lib/ui.js +1 -0
  56. package/lib/utils.js +18 -1
  57. package/lib/workers.js +28 -3
  58. package/package.json +108 -98
  59. package/translations/de-DE.js +5 -0
  60. package/translations/fr-FR.js +14 -1
  61. package/translations/it-IT.js +1 -0
  62. package/translations/ja-JP.js +5 -0
  63. package/translations/pl-PL.js +5 -0
  64. package/translations/pt-BR.js +1 -0
  65. package/translations/ru-RU.js +1 -0
  66. package/translations/zh-CN.js +5 -0
  67. package/translations/zh-TW.js +5 -0
  68. package/typings/index.d.ts +8 -6
  69. package/typings/promiseBasedTypes.d.ts +784 -822
  70. package/typings/types.d.ts +1214 -727
  71. package/CHANGELOG.md +0 -2492
  72. package/docs/advanced.md +0 -351
  73. package/docs/ai.md +0 -246
  74. package/docs/api.md +0 -323
  75. package/docs/basics.md +0 -980
  76. package/docs/bdd.md +0 -535
  77. package/docs/best.md +0 -237
  78. package/docs/books.md +0 -37
  79. package/docs/bootstrap.md +0 -135
  80. package/docs/build/ApiDataFactory.js +0 -409
  81. package/docs/build/Appium.js +0 -1978
  82. package/docs/build/FileSystem.js +0 -228
  83. package/docs/build/GraphQL.js +0 -204
  84. package/docs/build/GraphQLDataFactory.js +0 -309
  85. package/docs/build/JSONResponse.js +0 -338
  86. package/docs/build/Mochawesome.js +0 -71
  87. package/docs/build/Nightmare.js +0 -2147
  88. package/docs/build/OpenAI.js +0 -122
  89. package/docs/build/Playwright.js +0 -4134
  90. package/docs/build/Polly.js +0 -42
  91. package/docs/build/Protractor.js +0 -2701
  92. package/docs/build/Puppeteer.js +0 -3743
  93. package/docs/build/REST.js +0 -344
  94. package/docs/build/SeleniumWebdriver.js +0 -76
  95. package/docs/build/TestCafe.js +0 -2059
  96. package/docs/build/WebDriver.js +0 -4042
  97. package/docs/changelog.md +0 -2501
  98. package/docs/commands.md +0 -254
  99. package/docs/community-helpers.md +0 -58
  100. package/docs/configuration.md +0 -157
  101. package/docs/continuous-integration.md +0 -22
  102. package/docs/custom-helpers.md +0 -306
  103. package/docs/data.md +0 -375
  104. package/docs/detox.md +0 -235
  105. package/docs/docker.md +0 -137
  106. package/docs/email.md +0 -183
  107. package/docs/examples.md +0 -149
  108. package/docs/helpers/ApiDataFactory.md +0 -266
  109. package/docs/helpers/Appium.md +0 -1317
  110. package/docs/helpers/Detox.md +0 -586
  111. package/docs/helpers/FileSystem.md +0 -152
  112. package/docs/helpers/GraphQL.md +0 -130
  113. package/docs/helpers/GraphQLDataFactory.md +0 -226
  114. package/docs/helpers/JSONResponse.md +0 -254
  115. package/docs/helpers/Mochawesome.md +0 -8
  116. package/docs/helpers/MockRequest.md +0 -377
  117. package/docs/helpers/Nightmare.md +0 -1258
  118. package/docs/helpers/OpenAI.md +0 -70
  119. package/docs/helpers/Playwright.md +0 -2250
  120. package/docs/helpers/Polly.md +0 -44
  121. package/docs/helpers/Puppeteer-firefox.md +0 -86
  122. package/docs/helpers/Puppeteer.md +0 -2147
  123. package/docs/helpers/REST.md +0 -218
  124. package/docs/helpers/TestCafe.md +0 -1224
  125. package/docs/helpers/WebDriver.md +0 -2325
  126. package/docs/hooks.md +0 -340
  127. package/docs/index.md +0 -111
  128. package/docs/installation.md +0 -75
  129. package/docs/internal-api.md +0 -265
  130. package/docs/locators.md +0 -331
  131. package/docs/mobile-react-native-locators.md +0 -67
  132. package/docs/mobile.md +0 -344
  133. package/docs/nightmare.md +0 -223
  134. package/docs/pageobjects.md +0 -291
  135. package/docs/parallel.md +0 -288
  136. package/docs/playwright.md +0 -609
  137. package/docs/plugins.md +0 -1225
  138. package/docs/puppeteer.md +0 -316
  139. package/docs/quickstart.md +0 -163
  140. package/docs/react.md +0 -69
  141. package/docs/reports.md +0 -392
  142. package/docs/secrets.md +0 -36
  143. package/docs/shadow.md +0 -68
  144. package/docs/shared/keys.mustache +0 -31
  145. package/docs/shared/react.mustache +0 -1
  146. package/docs/testcafe.md +0 -174
  147. package/docs/translation.md +0 -247
  148. package/docs/tutorial.md +0 -271
  149. package/docs/typescript.md +0 -180
  150. package/docs/ui.md +0 -59
  151. package/docs/videos.md +0 -28
  152. package/docs/visual.md +0 -202
  153. package/docs/vue.md +0 -121
  154. package/docs/webapi/amOnPage.mustache +0 -11
  155. package/docs/webapi/appendField.mustache +0 -11
  156. package/docs/webapi/attachFile.mustache +0 -12
  157. package/docs/webapi/checkOption.mustache +0 -13
  158. package/docs/webapi/clearCookie.mustache +0 -10
  159. package/docs/webapi/clearField.mustache +0 -9
  160. package/docs/webapi/click.mustache +0 -25
  161. package/docs/webapi/clickLink.mustache +0 -8
  162. package/docs/webapi/closeCurrentTab.mustache +0 -7
  163. package/docs/webapi/closeOtherTabs.mustache +0 -8
  164. package/docs/webapi/dontSee.mustache +0 -11
  165. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  166. package/docs/webapi/dontSeeCookie.mustache +0 -8
  167. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  168. package/docs/webapi/dontSeeElement.mustache +0 -8
  169. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  170. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  171. package/docs/webapi/dontSeeInField.mustache +0 -11
  172. package/docs/webapi/dontSeeInSource.mustache +0 -8
  173. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  174. package/docs/webapi/doubleClick.mustache +0 -13
  175. package/docs/webapi/downloadFile.mustache +0 -12
  176. package/docs/webapi/dragAndDrop.mustache +0 -9
  177. package/docs/webapi/dragSlider.mustache +0 -11
  178. package/docs/webapi/executeAsyncScript.mustache +0 -24
  179. package/docs/webapi/executeScript.mustache +0 -26
  180. package/docs/webapi/fillField.mustache +0 -16
  181. package/docs/webapi/forceClick.mustache +0 -28
  182. package/docs/webapi/forceRightClick.mustache +0 -18
  183. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  184. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  185. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  186. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  187. package/docs/webapi/grabCookie.mustache +0 -11
  188. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  189. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  190. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  191. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  192. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  193. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  194. package/docs/webapi/grabGeoLocation.mustache +0 -8
  195. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  196. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  197. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  198. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  199. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  200. package/docs/webapi/grabPopupText.mustache +0 -5
  201. package/docs/webapi/grabSource.mustache +0 -8
  202. package/docs/webapi/grabTextFrom.mustache +0 -10
  203. package/docs/webapi/grabTextFromAll.mustache +0 -9
  204. package/docs/webapi/grabTitle.mustache +0 -8
  205. package/docs/webapi/grabValueFrom.mustache +0 -9
  206. package/docs/webapi/grabValueFromAll.mustache +0 -8
  207. package/docs/webapi/moveCursorTo.mustache +0 -12
  208. package/docs/webapi/openNewTab.mustache +0 -7
  209. package/docs/webapi/pressKey.mustache +0 -12
  210. package/docs/webapi/pressKeyDown.mustache +0 -12
  211. package/docs/webapi/pressKeyUp.mustache +0 -12
  212. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  213. package/docs/webapi/refreshPage.mustache +0 -6
  214. package/docs/webapi/resizeWindow.mustache +0 -6
  215. package/docs/webapi/rightClick.mustache +0 -14
  216. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  217. package/docs/webapi/saveScreenshot.mustache +0 -12
  218. package/docs/webapi/say.mustache +0 -10
  219. package/docs/webapi/scrollIntoView.mustache +0 -11
  220. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  221. package/docs/webapi/scrollPageToTop.mustache +0 -6
  222. package/docs/webapi/scrollTo.mustache +0 -12
  223. package/docs/webapi/see.mustache +0 -11
  224. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  225. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  226. package/docs/webapi/seeCookie.mustache +0 -8
  227. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  228. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  229. package/docs/webapi/seeElement.mustache +0 -8
  230. package/docs/webapi/seeElementInDOM.mustache +0 -8
  231. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  232. package/docs/webapi/seeInField.mustache +0 -12
  233. package/docs/webapi/seeInPopup.mustache +0 -8
  234. package/docs/webapi/seeInSource.mustache +0 -7
  235. package/docs/webapi/seeInTitle.mustache +0 -8
  236. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  237. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  238. package/docs/webapi/seeTextEquals.mustache +0 -9
  239. package/docs/webapi/seeTitleEquals.mustache +0 -8
  240. package/docs/webapi/selectOption.mustache +0 -21
  241. package/docs/webapi/setCookie.mustache +0 -16
  242. package/docs/webapi/setGeoLocation.mustache +0 -12
  243. package/docs/webapi/switchTo.mustache +0 -9
  244. package/docs/webapi/switchToNextTab.mustache +0 -10
  245. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  246. package/docs/webapi/type.mustache +0 -21
  247. package/docs/webapi/uncheckOption.mustache +0 -13
  248. package/docs/webapi/wait.mustache +0 -8
  249. package/docs/webapi/waitForClickable.mustache +0 -11
  250. package/docs/webapi/waitForDetached.mustache +0 -10
  251. package/docs/webapi/waitForElement.mustache +0 -11
  252. package/docs/webapi/waitForEnabled.mustache +0 -6
  253. package/docs/webapi/waitForFunction.mustache +0 -17
  254. package/docs/webapi/waitForInvisible.mustache +0 -10
  255. package/docs/webapi/waitForText.mustache +0 -13
  256. package/docs/webapi/waitForValue.mustache +0 -10
  257. package/docs/webapi/waitForVisible.mustache +0 -10
  258. package/docs/webapi/waitInUrl.mustache +0 -9
  259. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  260. package/docs/webapi/waitToHide.mustache +0 -10
  261. package/docs/webapi/waitUrlEquals.mustache +0 -10
  262. package/docs/webdriver.md +0 -657
  263. package/docs/wiki/Books-&-Posts.md +0 -27
  264. package/docs/wiki/Community-Helpers-&-Plugins.md +0 -49
  265. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -29
  266. package/docs/wiki/Examples.md +0 -139
  267. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
  268. package/docs/wiki/Home.md +0 -16
  269. package/docs/wiki/Release-Process.md +0 -24
  270. package/docs/wiki/Roadmap.md +0 -23
  271. package/docs/wiki/Tests.md +0 -1393
  272. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
  273. package/docs/wiki/Videos.md +0 -19
@@ -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;
@@ -1,338 +0,0 @@
1
- const assert = require('assert');
2
- const chai = require('chai');
3
- const joi = require('joi');
4
- const chaiDeepMatch = require('chai-deep-match');
5
- const Helper = require('@codeceptjs/helper');
6
-
7
- chai.use(chaiDeepMatch);
8
-
9
- const { expect } = chai;
10
-
11
- /**
12
- * This helper allows performing assertions on JSON responses paired with following helpers:
13
- *
14
- * * REST
15
- * * GraphQL
16
- * * Playwright
17
- *
18
- * It can check status codes, response data, response structure.
19
- *
20
- *
21
- * ## Configuration
22
- *
23
- * * `requestHelper` - a helper which will perform requests. `REST` by default, also `Playwright` or `GraphQL` can be used. Custom helpers must have `onResponse` hook in their config, which will be executed when request is performed.
24
- *
25
- * ### Examples
26
- *
27
- * Zero-configuration when paired with REST:
28
- *
29
- * ```js
30
- * // inside codecept.conf.js
31
- *{
32
- * helpers: {
33
- * REST: {
34
- * endpoint: 'http://site.com/api',
35
- * },
36
- * JSONResponse: {}
37
- * }
38
- *}
39
- * ```
40
- * Explicitly setting request helper if you use `makeApiRequest` of Playwright to perform requests and not paired REST:
41
- *
42
- * ```js
43
- * // inside codecept.conf.js
44
- * // ...
45
- * helpers: {
46
- * Playwright: {
47
- * url: 'https://localhost',
48
- * browser: 'chromium',
49
- * },
50
- * JSONResponse: {
51
- * requestHelper: 'Playwright',
52
- * }
53
- * }
54
- * ```
55
- * ## Access From Helpers
56
- *
57
- * If you plan to add custom assertions it is recommended to create a helper that will retrieve response object from JSONResponse:
58
- *
59
- *
60
- * ```js
61
- * // inside custom helper
62
- * const response = this.helpers.JSONResponse.response;
63
- * ```
64
- *
65
- * ## Methods
66
- */
67
- class JSONResponse extends Helper {
68
- constructor(config = {}) {
69
- super(config);
70
- this.options = {
71
- requestHelper: 'REST',
72
- };
73
- this.options = { ...this.options, ...config };
74
- }
75
-
76
- _beforeSuite() {
77
- this.response = null;
78
- if (!this.helpers[this.options.requestHelper]) {
79
- throw new Error(`Error setting JSONResponse, helper ${this.options.requestHelper} is not enabled in config, helpers: ${Object.keys(this.helpers)}`);
80
- }
81
- // connect to REST helper
82
- this.helpers[this.options.requestHelper].config.onResponse = (response) => {
83
- this.response = response;
84
- };
85
- }
86
-
87
- _before() {
88
- this.response = null;
89
- }
90
-
91
- static _checkRequirements() {
92
- try {
93
- require('joi');
94
- require('chai');
95
- } catch (e) {
96
- return ['joi'];
97
- }
98
- }
99
-
100
- /**
101
- * Checks that response code is equal to the provided one
102
- *
103
- * ```js
104
- * I.seeResponseCodeIs(200);
105
- * ```
106
- *
107
- * @param {number} code
108
- */
109
- seeResponseCodeIs(code) {
110
- this._checkResponseReady();
111
- expect(this.response.status).to.eql(code, 'Response code is not the same as expected');
112
- }
113
-
114
- /**
115
- * Checks that response code is not equal to the provided one
116
- *
117
- * ```js
118
- * I.dontSeeResponseCodeIs(500);
119
- * ```
120
- *
121
- * @param {number} code
122
- */
123
- dontSeeResponseCodeIs(code) {
124
- this._checkResponseReady();
125
- expect(this.response.status).not.to.eql(code);
126
- }
127
-
128
- /**
129
- * Checks that the response code is 4xx
130
- */
131
- seeResponseCodeIsClientError() {
132
- this._checkResponseReady();
133
- expect(this.response.status).to.be.gte(400);
134
- expect(this.response.status).to.be.lt(500);
135
- }
136
-
137
- /**
138
- * Checks that the response code is 3xx
139
- */
140
- seeResponseCodeIsRedirection() {
141
- this._checkResponseReady();
142
- expect(this.response.status).to.be.gte(300);
143
- expect(this.response.status).to.be.lt(400);
144
- }
145
-
146
- /**
147
- * Checks that the response code is 5xx
148
- */
149
- seeResponseCodeIsServerError() {
150
- this._checkResponseReady();
151
- expect(this.response.status).to.be.gte(500);
152
- expect(this.response.status).to.be.lt(600);
153
- }
154
-
155
- /**
156
- * Checks that the response code is 2xx
157
- * Use it instead of seeResponseCodeIs(200) if server can return 204 instead.
158
- *
159
- * ```js
160
- * I.seeResponseCodeIsSuccessful();
161
- * ```
162
- */
163
- seeResponseCodeIsSuccessful() {
164
- this._checkResponseReady();
165
- expect(this.response.status).to.be.gte(200);
166
- expect(this.response.status).to.be.lt(300);
167
- }
168
-
169
- /**
170
- * Checks for deep inclusion of a provided json in a response data.
171
- *
172
- * ```js
173
- * // response.data == { user: { name: 'jon', email: 'jon@doe.com' } }
174
- *
175
- * I.seeResponseContainsJson({ user: { email: 'jon@doe.com' } });
176
- * ```
177
- * If an array is received, checks that at least one element contains JSON
178
- * ```js
179
- * // response.data == [{ user: { name: 'jon', email: 'jon@doe.com' } }]
180
- *
181
- * I.seeResponseContainsJson({ user: { email: 'jon@doe.com' } });
182
- * ```
183
- *
184
- * @param {object} json
185
- */
186
- seeResponseContainsJson(json = {}) {
187
- this._checkResponseReady();
188
- if (Array.isArray(this.response.data)) {
189
- let fails = 0;
190
- for (const el of this.response.data) {
191
- try {
192
- expect(el).to.deep.match(json);
193
- } catch (err) {
194
- fails++;
195
- }
196
- }
197
- assert.ok(fails < this.response.data.length, `No elements in array matched ${JSON.stringify(json)}`);
198
- } else {
199
- expect(this.response.data).to.deep.match(json);
200
- }
201
- }
202
-
203
- /**
204
- * Checks for deep inclusion of a provided json in a response data.
205
- *
206
- * ```js
207
- * // response.data == { data: { user: 1 } }
208
- *
209
- * I.dontSeeResponseContainsJson({ user: 2 });
210
- * ```
211
- * If an array is received, checks that no element of array contains json:
212
- * ```js
213
- * // response.data == [{ user: 1 }, { user: 3 }]
214
- *
215
- * I.dontSeeResponseContainsJson({ user: 2 });
216
- * ```
217
- *
218
- * @param {object} json
219
- */
220
- dontSeeResponseContainsJson(json = {}) {
221
- this._checkResponseReady();
222
- if (Array.isArray(this.response.data)) {
223
- this.response.data.forEach(data => expect(data).not.to.deep.match(json));
224
- } else {
225
- expect(this.response.data).not.to.deep.match(json);
226
- }
227
- }
228
-
229
- /**
230
- * Checks for deep inclusion of a provided json in a response data.
231
- *
232
- * ```js
233
- * // response.data == { user: { name: 'jon', email: 'jon@doe.com' } }
234
- *
235
- * I.seeResponseContainsKeys(['user']);
236
- * ```
237
- *
238
- * If an array is received, check is performed for each element of array:
239
- *
240
- * ```js
241
- * // response.data == [{ user: 'jon' }, { user: 'matt'}]
242
- *
243
- * I.seeResponseContainsKeys(['user']);
244
- * ```
245
- *
246
- * @param {array} keys
247
- */
248
- seeResponseContainsKeys(keys = []) {
249
- this._checkResponseReady();
250
- if (Array.isArray(this.response.data)) {
251
- this.response.data.forEach(data => expect(data).to.include.keys(keys));
252
- } else {
253
- expect(this.response.data).to.include.keys(keys);
254
- }
255
- }
256
-
257
- /**
258
- * Executes a callback function passing in `response` object and chai assertions with `expect`
259
- * Use it to perform custom checks of response data
260
- *
261
- * ```js
262
- * I.seeResponseValidByCallback(({ data, status, expect }) => {
263
- * expect(status).to.eql(200);
264
- * expect(data).keys.to.include(['user', 'company']);
265
- * });
266
- * ```
267
- *
268
- * @param {function} fn
269
- */
270
- seeResponseValidByCallback(fn) {
271
- this._checkResponseReady();
272
- fn({ ...this.response, expect });
273
- const body = fn.toString();
274
- fn.toString = () => `${body.split('\n')[1]}...`;
275
- }
276
-
277
- /**
278
- * Checks that response data equals to expected:
279
- *
280
- * ```js
281
- * // response.data is { error: 'Not allowed' }
282
- *
283
- * I.seeResponseEquals({ error: 'Not allowed' })
284
- * ```
285
- * @param {object} resp
286
- */
287
- seeResponseEquals(resp) {
288
- this._checkResponseReady();
289
- expect(this.response.data).to.deep.equal(resp);
290
- }
291
-
292
- /**
293
- * Validates JSON structure of response using [joi library](https://joi.dev).
294
- * See [joi API](https://joi.dev/api/) for complete reference on usage.
295
- *
296
- * Use pre-initialized joi instance by passing function callback:
297
- *
298
- * ```js
299
- * // response.data is { name: 'jon', id: 1 }
300
- *
301
- * I.seeResponseMatchesJsonSchema(joi => {
302
- * return joi.object({
303
- * name: joi.string(),
304
- * id: joi.number()
305
- * })
306
- * });
307
- *
308
- * // or pass a valid schema
309
- * const joi = require('joi');
310
- *
311
- * I.seeResponseMatchesJsonSchema(joi.object({
312
- * name: joi.string(),
313
- * id: joi.number();
314
- * });
315
- * ```
316
- *
317
- * @param {any} fnOrSchema
318
- */
319
- seeResponseMatchesJsonSchema(fnOrSchema) {
320
- this._checkResponseReady();
321
- let schema = fnOrSchema;
322
- if (typeof fnOrSchema === 'function') {
323
- schema = fnOrSchema(joi);
324
- const body = fnOrSchema.toString();
325
- fnOrSchema.toString = () => `${body.split('\n')[1]}...`;
326
- }
327
- if (!schema) throw new Error('Empty Joi schema provided, see https://joi.dev/ for details');
328
- if (!joi.isSchema(schema)) throw new Error('Invalid Joi schema provided, see https://joi.dev/ for details');
329
- schema.toString = () => schema.describe();
330
- joi.assert(this.response.data, schema);
331
- }
332
-
333
- _checkResponseReady() {
334
- if (!this.response) throw new Error('Response is not available');
335
- }
336
- }
337
-
338
- module.exports = JSONResponse;
@@ -1,71 +0,0 @@
1
- let addMochawesomeContext;
2
- let currentTest;
3
- let currentSuite;
4
-
5
- const Helper = require('@codeceptjs/helper');
6
- const { clearString } = require('../utils');
7
-
8
- class Mochawesome extends Helper {
9
- constructor(config) {
10
- super(config);
11
-
12
- // set defaults
13
- this.options = {
14
- uniqueScreenshotNames: false,
15
- disableScreenshots: false,
16
- };
17
-
18
- addMochawesomeContext = require('mochawesome/addContext');
19
- this._createConfig(config);
20
- }
21
-
22
- _createConfig(config) {
23
- // override defaults with config
24
- Object.assign(this.options, config);
25
- }
26
-
27
- _beforeSuite(suite) {
28
- currentSuite = suite;
29
- currentTest = '';
30
- }
31
-
32
- _before() {
33
- if (currentSuite && currentSuite.ctx) {
34
- currentTest = { test: currentSuite.ctx.currentTest };
35
- }
36
- }
37
-
38
- _test(test) {
39
- currentTest = { test };
40
- }
41
-
42
- _failed(test) {
43
- if (this.options.disableScreenshots) return;
44
- let fileName;
45
- // Get proper name if we are fail on hook
46
- if (test.ctx.test.type === 'hook') {
47
- currentTest = { test: test.ctx.test };
48
- // ignore retries if we are in hook
49
- test._retries = -1;
50
- fileName = clearString(`${test.title}_${currentTest.test.title}`);
51
- } else {
52
- currentTest = { test };
53
- fileName = clearString(test.title);
54
- }
55
- if (this.options.uniqueScreenshotNames) {
56
- const uuid = test.uuid || test.ctx.test.uuid;
57
- fileName = `${fileName.substring(0, 10)}_${uuid}`;
58
- }
59
- if (test._retries < 1 || test._retries === test.retryNum) {
60
- fileName = `${fileName}.failed.png`;
61
- return addMochawesomeContext(currentTest, fileName);
62
- }
63
- }
64
-
65
- addMochawesomeContext(context) {
66
- if (currentTest === '') currentTest = { test: currentSuite.ctx.test };
67
- return addMochawesomeContext(currentTest, context);
68
- }
69
- }
70
-
71
- module.exports = Mochawesome;