codeceptjs 3.2.0 → 3.3.0-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 (74) hide show
  1. package/CHANGELOG.md +78 -2
  2. package/docs/advanced.md +3 -3
  3. package/docs/api.md +227 -188
  4. package/docs/basics.md +26 -1
  5. package/docs/bdd.md +2 -2
  6. package/docs/build/ApiDataFactory.js +13 -6
  7. package/docs/build/Appium.js +98 -36
  8. package/docs/build/FileSystem.js +11 -1
  9. package/docs/build/GraphQL.js +11 -0
  10. package/docs/build/JSONResponse.js +297 -0
  11. package/docs/build/Nightmare.js +48 -48
  12. package/docs/build/Playwright.js +277 -151
  13. package/docs/build/Puppeteer.js +77 -68
  14. package/docs/build/REST.js +36 -0
  15. package/docs/build/TestCafe.js +44 -44
  16. package/docs/build/WebDriver.js +70 -70
  17. package/docs/changelog.md +28 -2
  18. package/docs/configuration.md +8 -8
  19. package/docs/custom-helpers.md +1 -1
  20. package/docs/data.md +9 -9
  21. package/docs/helpers/ApiDataFactory.md +7 -0
  22. package/docs/helpers/Appium.md +240 -198
  23. package/docs/helpers/FileSystem.md +11 -1
  24. package/docs/helpers/JSONResponse.md +230 -0
  25. package/docs/helpers/Playwright.md +283 -216
  26. package/docs/helpers/Puppeteer.md +9 -1
  27. package/docs/helpers/REST.md +30 -9
  28. package/docs/installation.md +3 -1
  29. package/docs/internal-api.md +265 -0
  30. package/docs/mobile.md +11 -11
  31. package/docs/nightmare.md +3 -3
  32. package/docs/pageobjects.md +2 -0
  33. package/docs/playwright.md +73 -18
  34. package/docs/plugins.md +140 -40
  35. package/docs/puppeteer.md +28 -12
  36. package/docs/quickstart.md +2 -3
  37. package/docs/reports.md +44 -3
  38. package/docs/testcafe.md +1 -1
  39. package/docs/translation.md +2 -2
  40. package/docs/videos.md +2 -2
  41. package/docs/visual.md +2 -2
  42. package/docs/vue.md +1 -1
  43. package/docs/webdriver.md +92 -4
  44. package/lib/actor.js +2 -2
  45. package/lib/cli.js +25 -20
  46. package/lib/command/init.js +5 -15
  47. package/lib/command/workers/runTests.js +25 -7
  48. package/lib/config.js +17 -13
  49. package/lib/helper/ApiDataFactory.js +13 -6
  50. package/lib/helper/Appium.js +65 -3
  51. package/lib/helper/FileSystem.js +11 -1
  52. package/lib/helper/GraphQL.js +11 -0
  53. package/lib/helper/JSONResponse.js +297 -0
  54. package/lib/helper/Playwright.js +215 -89
  55. package/lib/helper/Puppeteer.js +13 -4
  56. package/lib/helper/REST.js +36 -0
  57. package/lib/helper/WebDriver.js +1 -1
  58. package/lib/helper/extras/Console.js +8 -0
  59. package/lib/helper/extras/PlaywrightRestartOpts.js +35 -0
  60. package/lib/interfaces/bdd.js +3 -1
  61. package/lib/listener/timeout.js +4 -3
  62. package/lib/plugin/allure.js +12 -0
  63. package/lib/plugin/autoLogin.js +1 -1
  64. package/lib/plugin/eachElement.js +127 -0
  65. package/lib/plugin/retryFailedStep.js +4 -3
  66. package/lib/plugin/stepTimeout.js +5 -4
  67. package/lib/plugin/tryTo.js +6 -0
  68. package/lib/recorder.js +2 -1
  69. package/lib/step.js +57 -2
  70. package/lib/utils.js +20 -0
  71. package/package.json +6 -4
  72. package/translations/pt-BR.js +8 -0
  73. package/typings/index.d.ts +4 -0
  74. package/typings/types.d.ts +345 -110
@@ -59,6 +59,12 @@ class GraphQL extends Helper {
59
59
  }
60
60
  }
61
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
+
62
68
  /**
63
69
  * Executes query via axios call
64
70
  *
@@ -92,6 +98,11 @@ class GraphQL extends Helper {
92
98
  );
93
99
  response = err.response;
94
100
  }
101
+
102
+ if (this.config.onResponse) {
103
+ await this.config.onResponse(response);
104
+ }
105
+
95
106
  this.debugSection('Response', JSON.stringify(response.data));
96
107
  return response;
97
108
  }
@@ -0,0 +1,297 @@
1
+ const chai = require('chai');
2
+ const joi = require('joi');
3
+ const chaiDeepMatch = require('chai-deep-match');
4
+ const Helper = require('../helper');
5
+
6
+ chai.use(chaiDeepMatch);
7
+
8
+ const { expect } = chai;
9
+
10
+ /**
11
+ * This helper allows performing assertions on JSON responses paired with following helpers:
12
+ *
13
+ * * REST
14
+ * * GraphQL
15
+ * * Playwright
16
+ *
17
+ * It can check status codes, response data, response structure.
18
+ *
19
+ *
20
+ * ## Configuration
21
+ *
22
+ * * `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.
23
+ *
24
+ * ### Examples
25
+ *
26
+ * Zero-configuration when paired with REST:
27
+ *
28
+ * ```js
29
+ * // inside codecept.conf.js
30
+ *{
31
+ * helpers: {
32
+ * REST: {
33
+ * endpoint: 'http://site.com/api',
34
+ * },
35
+ * JSONResponse: {}
36
+ * }
37
+ *}
38
+ * ```
39
+ * Explicitly setting request helper if you use `makeApiRequest` of Playwright to perform requests and not paired REST:
40
+ *
41
+ * ```js
42
+ * // inside codecept.conf.js
43
+ * // ...
44
+ * helpers: {
45
+ * Playwright: {
46
+ * url: 'https://localhost',
47
+ * browser: 'chromium',
48
+ * },
49
+ * JSONResponse: {
50
+ * requestHelper: 'Playwright',
51
+ * }
52
+ * }
53
+ * ```
54
+ * ## Access From Helpers
55
+ *
56
+ * If you plan to add custom assertions it is recommended to create a helper that will retrieve response object from JSONResponse:
57
+ *
58
+ *
59
+ * ```js
60
+ * // inside custom helper
61
+ * const response = this.helpers.JSONResponse.response;
62
+ * ```
63
+ *
64
+ * ## Methods
65
+ */
66
+ class JSONResponse extends Helper {
67
+ constructor(config = {}) {
68
+ super(config);
69
+ this.options = {
70
+ requestHelper: 'REST',
71
+ };
72
+ this.options = { ...this.options, ...config };
73
+ }
74
+
75
+ _beforeSuite() {
76
+ this.response = null;
77
+ if (!this.helpers[this.options.requestHelper]) {
78
+ throw new Error(`Error setting JSONResponse, helper ${this.options.requestHelper} is not enabled in config, helpers: ${Object.keys(this.helpers)}`);
79
+ }
80
+ // connect to REST helper
81
+ this.helpers[this.options.requestHelper].config.onResponse = (response) => {
82
+ this.response = response;
83
+ };
84
+ }
85
+
86
+ _before() {
87
+ this.response = null;
88
+ }
89
+
90
+ static _checkRequirements() {
91
+ try {
92
+ require('joi');
93
+ require('chai');
94
+ } catch (e) {
95
+ return ['joi'];
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Checks that response code is equal to the provided one
101
+ *
102
+ * ```js
103
+ * I.seeResponseCodeIs(200);
104
+ * ```
105
+ *
106
+ * @param {number} code
107
+ */
108
+ seeResponseCodeIs(code) {
109
+ this._checkResponseReady();
110
+ expect(this.response.status).to.eql(code, 'Response code is not the same as expected');
111
+ }
112
+
113
+ /**
114
+ * Checks that response code is not equal to the provided one
115
+ *
116
+ * ```js
117
+ * I.dontSeeResponseCodeIs(500);
118
+ * ```
119
+ *
120
+ * @param {number} code
121
+ */
122
+ dontSeeResponseCodeIs(code) {
123
+ this._checkResponseReady();
124
+ expect(this.response.status).not.to.eql(code);
125
+ }
126
+
127
+ /**
128
+ * Checks that the response code is 4xx
129
+ */
130
+ seeResponseCodeIsClientError() {
131
+ this._checkResponseReady();
132
+ expect(this.response.status).to.be.gte(400);
133
+ expect(this.response.status).to.be.lt(500);
134
+ }
135
+
136
+ /**
137
+ * Checks that the response code is 3xx
138
+ */
139
+ seeResponseCodeIsRedirection() {
140
+ this._checkResponseReady();
141
+ expect(this.response.status).to.be.gte(300);
142
+ expect(this.response.status).to.be.lt(400);
143
+ }
144
+
145
+ /**
146
+ * Checks that the response code is 5xx
147
+ */
148
+ seeResponseCodeIsServerError() {
149
+ this._checkResponseReady();
150
+ expect(this.response.status).to.be.gte(500);
151
+ expect(this.response.status).to.be.lt(600);
152
+ }
153
+
154
+ /**
155
+ * Checks that the response code is 2xx
156
+ * Use it instead of seeResponseCodeIs(200) if server can return 204 instead.
157
+ *
158
+ * ```js
159
+ * I.seeResponseCodeIsSuccessful();
160
+ * ```
161
+ */
162
+ seeResponseCodeIsSuccessful() {
163
+ this._checkResponseReady();
164
+ expect(this.response.status).to.be.gte(200);
165
+ expect(this.response.status).to.be.lt(300);
166
+ }
167
+
168
+ /**
169
+ * Checks for deep inclusion of a provided json in a response data.
170
+ *
171
+ * ```js
172
+ * // response.data == { user: { name: 'jon', email: 'jon@doe.com' } }
173
+ *
174
+ * I.seeResponseContainsJson({ user: { email: 'jon@doe.com' } });
175
+ * ```
176
+ *
177
+ * @param {object} json
178
+ */
179
+ seeResponseContainsJson(json = {}) {
180
+ this._checkResponseReady();
181
+ expect(this.response.data).to.deep.match(json);
182
+ }
183
+
184
+ /**
185
+ * Checks for deep inclusion of a provided json in a response data.
186
+ *
187
+ * ```js
188
+ * // response.data == { data: { user: 1 } }
189
+ *
190
+ * I.dontSeeResponseContainsJson({ user: 2 });
191
+ * ```
192
+ *
193
+ * @param {object} json
194
+ */
195
+ dontSeeResponseContainsJson(json = {}) {
196
+ this._checkResponseReady();
197
+ expect(this.response.data).not.to.deep.match(json);
198
+ }
199
+
200
+ /**
201
+ * Checks for deep inclusion of a provided json in a response data.
202
+ *
203
+ * ```js
204
+ * // response.data == { user: { name: 'jon', email: 'jon@doe.com' } }
205
+ *
206
+ * I.seeResponseContainsKeys(['user']);
207
+ * ```
208
+ *
209
+ * @param {array} keys
210
+ */
211
+ seeResponseContainsKeys(keys = []) {
212
+ this._checkResponseReady();
213
+ expect(this.response.data).to.include.keys(keys);
214
+ }
215
+
216
+ /**
217
+ * Executes a callback function passing in `response` object and chai assertions with `expect`
218
+ * Use it to perform custom checks of response data
219
+ *
220
+ * ```js
221
+ * I.seeResponseValidByCallback({ data, status, expect } => {
222
+ * expect(status).to.eql(200);
223
+ * expect(data).keys.to.include(['user', 'company']);
224
+ * });
225
+ * ```
226
+ *
227
+ * @param {function} fn
228
+ */
229
+ seeResponseValidByCallback(fn) {
230
+ this._checkResponseReady();
231
+ fn({ ...this.response, expect });
232
+ const body = fn.toString();
233
+ fn.toString = () => `${body.split('\n')[1]}...`;
234
+ }
235
+
236
+ /**
237
+ * Checks that response data equals to expected:
238
+ *
239
+ * ```js
240
+ * // response.data is { error: 'Not allowed' }
241
+ *
242
+ * I.seeResponseEquals({ error: 'Not allowed' })
243
+ * ```
244
+ * @param {object} resp
245
+ */
246
+ seeResponseEquals(resp) {
247
+ this._checkResponseReady();
248
+ expect(this.response.data).to.deep.equal(resp);
249
+ }
250
+
251
+ /**
252
+ * Validates JSON structure of response using [joi library](https://joi.dev).
253
+ * See [joi API](https://joi.dev/api/) for complete reference on usage.
254
+ *
255
+ * Use pre-initialized joi instance by passing function callback:
256
+ *
257
+ * ```js
258
+ * // response.data is { name: 'jon', id: 1 }
259
+ *
260
+ * I.seeResponseMatchesJsonSchema(joi => {
261
+ * return joi.object({
262
+ * name: joi.string();
263
+ * id: joi.number();
264
+ * })
265
+ * });
266
+ *
267
+ * // or pass a valid schema
268
+ * const joi = require('joi);
269
+ *
270
+ * I.seeResponseMatchesJsonSchema(joi.object({
271
+ * name: joi.string();
272
+ * id: joi.number();
273
+ * });
274
+ * ```
275
+ *
276
+ * @param {any} fnOrSchema
277
+ */
278
+ seeResponseMatchesJsonSchema(fnOrSchema) {
279
+ this._checkResponseReady();
280
+ let schema = fnOrSchema;
281
+ if (typeof fnOrSchema === 'function') {
282
+ schema = fnOrSchema(joi);
283
+ const body = fnOrSchema.toString();
284
+ fnOrSchema.toString = () => `${body.split('\n')[1]}...`;
285
+ }
286
+ if (!schema) throw new Error('Empty Joi schema provided, see https://joi.dev/ for details');
287
+ if (!joi.isSchema(schema)) throw new Error('Invalid Joi schema provided, see https://joi.dev/ for details');
288
+ schema.toString = () => schema.describe();
289
+ joi.assert(this.response.data, schema);
290
+ }
291
+
292
+ _checkResponseReady() {
293
+ if (!this.response) throw new Error('Response is not available');
294
+ }
295
+ }
296
+
297
+ module.exports = JSONResponse;