codeceptjs 4.0.0-beta.1 → 4.0.0-beta.3

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 (151) hide show
  1. package/bin/codecept.js +84 -81
  2. package/lib/actor.js +13 -13
  3. package/lib/ai.js +10 -13
  4. package/lib/assert/empty.js +20 -21
  5. package/lib/assert/equal.js +37 -39
  6. package/lib/assert/error.js +14 -14
  7. package/lib/assert/include.js +46 -47
  8. package/lib/assert/throws.js +13 -11
  9. package/lib/assert/truth.js +19 -22
  10. package/lib/assert.js +4 -2
  11. package/lib/cli.js +57 -49
  12. package/lib/codecept.js +142 -155
  13. package/lib/colorUtils.js +3 -3
  14. package/lib/command/configMigrate.js +58 -52
  15. package/lib/command/definitions.js +88 -89
  16. package/lib/command/dryRun.js +71 -68
  17. package/lib/command/generate.js +197 -188
  18. package/lib/command/gherkin/init.js +27 -16
  19. package/lib/command/gherkin/snippets.js +20 -20
  20. package/lib/command/gherkin/steps.js +8 -8
  21. package/lib/command/info.js +40 -38
  22. package/lib/command/init.js +290 -288
  23. package/lib/command/interactive.js +32 -32
  24. package/lib/command/list.js +26 -26
  25. package/lib/command/run-multiple/chunk.js +5 -5
  26. package/lib/command/run-multiple/collection.js +3 -3
  27. package/lib/command/run-multiple/run.js +6 -2
  28. package/lib/command/run-multiple.js +113 -93
  29. package/lib/command/run-rerun.js +20 -25
  30. package/lib/command/run-workers.js +64 -66
  31. package/lib/command/run.js +26 -29
  32. package/lib/command/utils.js +80 -65
  33. package/lib/command/workers/runTests.js +10 -10
  34. package/lib/config.js +10 -9
  35. package/lib/container.js +40 -48
  36. package/lib/data/context.js +60 -59
  37. package/lib/data/dataScenarioConfig.js +47 -47
  38. package/lib/data/dataTableArgument.js +29 -29
  39. package/lib/data/table.js +26 -20
  40. package/lib/event.js +163 -167
  41. package/lib/heal.js +13 -17
  42. package/lib/helper/AI.js +130 -41
  43. package/lib/helper/ApiDataFactory.js +73 -69
  44. package/lib/helper/Appium.js +413 -382
  45. package/lib/helper/ExpectHelper.js +40 -48
  46. package/lib/helper/FileSystem.js +80 -79
  47. package/lib/helper/GraphQL.js +44 -43
  48. package/lib/helper/GraphQLDataFactory.js +50 -50
  49. package/lib/helper/JSONResponse.js +65 -62
  50. package/lib/helper/Mochawesome.js +28 -28
  51. package/lib/helper/MockServer.js +12 -14
  52. package/lib/helper/Nightmare.js +662 -566
  53. package/lib/helper/Playwright.js +1361 -1216
  54. package/lib/helper/Protractor.js +663 -627
  55. package/lib/helper/Puppeteer.js +1231 -1128
  56. package/lib/helper/REST.js +159 -68
  57. package/lib/helper/SoftExpectHelper.js +2 -2
  58. package/lib/helper/TestCafe.js +490 -484
  59. package/lib/helper/WebDriver.js +1297 -1156
  60. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  61. package/lib/helper/errors/ConnectionRefused.js +1 -1
  62. package/lib/helper/errors/ElementAssertion.js +2 -2
  63. package/lib/helper/errors/ElementNotFound.js +2 -2
  64. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
  65. package/lib/helper/extras/Console.js +1 -1
  66. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  67. package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
  68. package/lib/helper/extras/PlaywrightRestartOpts.js +21 -18
  69. package/lib/helper/extras/Popup.js +1 -1
  70. package/lib/helper/extras/React.js +3 -3
  71. package/lib/helper/network/actions.js +14 -7
  72. package/lib/helper/network/utils.js +3 -2
  73. package/lib/helper/scripts/blurElement.js +1 -1
  74. package/lib/helper/scripts/focusElement.js +1 -1
  75. package/lib/helper/scripts/highlightElement.js +1 -1
  76. package/lib/helper/scripts/isElementClickable.js +1 -1
  77. package/lib/helper/testcafe/testControllerHolder.js +1 -1
  78. package/lib/helper/testcafe/testcafe-utils.js +6 -7
  79. package/lib/helper.js +1 -3
  80. package/lib/history.js +6 -5
  81. package/lib/hooks.js +6 -6
  82. package/lib/html.js +7 -7
  83. package/lib/index.js +25 -41
  84. package/lib/interfaces/bdd.js +47 -64
  85. package/lib/interfaces/featureConfig.js +19 -19
  86. package/lib/interfaces/gherkin.js +124 -118
  87. package/lib/interfaces/scenarioConfig.js +29 -29
  88. package/lib/listener/artifacts.js +9 -9
  89. package/lib/listener/config.js +24 -24
  90. package/lib/listener/exit.js +12 -12
  91. package/lib/listener/helpers.js +42 -42
  92. package/lib/listener/mocha.js +11 -11
  93. package/lib/listener/retry.js +32 -30
  94. package/lib/listener/steps.js +50 -53
  95. package/lib/listener/timeout.js +54 -54
  96. package/lib/locator.js +6 -10
  97. package/lib/mochaFactory.js +18 -15
  98. package/lib/output.js +6 -10
  99. package/lib/parser.js +15 -12
  100. package/lib/pause.js +40 -33
  101. package/lib/plugin/allure.js +15 -15
  102. package/lib/plugin/autoDelay.js +29 -37
  103. package/lib/plugin/autoLogin.js +70 -65
  104. package/lib/plugin/commentStep.js +18 -18
  105. package/lib/plugin/coverage.js +115 -67
  106. package/lib/plugin/customLocator.js +21 -20
  107. package/lib/plugin/debugErrors.js +24 -24
  108. package/lib/plugin/eachElement.js +38 -38
  109. package/lib/plugin/fakerTransform.js +6 -6
  110. package/lib/plugin/heal.js +67 -108
  111. package/lib/plugin/pauseOnFail.js +11 -11
  112. package/lib/plugin/retryFailedStep.js +32 -39
  113. package/lib/plugin/retryTo.js +46 -40
  114. package/lib/plugin/screenshotOnFail.js +109 -87
  115. package/lib/plugin/selenoid.js +131 -118
  116. package/lib/plugin/standardActingHelpers.js +2 -8
  117. package/lib/plugin/stepByStepReport.js +110 -91
  118. package/lib/plugin/stepTimeout.js +24 -23
  119. package/lib/plugin/subtitles.js +34 -35
  120. package/lib/plugin/tryTo.js +40 -30
  121. package/lib/plugin/wdio.js +78 -75
  122. package/lib/recorder.js +14 -17
  123. package/lib/rerun.js +11 -10
  124. package/lib/scenario.js +25 -23
  125. package/lib/secret.js +4 -2
  126. package/lib/session.js +10 -10
  127. package/lib/step.js +12 -9
  128. package/lib/store.js +2 -3
  129. package/lib/transform.js +1 -1
  130. package/lib/translation.js +7 -8
  131. package/lib/ui.js +12 -14
  132. package/lib/utils.js +70 -72
  133. package/lib/within.js +10 -10
  134. package/lib/workerStorage.js +27 -25
  135. package/lib/workers.js +29 -32
  136. package/package.json +56 -57
  137. package/translations/de-DE.js +1 -1
  138. package/translations/fr-FR.js +1 -1
  139. package/translations/index.js +9 -13
  140. package/translations/it-IT.js +1 -1
  141. package/translations/ja-JP.js +1 -1
  142. package/translations/pl-PL.js +1 -1
  143. package/translations/pt-BR.js +1 -1
  144. package/translations/ru-RU.js +1 -1
  145. package/translations/zh-CN.js +1 -1
  146. package/translations/zh-TW.js +1 -1
  147. package/typings/index.d.ts +415 -65
  148. package/typings/promiseBasedTypes.d.ts +32 -0
  149. package/typings/types.d.ts +32 -0
  150. package/lib/dirname.js +0 -5
  151. package/lib/helper/Expect.js +0 -425
@@ -1,8 +1,9 @@
1
- import { default as axios } from 'axios';
2
- import Helper from '@codeceptjs/helper';
3
- import Secret from '../secret.js';
4
- import { beautify } from '../utils.js';
5
- import { output } from '../output.js';
1
+ const axios = require('axios').default
2
+ const Helper = require('@codeceptjs/helper')
3
+ const { Agent } = require('https')
4
+ const Secret = require('../secret')
5
+
6
+ const { beautify } = require('../utils')
6
7
 
7
8
  /**
8
9
  * ## Configuration
@@ -10,14 +11,16 @@ import { output } from '../output.js';
10
11
  * @typedef RESTConfig
11
12
  * @type {object}
12
13
  * @prop {string} [endpoint] - API base URL
13
- * @prop {boolean} [prettyPrintJson=false] - pretty print json for response/request on console logs
14
- * @prop {number} [timeout=1000] - timeout for requests in milliseconds. 10000ms by default
15
- * @prop {object} [defaultHeaders] - a list of default headers
16
- * @prop {function} [onRequest] - a async function which can update request object.
17
- * @prop {function} [onResponse] - a async function which can update response object.
14
+ * @prop {boolean} [prettyPrintJson=false] - pretty print json for response/request on console logs.
15
+ * @prop {boolean} [printCurl=false] - print cURL request on console logs. False by default.
16
+ * @prop {number} [timeout=1000] - timeout for requests in milliseconds. 10000ms by default.
17
+ * @prop {object} [defaultHeaders] - a list of default headers.
18
+ * @prop {object} [httpAgent] - create an agent with SSL certificate
19
+ * @prop {function} [onRequest] - an async function which can update request object.
20
+ * @prop {function} [onResponse] - an async function which can update response object.
18
21
  * @prop {number} [maxUploadFileSize] - set the max content file size in MB when performing api calls.
19
22
  */
20
- const config = {};
23
+ const config = {}
21
24
 
22
25
  /**
23
26
  * REST helper allows to send additional requests to the REST API during acceptance tests.
@@ -41,6 +44,41 @@ const config = {};
41
44
  *}
42
45
  * ```
43
46
  *
47
+ * With httpAgent
48
+ *
49
+ * ```js
50
+ * {
51
+ * helpers: {
52
+ * REST: {
53
+ * endpoint: 'http://site.com/api',
54
+ * prettyPrintJson: true,
55
+ * httpAgent: {
56
+ * key: fs.readFileSync(__dirname + '/path/to/keyfile.key'),
57
+ * cert: fs.readFileSync(__dirname + '/path/to/certfile.cert'),
58
+ * rejectUnauthorized: false,
59
+ * keepAlive: true
60
+ * }
61
+ * }
62
+ * }
63
+ * }
64
+ * ```
65
+ *
66
+ * ```js
67
+ * {
68
+ * helpers: {
69
+ * REST: {
70
+ * endpoint: 'http://site.com/api',
71
+ * prettyPrintJson: true,
72
+ * httpAgent: {
73
+ * ca: fs.readFileSync(__dirname + '/path/to/ca.pem'),
74
+ * rejectUnauthorized: false,
75
+ * keepAlive: true
76
+ * }
77
+ * }
78
+ * }
79
+ * }
80
+ * ```
81
+ *
44
82
  * ## Access From Helpers
45
83
  *
46
84
  * Send REST requests by accessing `_executeRequest` method:
@@ -56,7 +94,7 @@ const config = {};
56
94
  */
57
95
  class REST extends Helper {
58
96
  constructor(config) {
59
- super(config);
97
+ super(config)
60
98
  this.options = {
61
99
  timeout: 10000,
62
100
  defaultHeaders: {},
@@ -64,39 +102,55 @@ class REST extends Helper {
64
102
  prettyPrintJson: false,
65
103
  onRequest: null,
66
104
  onResponse: null,
67
- };
105
+ }
68
106
 
69
107
  if (this.options.maxContentLength) {
70
- const maxContentLength = this.options.maxUploadFileSize * 1024 * 1024;
71
- this.options.maxContentLength = maxContentLength;
72
- this.options.maxBodyLength = maxContentLength;
108
+ const maxContentLength = this.options.maxUploadFileSize * 1024 * 1024
109
+ this.options.maxContentLength = maxContentLength
110
+ this.options.maxBodyLength = maxContentLength
73
111
  }
74
112
 
75
113
  // override defaults with config
76
- this._setConfig(config);
114
+ this._setConfig(config)
115
+
116
+ this.headers = { ...this.options.defaultHeaders }
117
+
118
+ // Create an agent with SSL certificate
119
+ if (this.options.httpAgent) {
120
+ // if one of those keys is there, all good to go
121
+ if (this.options.httpAgent.ca || this.options.httpAgent.key || this.options.httpAgent.cert) {
122
+ this.httpsAgent = new Agent(this.options.httpAgent)
123
+ } else {
124
+ // otherwise, throws an error of httpAgent config
125
+ throw Error('Please recheck your httpAgent config!')
126
+ }
127
+ }
77
128
 
78
- this.headers = { ...this.options.defaultHeaders };
79
- this.axios = axios.create();
129
+ this.axios = this.httpsAgent ? axios.create({ httpsAgent: this.httpsAgent }) : axios.create()
80
130
  // @ts-ignore
81
- this.axios.defaults.headers = this.options.defaultHeaders;
131
+ this.axios.defaults.headers = this.options.defaultHeaders
82
132
  }
83
133
 
84
134
  static _config() {
85
135
  return [
86
- { name: 'endpoint', message: 'Endpoint of API you are going to test', default: 'http://localhost:3000/api' },
87
- ];
136
+ {
137
+ name: 'endpoint',
138
+ message: 'Endpoint of API you are going to test',
139
+ default: 'http://localhost:3000/api',
140
+ },
141
+ ]
88
142
  }
89
143
 
90
144
  static _checkRequirements() {
91
145
  try {
92
- require('axios');
146
+ require('axios')
93
147
  } catch (e) {
94
- return ['axios'];
148
+ return ['axios']
95
149
  }
96
150
  }
97
151
 
98
152
  _before() {
99
- this.headers = { ...this.options.defaultHeaders };
153
+ this.headers = { ...this.options.defaultHeaders }
100
154
  }
101
155
 
102
156
  /**
@@ -105,7 +159,7 @@ class REST extends Helper {
105
159
  * @param {object} headers headers list
106
160
  */
107
161
  haveRequestHeaders(headers) {
108
- this.headers = { ...this.headers, ...headers };
162
+ this.headers = { ...this.headers, ...headers }
109
163
  }
110
164
 
111
165
  /**
@@ -119,7 +173,7 @@ class REST extends Helper {
119
173
  * @param {string | CodeceptJS.Secret} accessToken Bearer access token
120
174
  */
121
175
  amBearerAuthenticated(accessToken) {
122
- this.haveRequestHeaders({ Authorization: `Bearer ${accessToken}` });
176
+ this.haveRequestHeaders({ Authorization: `Bearer ${accessToken}` })
123
177
  }
124
178
 
125
179
  /**
@@ -131,54 +185,65 @@ class REST extends Helper {
131
185
  */
132
186
  async _executeRequest(request) {
133
187
  // Add custom headers. They can be set by amBearerAuthenticated() or haveRequestHeaders()
134
- request.headers = { ...this.headers, ...request.headers };
188
+ request.headers = { ...this.headers, ...request.headers }
135
189
 
136
- const _debugRequest = { ...request };
137
- this.axios.defaults.timeout = request.timeout || this.options.timeout;
190
+ const _debugRequest = { ...request }
191
+ this.axios.defaults.timeout = request.timeout || this.options.timeout
138
192
 
139
193
  if (this.headers && this.headers.auth) {
140
- request.auth = this.headers.auth;
194
+ request.auth = this.headers.auth
141
195
  }
142
196
 
143
197
  if (typeof request.data === 'object') {
144
- const returnedValue = {};
198
+ const returnedValue = {}
145
199
  for (const [key, value] of Object.entries(request.data)) {
146
- returnedValue[key] = value;
147
- if (value instanceof Secret) returnedValue[key] = value.getMasked();
200
+ returnedValue[key] = value
201
+ if (value instanceof Secret) returnedValue[key] = value.getMasked()
148
202
  }
149
- _debugRequest.data = returnedValue;
203
+ _debugRequest.data = returnedValue
150
204
  }
151
205
 
152
206
  if (request.data instanceof Secret) {
153
- _debugRequest.data = '*****';
154
- request.data = (typeof request.data === 'object' && !(request.data instanceof Secret)) ? { ...request.data.toString() } : request.data.toString();
207
+ _debugRequest.data = '*****'
208
+ request.data =
209
+ typeof request.data === 'object' && !(request.data instanceof Secret)
210
+ ? { ...request.data.toString() }
211
+ : request.data.toString()
155
212
  }
156
213
 
157
- if ((typeof request.data) === 'string') {
214
+ if (typeof request.data === 'string') {
158
215
  if (!request.headers || !request.headers['Content-Type']) {
159
- request.headers = { ...request.headers, ...{ 'Content-Type': 'application/x-www-form-urlencoded' } };
216
+ request.headers = { ...request.headers, ...{ 'Content-Type': 'application/x-www-form-urlencoded' } }
160
217
  }
161
218
  }
162
219
 
163
220
  if (this.config.onRequest) {
164
- await this.config.onRequest(request);
221
+ await this.config.onRequest(request)
165
222
  }
166
223
 
167
- this.options.prettyPrintJson ? output.debugSection('Request', beautify(JSON.stringify(_debugRequest))) : output.debugSection('Request', JSON.stringify(_debugRequest));
224
+ this.options.prettyPrintJson
225
+ ? this.debugSection('Request', beautify(JSON.stringify(_debugRequest)))
226
+ : this.debugSection('Request', JSON.stringify(_debugRequest))
168
227
 
169
- let response;
228
+ if (this.options.printCurl) {
229
+ this.debugSection('CURL Request', curlize(request))
230
+ }
231
+
232
+ let response
170
233
  try {
171
- response = await this.axios(request);
234
+ response = await this.axios(request)
172
235
  } catch (err) {
173
- if (!err.response) throw err;
174
- output.debugSection('Response', `Response error. Status code: ${err.response.status}`);
175
- response = err.response;
236
+ if (!err.response) throw err
237
+ this.debugSection('Response', `Response error. Status code: ${err.response.status}`)
238
+ response = err.response
176
239
  }
177
240
  if (this.config.onResponse) {
178
- await this.config.onResponse(response);
241
+ await this.config.onResponse(response)
179
242
  }
180
- this.options.prettyPrintJson ? output.debugSection('Response', beautify(JSON.stringify(response.data))) : output.debugSection('Response', JSON.stringify(response.data));
181
- return response;
243
+ this.options.prettyPrintJson
244
+ ? this.debugSection('Response', beautify(JSON.stringify(response.data)))
245
+ : this.debugSection('Response', JSON.stringify(response.data))
246
+ return response
182
247
  }
183
248
 
184
249
  /**
@@ -187,7 +252,7 @@ class REST extends Helper {
187
252
  * @param {*} url
188
253
  */
189
254
  _url(url) {
190
- return /^\w+\:\/\//.test(url) ? url : this.options.endpoint + url;
255
+ return /^\w+\:\/\//.test(url) ? url : this.options.endpoint + url
191
256
  }
192
257
 
193
258
  /**
@@ -200,7 +265,7 @@ class REST extends Helper {
200
265
  * @param {number} newTimeout - timeout in milliseconds
201
266
  */
202
267
  setRequestTimeout(newTimeout) {
203
- this.options.timeout = newTimeout;
268
+ this.options.timeout = newTimeout
204
269
  }
205
270
 
206
271
  /**
@@ -219,8 +284,8 @@ class REST extends Helper {
219
284
  const request = {
220
285
  baseURL: this._url(url),
221
286
  headers,
222
- };
223
- return this._executeRequest(request);
287
+ }
288
+ return this._executeRequest(request)
224
289
  }
225
290
 
226
291
  /**
@@ -246,14 +311,14 @@ class REST extends Helper {
246
311
  method: 'POST',
247
312
  data: payload,
248
313
  headers,
249
- };
314
+ }
250
315
 
251
316
  if (this.options.maxContentLength) {
252
- request.maxContentLength = this.options.maxContentLength;
253
- request.maxBodyLength = this.options.maxContentLength;
317
+ request.maxContentLength = this.options.maxContentLength
318
+ request.maxBodyLength = this.options.maxContentLength
254
319
  }
255
320
 
256
- return this._executeRequest(request);
321
+ return this._executeRequest(request)
257
322
  }
258
323
 
259
324
  /**
@@ -279,14 +344,14 @@ class REST extends Helper {
279
344
  method: 'PATCH',
280
345
  data: payload,
281
346
  headers,
282
- };
347
+ }
283
348
 
284
349
  if (this.options.maxContentLength) {
285
- request.maxContentLength = this.options.maxContentLength;
286
- request.maxBodyLength = this.options.maxBodyLength;
350
+ request.maxContentLength = this.options.maxContentLength
351
+ request.maxBodyLength = this.options.maxBodyLength
287
352
  }
288
353
 
289
- return this._executeRequest(request);
354
+ return this._executeRequest(request)
290
355
  }
291
356
 
292
357
  /**
@@ -312,14 +377,14 @@ class REST extends Helper {
312
377
  method: 'PUT',
313
378
  data: payload,
314
379
  headers,
315
- };
380
+ }
316
381
 
317
382
  if (this.options.maxContentLength) {
318
- request.maxContentLength = this.options.maxContentLength;
319
- request.maxBodyLength = this.options.maxBodyLength;
383
+ request.maxContentLength = this.options.maxContentLength
384
+ request.maxBodyLength = this.options.maxBodyLength
320
385
  }
321
386
 
322
- return this._executeRequest(request);
387
+ return this._executeRequest(request)
323
388
  }
324
389
 
325
390
  /**
@@ -339,9 +404,35 @@ class REST extends Helper {
339
404
  baseURL: this._url(url),
340
405
  method: 'DELETE',
341
406
  headers,
342
- };
407
+ }
408
+
409
+ return this._executeRequest(request)
410
+ }
411
+ }
412
+
413
+ module.exports = REST
414
+
415
+ function curlize(request) {
416
+ if (request.data?.constructor.name.toLowerCase() === 'formdata')
417
+ return 'cURL is not printed as the request body is not a JSON'
418
+ let curl =
419
+ `curl --location --request ${request.method ? request.method.toUpperCase() : 'GET'} ${request.baseURL} `.replace(
420
+ "'",
421
+ '',
422
+ )
423
+
424
+ if (request.headers) {
425
+ Object.entries(request.headers).forEach(([key, value]) => {
426
+ curl += `-H "${key}: ${value}" `
427
+ })
428
+ }
429
+
430
+ if (!curl.toLowerCase().includes('content-type: application/json')) {
431
+ curl += '-H "Content-Type: application/json" '
432
+ }
343
433
 
344
- return this._executeRequest(request);
434
+ if (request.data) {
435
+ curl += `-d '${JSON.stringify(request.data)}'`
345
436
  }
437
+ return curl
346
438
  }
347
- export default REST;
@@ -1,4 +1,4 @@
1
- import ExpectHelper from './ExpectHelper.js'
1
+ const ExpectHelper = require('./ExpectHelper')
2
2
 
3
3
  /**
4
4
  * SoftAssertHelper is a utility class for performing soft assertions.
@@ -378,4 +378,4 @@ class SoftAssertHelper extends ExpectHelper {
378
378
  this.softAssert(() => this.expectMatchesPattern(actualValue, expectedPattern, customErrorMsg), customErrorMsg)
379
379
  }
380
380
  }
381
- export default SoftAssertHelper
381
+ module.exports = SoftAssertHelper