codeceptjs 3.4.1 → 3.5.1-2.beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/README.md +31 -30
  2. package/bin/codecept.js +1 -1
  3. package/lib/actor.js +6 -3
  4. package/lib/ai.js +180 -0
  5. package/lib/cli.js +13 -3
  6. package/lib/codecept.js +8 -0
  7. package/lib/colorUtils.js +10 -0
  8. package/lib/command/definitions.js +2 -7
  9. package/lib/command/dryRun.js +11 -2
  10. package/lib/command/generate.js +46 -3
  11. package/lib/command/info.js +24 -0
  12. package/lib/command/init.js +64 -6
  13. package/lib/command/interactive.js +15 -1
  14. package/lib/command/run-multiple/collection.js +17 -5
  15. package/lib/command/run-multiple.js +4 -2
  16. package/lib/command/run-workers.js +68 -5
  17. package/lib/command/run.js +7 -0
  18. package/lib/command/workers/runTests.js +39 -0
  19. package/lib/container.js +13 -3
  20. package/lib/data/context.js +14 -6
  21. package/lib/event.js +4 -0
  22. package/lib/helper/ApiDataFactory.js +2 -1
  23. package/lib/helper/Appium.js +116 -29
  24. package/lib/helper/Expect.js +422 -0
  25. package/lib/helper/FileSystem.js +1 -1
  26. package/lib/helper/GraphQL.js +25 -0
  27. package/lib/helper/JSONResponse.js +4 -4
  28. package/lib/helper/Nightmare.js +10 -5
  29. package/lib/helper/OpenAI.js +126 -0
  30. package/lib/helper/Playwright.js +1298 -229
  31. package/lib/helper/Protractor.js +12 -7
  32. package/lib/helper/Puppeteer.js +204 -64
  33. package/lib/helper/REST.js +15 -5
  34. package/lib/helper/TestCafe.js +45 -10
  35. package/lib/helper/WebDriver.js +252 -83
  36. package/lib/helper/errors/ElementNotFound.js +2 -1
  37. package/lib/helper/extras/PlaywrightReactVueLocator.js +38 -0
  38. package/lib/helper/scripts/blurElement.js +17 -0
  39. package/lib/helper/scripts/focusElement.js +17 -0
  40. package/lib/helper/scripts/highlightElement.js +20 -0
  41. package/lib/html.js +258 -0
  42. package/lib/interfaces/bdd.js +1 -1
  43. package/lib/interfaces/gherkin.js +37 -3
  44. package/lib/interfaces/scenarioConfig.js +1 -0
  45. package/lib/listener/retry.js +2 -1
  46. package/lib/locator.js +17 -4
  47. package/lib/mochaFactory.js +2 -1
  48. package/lib/output.js +1 -1
  49. package/lib/pause.js +78 -19
  50. package/lib/plugin/autoLogin.js +45 -10
  51. package/lib/plugin/debugErrors.js +67 -0
  52. package/lib/plugin/fakerTransform.js +4 -6
  53. package/lib/plugin/heal.js +209 -0
  54. package/lib/plugin/retryFailedStep.js +10 -1
  55. package/lib/plugin/retryTo.js +2 -4
  56. package/lib/plugin/screenshotOnFail.js +11 -2
  57. package/lib/plugin/selenoid.js +6 -1
  58. package/lib/plugin/standardActingHelpers.js +0 -2
  59. package/lib/plugin/stepByStepReport.js +2 -2
  60. package/lib/plugin/tryTo.js +5 -7
  61. package/lib/plugin/wdio.js +0 -1
  62. package/lib/recorder.js +22 -11
  63. package/lib/secret.js +5 -4
  64. package/lib/session.js +1 -1
  65. package/lib/step.js +36 -12
  66. package/lib/ui.js +5 -3
  67. package/lib/utils.js +22 -1
  68. package/lib/workers.js +83 -10
  69. package/package.json +117 -95
  70. package/translations/de-DE.js +5 -0
  71. package/translations/fr-FR.js +14 -1
  72. package/translations/it-IT.js +1 -0
  73. package/translations/ja-JP.js +14 -9
  74. package/translations/pl-PL.js +5 -0
  75. package/translations/pt-BR.js +1 -0
  76. package/translations/ru-RU.js +1 -0
  77. package/translations/zh-CN.js +5 -0
  78. package/translations/zh-TW.js +5 -0
  79. package/typings/index.d.ts +51 -15
  80. package/typings/promiseBasedTypes.d.ts +864 -802
  81. package/typings/types.d.ts +1339 -744
  82. package/CHANGELOG.md +0 -2427
  83. package/docs/advanced.md +0 -351
  84. package/docs/api.md +0 -323
  85. package/docs/basics.md +0 -980
  86. package/docs/bdd.md +0 -535
  87. package/docs/best.md +0 -237
  88. package/docs/books.md +0 -37
  89. package/docs/bootstrap.md +0 -135
  90. package/docs/build/ApiDataFactory.js +0 -409
  91. package/docs/build/Appium.js +0 -1938
  92. package/docs/build/FileSystem.js +0 -228
  93. package/docs/build/GraphQL.js +0 -204
  94. package/docs/build/GraphQLDataFactory.js +0 -309
  95. package/docs/build/JSONResponse.js +0 -338
  96. package/docs/build/Mochawesome.js +0 -71
  97. package/docs/build/Nightmare.js +0 -2145
  98. package/docs/build/Playwright.js +0 -3986
  99. package/docs/build/Polly.js +0 -42
  100. package/docs/build/Protractor.js +0 -2699
  101. package/docs/build/Puppeteer.js +0 -3710
  102. package/docs/build/REST.js +0 -334
  103. package/docs/build/SeleniumWebdriver.js +0 -76
  104. package/docs/build/TestCafe.js +0 -2057
  105. package/docs/build/WebDriver.js +0 -4017
  106. package/docs/changelog.md +0 -2436
  107. package/docs/commands.md +0 -254
  108. package/docs/community-helpers.md +0 -58
  109. package/docs/configuration.md +0 -157
  110. package/docs/continuous-integration.md +0 -22
  111. package/docs/custom-helpers.md +0 -306
  112. package/docs/data.md +0 -375
  113. package/docs/detox.md +0 -235
  114. package/docs/docker.md +0 -137
  115. package/docs/email.md +0 -183
  116. package/docs/examples.md +0 -149
  117. package/docs/helpers/ApiDataFactory.md +0 -266
  118. package/docs/helpers/Appium.md +0 -1312
  119. package/docs/helpers/Detox.md +0 -586
  120. package/docs/helpers/FileSystem.md +0 -152
  121. package/docs/helpers/GraphQL.md +0 -130
  122. package/docs/helpers/GraphQLDataFactory.md +0 -226
  123. package/docs/helpers/JSONResponse.md +0 -254
  124. package/docs/helpers/Mochawesome.md +0 -8
  125. package/docs/helpers/MockRequest.md +0 -377
  126. package/docs/helpers/Nightmare.md +0 -1256
  127. package/docs/helpers/Playwright.md +0 -2208
  128. package/docs/helpers/Polly.md +0 -44
  129. package/docs/helpers/Puppeteer-firefox.md +0 -86
  130. package/docs/helpers/Puppeteer.md +0 -2141
  131. package/docs/helpers/REST.md +0 -217
  132. package/docs/helpers/TestCafe.md +0 -1222
  133. package/docs/helpers/WebDriver.md +0 -2319
  134. package/docs/hooks.md +0 -340
  135. package/docs/index.md +0 -111
  136. package/docs/installation.md +0 -75
  137. package/docs/internal-api.md +0 -265
  138. package/docs/locators.md +0 -331
  139. package/docs/mobile-react-native-locators.md +0 -67
  140. package/docs/mobile.md +0 -297
  141. package/docs/nightmare.md +0 -223
  142. package/docs/pageobjects.md +0 -291
  143. package/docs/parallel.md +0 -232
  144. package/docs/playwright.md +0 -609
  145. package/docs/plugins.md +0 -1171
  146. package/docs/puppeteer.md +0 -316
  147. package/docs/quickstart.md +0 -163
  148. package/docs/react.md +0 -69
  149. package/docs/reports.md +0 -392
  150. package/docs/secrets.md +0 -30
  151. package/docs/shadow.md +0 -68
  152. package/docs/shared/keys.mustache +0 -31
  153. package/docs/shared/react.mustache +0 -1
  154. package/docs/testcafe.md +0 -174
  155. package/docs/translation.md +0 -247
  156. package/docs/tutorial.md +0 -271
  157. package/docs/typescript.md +0 -180
  158. package/docs/ui.md +0 -59
  159. package/docs/videos.md +0 -28
  160. package/docs/visual.md +0 -202
  161. package/docs/vue.md +0 -121
  162. package/docs/webapi/amOnPage.mustache +0 -11
  163. package/docs/webapi/appendField.mustache +0 -9
  164. package/docs/webapi/attachFile.mustache +0 -12
  165. package/docs/webapi/checkOption.mustache +0 -13
  166. package/docs/webapi/clearCookie.mustache +0 -10
  167. package/docs/webapi/clearField.mustache +0 -9
  168. package/docs/webapi/click.mustache +0 -25
  169. package/docs/webapi/clickLink.mustache +0 -8
  170. package/docs/webapi/closeCurrentTab.mustache +0 -7
  171. package/docs/webapi/closeOtherTabs.mustache +0 -8
  172. package/docs/webapi/dontSee.mustache +0 -11
  173. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  174. package/docs/webapi/dontSeeCookie.mustache +0 -8
  175. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  176. package/docs/webapi/dontSeeElement.mustache +0 -8
  177. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  178. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  179. package/docs/webapi/dontSeeInField.mustache +0 -11
  180. package/docs/webapi/dontSeeInSource.mustache +0 -8
  181. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  182. package/docs/webapi/doubleClick.mustache +0 -13
  183. package/docs/webapi/downloadFile.mustache +0 -12
  184. package/docs/webapi/dragAndDrop.mustache +0 -9
  185. package/docs/webapi/dragSlider.mustache +0 -11
  186. package/docs/webapi/executeAsyncScript.mustache +0 -24
  187. package/docs/webapi/executeScript.mustache +0 -26
  188. package/docs/webapi/fillField.mustache +0 -16
  189. package/docs/webapi/forceClick.mustache +0 -28
  190. package/docs/webapi/forceRightClick.mustache +0 -18
  191. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  192. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  193. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  194. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  195. package/docs/webapi/grabCookie.mustache +0 -11
  196. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  197. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  198. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  199. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  200. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  201. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  202. package/docs/webapi/grabGeoLocation.mustache +0 -8
  203. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  204. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  205. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  206. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  207. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  208. package/docs/webapi/grabPopupText.mustache +0 -5
  209. package/docs/webapi/grabSource.mustache +0 -8
  210. package/docs/webapi/grabTextFrom.mustache +0 -10
  211. package/docs/webapi/grabTextFromAll.mustache +0 -9
  212. package/docs/webapi/grabTitle.mustache +0 -8
  213. package/docs/webapi/grabValueFrom.mustache +0 -9
  214. package/docs/webapi/grabValueFromAll.mustache +0 -8
  215. package/docs/webapi/moveCursorTo.mustache +0 -12
  216. package/docs/webapi/openNewTab.mustache +0 -7
  217. package/docs/webapi/pressKey.mustache +0 -12
  218. package/docs/webapi/pressKeyDown.mustache +0 -12
  219. package/docs/webapi/pressKeyUp.mustache +0 -12
  220. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  221. package/docs/webapi/refreshPage.mustache +0 -6
  222. package/docs/webapi/resizeWindow.mustache +0 -6
  223. package/docs/webapi/rightClick.mustache +0 -14
  224. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  225. package/docs/webapi/saveScreenshot.mustache +0 -12
  226. package/docs/webapi/say.mustache +0 -10
  227. package/docs/webapi/scrollIntoView.mustache +0 -11
  228. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  229. package/docs/webapi/scrollPageToTop.mustache +0 -6
  230. package/docs/webapi/scrollTo.mustache +0 -12
  231. package/docs/webapi/see.mustache +0 -11
  232. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  233. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  234. package/docs/webapi/seeCookie.mustache +0 -8
  235. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  236. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  237. package/docs/webapi/seeElement.mustache +0 -8
  238. package/docs/webapi/seeElementInDOM.mustache +0 -8
  239. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  240. package/docs/webapi/seeInField.mustache +0 -12
  241. package/docs/webapi/seeInPopup.mustache +0 -8
  242. package/docs/webapi/seeInSource.mustache +0 -7
  243. package/docs/webapi/seeInTitle.mustache +0 -8
  244. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  245. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  246. package/docs/webapi/seeTextEquals.mustache +0 -9
  247. package/docs/webapi/seeTitleEquals.mustache +0 -8
  248. package/docs/webapi/selectOption.mustache +0 -21
  249. package/docs/webapi/setCookie.mustache +0 -16
  250. package/docs/webapi/setGeoLocation.mustache +0 -12
  251. package/docs/webapi/switchTo.mustache +0 -9
  252. package/docs/webapi/switchToNextTab.mustache +0 -10
  253. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  254. package/docs/webapi/type.mustache +0 -18
  255. package/docs/webapi/uncheckOption.mustache +0 -13
  256. package/docs/webapi/wait.mustache +0 -8
  257. package/docs/webapi/waitForClickable.mustache +0 -11
  258. package/docs/webapi/waitForDetached.mustache +0 -10
  259. package/docs/webapi/waitForElement.mustache +0 -11
  260. package/docs/webapi/waitForEnabled.mustache +0 -6
  261. package/docs/webapi/waitForFunction.mustache +0 -17
  262. package/docs/webapi/waitForInvisible.mustache +0 -10
  263. package/docs/webapi/waitForText.mustache +0 -13
  264. package/docs/webapi/waitForValue.mustache +0 -10
  265. package/docs/webapi/waitForVisible.mustache +0 -10
  266. package/docs/webapi/waitInUrl.mustache +0 -9
  267. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  268. package/docs/webapi/waitToHide.mustache +0 -10
  269. package/docs/webapi/waitUrlEquals.mustache +0 -10
  270. package/docs/webdriver.md +0 -657
  271. package/docs/wiki/Books-&-Posts.md +0 -27
  272. package/docs/wiki/Community-Helpers-&-Plugins.md +0 -49
  273. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -29
  274. package/docs/wiki/Examples.md +0 -139
  275. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
  276. package/docs/wiki/Home.md +0 -16
  277. package/docs/wiki/Release-Process.md +0 -24
  278. package/docs/wiki/Roadmap.md +0 -23
  279. package/docs/wiki/Tests.md +0 -1393
  280. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
  281. package/docs/wiki/Videos.md +0 -19
@@ -34,7 +34,8 @@ const config = {};
34
34
  * endpoint: 'http://site.com/api',
35
35
  * prettyPrintJson: true,
36
36
  * onRequest: (request) => {
37
- * request.headers.auth = '123';
37
+ * request.headers.auth = '123';
38
+ * }
38
39
  * }
39
40
  * }
40
41
  *}
@@ -136,6 +137,15 @@ class REST extends Helper {
136
137
  request.auth = this.headers.auth;
137
138
  }
138
139
 
140
+ if (typeof request.data === 'object') {
141
+ const returnedValue = {};
142
+ for (const [key, value] of Object.entries(request.data)) {
143
+ returnedValue[key] = value;
144
+ if (value instanceof Secret) returnedValue[key] = value.getMasked();
145
+ }
146
+ _debugRequest.data = returnedValue;
147
+ }
148
+
139
149
  if (request.data instanceof Secret) {
140
150
  _debugRequest.data = '*****';
141
151
  request.data = (typeof request.data === 'object' && !(request.data instanceof Secret)) ? { ...request.data.toString() } : request.data.toString();
@@ -198,7 +208,7 @@ class REST extends Helper {
198
208
  * ```
199
209
  *
200
210
  * @param {*} url
201
- * @param {object} [headers={}] - the headers object to be sent. By default it is sent as an empty object
211
+ * @param {object} [headers={}] - the headers object to be sent. By default, it is sent as an empty object
202
212
  *
203
213
  * @returns {Promise<*>} response
204
214
  */
@@ -222,8 +232,8 @@ class REST extends Helper {
222
232
  * ```
223
233
  *
224
234
  * @param {*} url
225
- * @param {*} [payload={}] - the payload to be sent. By default it is sent as an empty object
226
- * @param {object} [headers={}] - the headers object to be sent. By default it is sent as an empty object
235
+ * @param {*} [payload={}] - the payload to be sent. By default, it is sent as an empty object
236
+ * @param {object} [headers={}] - the headers object to be sent. By default, it is sent as an empty object
227
237
  *
228
238
  * @returns {Promise<*>} response
229
239
  */
@@ -317,7 +327,7 @@ class REST extends Helper {
317
327
  * ```
318
328
  *
319
329
  * @param {*} url
320
- * @param {object} [headers={}] - the headers object to be sent. By default it is sent as an empty object
330
+ * @param {object} [headers={}] - the headers object to be sent. By default, it is sent as an empty object
321
331
  *
322
332
  * @returns {Promise<*>} response
323
333
  */
@@ -20,7 +20,7 @@ const { urlEquals } = require('../assert/equal');
20
20
  const { empty } = require('../assert/empty');
21
21
  const { truth } = require('../assert/truth');
22
22
  const {
23
- xpathLocator,
23
+ xpathLocator, normalizeSpacesInString,
24
24
  } = require('../utils');
25
25
  const Locator = require('../locator');
26
26
 
@@ -346,6 +346,34 @@ class TestCafe extends Helper {
346
346
  return this.t.resizeWindow(width, height).catch(mapError);
347
347
  }
348
348
 
349
+ /**
350
+ * {{> focus }}
351
+ *
352
+ */
353
+ async focus(locator) {
354
+ const els = await this._locate(locator);
355
+ await assertElementExists(els, locator, 'Element to focus');
356
+ const element = await els.nth(0);
357
+
358
+ const focusElement = ClientFunction(() => element().focus(), { boundTestRun: this.t, dependencies: { element } });
359
+
360
+ return focusElement();
361
+ }
362
+
363
+ /**
364
+ * {{> blur }}
365
+ *
366
+ */
367
+ async blur(locator) {
368
+ const els = await this._locate(locator);
369
+ await assertElementExists(els, locator, 'Element to blur');
370
+ const element = await els.nth(0);
371
+
372
+ const blurElement = ClientFunction(() => element().blur(), { boundTestRun: this.t, dependencies: { element } });
373
+
374
+ return blurElement();
375
+ }
376
+
349
377
  /**
350
378
  * {{> click }}
351
379
  *
@@ -410,7 +438,7 @@ class TestCafe extends Helper {
410
438
  const el = await els.nth(0);
411
439
 
412
440
  return this.t
413
- .typeText(el, value, { replace: false })
441
+ .typeText(el, value.toString(), { replace: false })
414
442
  .catch(mapError);
415
443
  }
416
444
 
@@ -609,9 +637,9 @@ class TestCafe extends Helper {
609
637
  async see(text, context = null) {
610
638
  let els;
611
639
  if (context) {
612
- els = (await findElements.call(this, this.context, context)).withText(text);
640
+ els = (await findElements.call(this, this.context, context)).withText(normalizeSpacesInString(text));
613
641
  } else {
614
- els = (await findElements.call(this, this.context, '*')).withText(text);
642
+ els = (await findElements.call(this, this.context, '*')).withText(normalizeSpacesInString(text));
615
643
  }
616
644
 
617
645
  return this.t
@@ -699,13 +727,14 @@ class TestCafe extends Helper {
699
727
  * {{> seeInField }}
700
728
  */
701
729
  async seeInField(field, value) {
730
+ const _value = (typeof value === 'boolean') ? value : value.toString();
702
731
  // const expectedValue = findElements.call(this, this.context, field).value;
703
732
  const els = await findFields.call(this, field);
704
733
  assertElementExists(els, field, 'Field');
705
734
  const el = await els.nth(0);
706
735
 
707
736
  return this.t
708
- .expect(await el.value).eql(value)
737
+ .expect(await el.value).eql(_value)
709
738
  .catch(mapError);
710
739
  }
711
740
 
@@ -713,13 +742,14 @@ class TestCafe extends Helper {
713
742
  * {{> dontSeeInField }}
714
743
  */
715
744
  async dontSeeInField(field, value) {
745
+ const _value = (typeof value === 'boolean') ? value : value.toString();
716
746
  // const expectedValue = findElements.call(this, this.context, field).value;
717
747
  const els = await findFields.call(this, field);
718
748
  assertElementExists(els, field, 'Field');
719
749
  const el = await els.nth(0);
720
750
 
721
751
  return this.t
722
- .expect(el.value).notEql(value)
752
+ .expect(el.value).notEql(_value)
723
753
  .catch(mapError);
724
754
  }
725
755
 
@@ -792,7 +822,7 @@ class TestCafe extends Helper {
792
822
  /**
793
823
  * {{> executeScript }}
794
824
  *
795
- * If a function returns a Promise It will wait for it resolution.
825
+ * If a function returns a Promise It will wait for its resolution.
796
826
  */
797
827
  async executeScript(fn, ...args) {
798
828
  const browserFn = createClientFunction(fn, args).with({ boundTestRun: this.t });
@@ -932,8 +962,11 @@ class TestCafe extends Helper {
932
962
  const body = document.body;
933
963
  const html = document.documentElement;
934
964
  window.scrollTo(0, Math.max(
935
- body.scrollHeight, body.offsetHeight,
936
- html.clientHeight, html.scrollHeight, html.offsetHeight,
965
+ body.scrollHeight,
966
+ body.offsetHeight,
967
+ html.clientHeight,
968
+ html.scrollHeight,
969
+ html.offsetHeight,
937
970
  ));
938
971
  }).with({ boundTestRun: this.t })().catch(mapError);
939
972
  }
@@ -1192,7 +1225,9 @@ class TestCafe extends Helper {
1192
1225
  }
1193
1226
 
1194
1227
  async function waitForFunction(browserFn, waitTimeout) {
1195
- const pause = () => new Promise((done => setTimeout(done, 50)));
1228
+ const pause = () => new Promise((done => {
1229
+ setTimeout(done, 50);
1230
+ }));
1196
1231
 
1197
1232
  const start = Date.now();
1198
1233
  // eslint-disable-next-line no-constant-condition