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
@@ -0,0 +1,422 @@
1
+ const chai = require('chai');
2
+ const output = require('../output');
3
+
4
+ const { expect } = chai;
5
+
6
+ chai.use(require('chai-string'));
7
+ // @ts-ignore
8
+ chai.use(require('chai-exclude'));
9
+ chai.use(require('chai-match-pattern'));
10
+
11
+ /**
12
+ * This helper allows performing assertions based on Chai.
13
+ *
14
+ * ### Examples
15
+ *
16
+ * Zero-configuration when paired with other helpers like REST, Playwright:
17
+ *
18
+ * ```js
19
+ * // inside codecept.conf.js
20
+ *{
21
+ * helpers: {
22
+ * Playwright: {...},
23
+ * Expect: {},
24
+ * }
25
+ *}
26
+ * ```
27
+ *
28
+ * ## Methods
29
+ */
30
+ class ExpectHelper {
31
+ /**
32
+ *
33
+ * @param {*} actualValue
34
+ * @param {*} expectedValue
35
+ * @param {*} [customErrorMsg]
36
+ */
37
+ expectEqual(actualValue, expectedValue, customErrorMsg = '') {
38
+ // @ts-ignore
39
+ output.step(`I expect "${JSON.stringify(actualValue)}" to equal "${JSON.stringify(expectedValue)}"`);
40
+ return expect(actualValue, customErrorMsg).to.equal(expectedValue);
41
+ }
42
+
43
+ /**
44
+ *
45
+ * @param {*} actualValue
46
+ * @param {*} expectedValue
47
+ * @param {*} [customErrorMsg]
48
+ */
49
+ expectNotEqual(actualValue, expectedValue, customErrorMsg = '') {
50
+ // @ts-ignore
51
+ output.step(`I expect "${JSON.stringify(actualValue)}" to not equal "${JSON.stringify(expectedValue)}"`);
52
+ return expect(actualValue, customErrorMsg).not.to.equal(expectedValue);
53
+ }
54
+
55
+ /**
56
+ *
57
+ * @param {*} actualValue
58
+ * @param {*} expectedValue
59
+ * @param {*} [customErrorMsg]
60
+
61
+ */
62
+ expectDeepEqual(actualValue, expectedValue, customErrorMsg = '') {
63
+ // @ts-ignore
64
+ output.step(`I expect "${JSON.stringify(actualValue)}" to deep equal "${JSON.stringify(expectedValue)}"`);
65
+ return expect(actualValue, customErrorMsg).to.deep.equal(expectedValue);
66
+ }
67
+
68
+ /**
69
+ *
70
+ * @param {*} actualValue
71
+ * @param {*} expectedValue
72
+ * @param {*} [customErrorMsg]
73
+ */
74
+ expectNotDeepEqual(actualValue, expectedValue, customErrorMsg = '') {
75
+ // @ts-ignore
76
+ output.step(`I expect "${JSON.stringify(actualValue)}" to not deep equal "${JSON.stringify(expectedValue)}"`);
77
+ return expect(actualValue, customErrorMsg).to.not.deep.equal(expectedValue);
78
+ }
79
+
80
+ /**
81
+ *
82
+ * @param {*} actualValue
83
+ * @param {*} expectedValueToContain
84
+ * @param {*} [customErrorMsg]
85
+ */
86
+ expectContain(actualValue, expectedValueToContain, customErrorMsg = '') {
87
+ // @ts-ignore
88
+ output.step(`I expect "${JSON.stringify(actualValue)}" to contain "${JSON.stringify(expectedValueToContain)}"`);
89
+ return expect(actualValue, customErrorMsg).to.contain(
90
+ expectedValueToContain,
91
+ );
92
+ }
93
+
94
+ /**
95
+ *
96
+ * @param {*} actualValue
97
+ * @param {*} expectedValueToNotContain
98
+ * @param {*} [customErrorMsg]
99
+ */
100
+ expectNotContain(
101
+ actualValue,
102
+ expectedValueToNotContain,
103
+ customErrorMsg = '',
104
+ ) {
105
+ // @ts-ignore
106
+ output.step(`I expect "${JSON.stringify(actualValue)}" to not contain "${JSON.stringify(expectedValueToNotContain)}"`);
107
+ return expect(actualValue, customErrorMsg).not.to.contain(
108
+ expectedValueToNotContain,
109
+ );
110
+ }
111
+
112
+ /**
113
+ *
114
+ * @param {*} actualValue
115
+ * @param {*} expectedValueToStartWith
116
+ * @param {*} [customErrorMsg]
117
+ */
118
+ expectStartsWith(actualValue, expectedValueToStartWith, customErrorMsg = '') {
119
+ // @ts-ignore
120
+ output.step(`I expect "${JSON.stringify(actualValue)}" to start with "${JSON.stringify(expectedValueToStartWith)}"`);
121
+ return expect(actualValue, customErrorMsg).to.startsWith(
122
+ expectedValueToStartWith,
123
+ );
124
+ }
125
+
126
+ /**
127
+ *
128
+ * @param {*} actualValue
129
+ * @param {*} expectedValueToNotStartWith
130
+ * @param {*} [customErrorMsg]
131
+ */
132
+ expectNotStartsWith(
133
+ actualValue,
134
+ expectedValueToNotStartWith,
135
+ customErrorMsg = '',
136
+ ) {
137
+ // @ts-ignore
138
+ output.step(`I expect "${JSON.stringify(actualValue)}" to not start with "${JSON.stringify(expectedValueToNotStartWith)}"`);
139
+ return expect(actualValue, customErrorMsg).not.to.startsWith(
140
+ expectedValueToNotStartWith,
141
+ );
142
+ }
143
+
144
+ /**
145
+ * @param {*} actualValue
146
+ * @param {*} expectedValueToEndWith
147
+ * @param {*} [customErrorMsg]
148
+ */
149
+ expectEndsWith(actualValue, expectedValueToEndWith, customErrorMsg = '') {
150
+ // @ts-ignore
151
+ output.step(`I expect "${JSON.stringify(actualValue)}" to end with "${JSON.stringify(expectedValueToEndWith)}"`);
152
+ return expect(actualValue, customErrorMsg).to.endsWith(
153
+ expectedValueToEndWith,
154
+ );
155
+ }
156
+
157
+ /**
158
+ * @param {*} actualValue
159
+ * @param {*} expectedValueToNotEndWith
160
+ * @param {*} [customErrorMsg]
161
+ */
162
+ expectNotEndsWith(
163
+ actualValue,
164
+ expectedValueToNotEndWith,
165
+ customErrorMsg = '',
166
+ ) {
167
+ // @ts-ignore
168
+ output.step(`I expect "${JSON.stringify(actualValue)}" to not end with "${JSON.stringify(expectedValueToNotEndWith)}"`);
169
+ return expect(actualValue, customErrorMsg).not.to.endsWith(
170
+ expectedValueToNotEndWith,
171
+ );
172
+ }
173
+
174
+ /**
175
+ * @param {*} targetData
176
+ * @param {*} jsonSchema
177
+ * @param {*} [customErrorMsg]
178
+ */
179
+ expectJsonSchema(targetData, jsonSchema, customErrorMsg = '') {
180
+ // @ts-ignore
181
+ output.step(`I expect "${JSON.stringify(targetData)}" to match this JSON schema "${JSON.stringify(jsonSchema)}"`);
182
+ chai.use(require('chai-json-schema'));
183
+ return expect(targetData, customErrorMsg).to.be.jsonSchema(jsonSchema);
184
+ }
185
+
186
+ /**
187
+ * @param {*} targetData
188
+ * @param {*} jsonSchema
189
+ * @param {*} [customErrorMsg]
190
+ * @param {*} ajvOptions Pass AJV options
191
+ */
192
+ expectJsonSchemaUsingAJV(
193
+ targetData,
194
+ jsonSchema,
195
+ customErrorMsg = '',
196
+ ajvOptions = { allErrors: true },
197
+ ) {
198
+ // @ts-ignore
199
+ output.step(`I expect "${JSON.stringify(targetData)}" to match this JSON schema using AJV "${JSON.stringify(jsonSchema)}"`);
200
+ chai.use(require('chai-json-schema-ajv').create(ajvOptions));
201
+ return expect(targetData, customErrorMsg).to.be.jsonSchema(jsonSchema);
202
+ }
203
+
204
+ /**
205
+ * @param {*} targetData
206
+ * @param {*} propertyName
207
+ * @param {*} [customErrorMsg]
208
+ */
209
+ expectHasProperty(targetData, propertyName, customErrorMsg = '') {
210
+ // @ts-ignore
211
+ output.step(`I expect "${JSON.stringify(targetData)}" to have property: "${JSON.stringify(propertyName)}"`);
212
+ return expect(targetData, customErrorMsg).to.have.property(propertyName);
213
+ }
214
+
215
+ /**
216
+ * @param {*} targetData
217
+ * @param {*} propertyName
218
+ * @param {*} [customErrorMsg]
219
+ */
220
+ expectHasAProperty(targetData, propertyName, customErrorMsg = '') {
221
+ // @ts-ignore
222
+ output.step(`I expect "${JSON.stringify(targetData)}" to have a property: "${JSON.stringify(propertyName)}"`);
223
+ return expect(targetData, customErrorMsg).to.have.a.property(propertyName);
224
+ }
225
+
226
+ /**
227
+ * @param {*} targetData
228
+ * @param {*} type
229
+ * @param {*} [customErrorMsg]
230
+ */
231
+ expectToBeA(targetData, type, customErrorMsg = '') {
232
+ // @ts-ignore
233
+ output.step(`I expect "${JSON.stringify(targetData)}" to be a "${JSON.stringify(type)}"`);
234
+ return expect(targetData, customErrorMsg).to.be.a(type);
235
+ }
236
+
237
+ /**
238
+ * @param {*} targetData
239
+ * @param {*} type
240
+ * @param {*} [customErrorMsg]
241
+ */
242
+ expectToBeAn(targetData, type, customErrorMsg = '') {
243
+ // @ts-ignore
244
+ output.step(`I expect "${JSON.stringify(targetData)}" to be an "${JSON.stringify(type)}"`);
245
+ return expect(targetData, customErrorMsg).to.be.an(type);
246
+ }
247
+
248
+ /**
249
+ * @param {*} targetData
250
+ * @param {*} regex
251
+ * @param {*} [customErrorMsg]
252
+ */
253
+ expectMatchRegex(targetData, regex, customErrorMsg = '') {
254
+ // @ts-ignore
255
+ output.step(`I expect "${JSON.stringify(targetData)}" to match the regex "${JSON.stringify(regex)}"`);
256
+ return expect(targetData, customErrorMsg).to.match(regex);
257
+ }
258
+
259
+ /**
260
+ * @param {*} targetData
261
+ * @param {*} length
262
+ * @param {*} [customErrorMsg]
263
+ */
264
+ expectLengthOf(targetData, length, customErrorMsg = '') {
265
+ // @ts-ignore
266
+ output.step(`I expect "${JSON.stringify(targetData)}" to have length of "${JSON.stringify(length)}"`);
267
+ return expect(targetData, customErrorMsg).to.have.lengthOf(length);
268
+ }
269
+
270
+ /**
271
+ * @param {*} targetData
272
+ * @param {*} [customErrorMsg]
273
+ */
274
+ expectEmpty(targetData, customErrorMsg = '') {
275
+ // @ts-ignore
276
+ output.step(`I expect "${JSON.stringify(targetData)}" to be empty`);
277
+ return expect(targetData, customErrorMsg).to.be.empty;
278
+ }
279
+
280
+ /**
281
+ * @param {*} targetData
282
+ * @param {*} [customErrorMsg]
283
+ */
284
+ expectTrue(targetData, customErrorMsg = '') {
285
+ // @ts-ignore
286
+ output.step(`I expect "${JSON.stringify(targetData)}" to be true`);
287
+ return expect(targetData, customErrorMsg).to.be.true;
288
+ }
289
+
290
+ /**
291
+ * @param {*} targetData
292
+ * @param {*} [customErrorMsg]
293
+ */
294
+ expectFalse(targetData, customErrorMsg = '') {
295
+ // @ts-ignore
296
+ output.step(`I expect "${JSON.stringify(targetData)}" to be false`);
297
+ return expect(targetData, customErrorMsg).to.be.false;
298
+ }
299
+
300
+ /**
301
+ * @param {*} targetData
302
+ * @param {*} aboveThan
303
+ * @param {*} [customErrorMsg]
304
+ */
305
+ expectAbove(targetData, aboveThan, customErrorMsg = '') {
306
+ // @ts-ignore
307
+ output.step(`I expect "${JSON.stringify(targetData)}" to be above ${JSON.stringify(aboveThan)}`);
308
+ return expect(targetData, customErrorMsg).to.be.above(aboveThan);
309
+ }
310
+
311
+ /**
312
+ * @param {*} targetData
313
+ * @param {*} belowThan
314
+ * @param {*} [customErrorMsg]
315
+ */
316
+ expectBelow(targetData, belowThan, customErrorMsg = '') {
317
+ // @ts-ignore
318
+ output.step(`I expect "${JSON.stringify(targetData)}" to be below ${JSON.stringify(belowThan)}`);
319
+ return expect(targetData, customErrorMsg).to.be.below(belowThan);
320
+ }
321
+
322
+ /**
323
+ * @param {*} targetData
324
+ * @param {*} lengthAboveThan
325
+ * @param {*} [customErrorMsg]
326
+ */
327
+ expectLengthAboveThan(targetData, lengthAboveThan, customErrorMsg = '') {
328
+ // @ts-ignore
329
+ output.step(`I expect "${JSON.stringify(targetData)}" to have length of above ${JSON.stringify(lengthAboveThan)}`);
330
+ return expect(targetData, customErrorMsg).to.have.lengthOf.above(
331
+ lengthAboveThan,
332
+ );
333
+ }
334
+
335
+ /**
336
+ * @param {*} targetData
337
+ * @param {*} lengthBelowThan
338
+ * @param {*} [customErrorMsg]
339
+ */
340
+ expectLengthBelowThan(targetData, lengthBelowThan, customErrorMsg = '') {
341
+ // @ts-ignore
342
+ output.step(`I expect "${JSON.stringify(targetData)}" to have length of below ${JSON.stringify(lengthBelowThan)}`);
343
+ return expect(targetData, customErrorMsg).to.have.lengthOf.below(
344
+ lengthBelowThan,
345
+ );
346
+ }
347
+
348
+ /**
349
+ * @param {*} actualValue
350
+ * @param {*} expectedValue
351
+ * @param {*} [customErrorMsg]
352
+ */
353
+ expectEqualIgnoreCase(actualValue, expectedValue, customErrorMsg = '') {
354
+ // @ts-ignore
355
+ output.step(`I expect and ingore case "${JSON.stringify(actualValue)}" to equal "${JSON.stringify(expectedValue)}"`);
356
+ return expect(actualValue, customErrorMsg).to.equalIgnoreCase(
357
+ expectedValue,
358
+ );
359
+ }
360
+
361
+ /**
362
+ * expects members of two arrays are deeply equal
363
+ * @param {*} actualValue
364
+ * @param {*} expectedValue
365
+ * @param {*} [customErrorMsg]
366
+ */
367
+ expectDeepMembers(actualValue, expectedValue, customErrorMsg = '') {
368
+ // @ts-ignore
369
+ output.step(`I expect members of "${JSON.stringify(actualValue)}" and "${JSON.stringify(expectedValue)}" arrays are deeply equal`);
370
+ return expect(actualValue, customErrorMsg).to.have.deep.members(
371
+ expectedValue,
372
+ );
373
+ }
374
+
375
+ /**
376
+ * expects an array to be a superset of another array
377
+ * @param {*} superset
378
+ * @param {*} set
379
+ * @param {*} [customErrorMsg]
380
+ */
381
+ expectDeepIncludeMembers(superset, set, customErrorMsg = '') {
382
+ // @ts-ignore
383
+ output.step(`I expect "${JSON.stringify(superset)}" array to be a superset of "${JSON.stringify(set)}" array`);
384
+ return expect(superset, customErrorMsg).to.deep.include.members(
385
+ set,
386
+ );
387
+ }
388
+
389
+ /**
390
+ * expects members of two JSON objects are deeply equal excluding some properties
391
+ * @param {*} actualValue
392
+ * @param {*} expectedValue
393
+ * @param {*} fieldsToExclude
394
+ * @param {*} [customErrorMsg]
395
+ */
396
+ expectDeepEqualExcluding(
397
+ actualValue,
398
+ expectedValue,
399
+ fieldsToExclude,
400
+ customErrorMsg = '',
401
+ ) {
402
+ // @ts-ignore
403
+ output.step(`I expect members of "${JSON.stringify(actualValue)}" and "${JSON.stringify(expectedValue)}" JSON objects are deeply equal excluding properties: ${JSON.stringify(fieldsToExclude)}`);
404
+ return expect(actualValue, customErrorMsg)
405
+ .excludingEvery(fieldsToExclude)
406
+ .to.deep.equal(expectedValue);
407
+ }
408
+
409
+ /**
410
+ * expects a JSON object matches a provided pattern
411
+ * @param {*} actualValue
412
+ * @param {*} expectedPattern
413
+ * @param {*} [customErrorMsg]
414
+ */
415
+ expectMatchesPattern(actualValue, expectedPattern, customErrorMsg = '') {
416
+ // @ts-ignore
417
+ output.step(`I expect "${JSON.stringify(actualValue)}" to match the ${JSON.stringify(expectedPattern)} pattern`);
418
+ return expect(actualValue, customErrorMsg).to.matchPattern(expectedPattern);
419
+ }
420
+ }
421
+
422
+ module.exports = ExpectHelper;
@@ -52,7 +52,7 @@ class FileSystem extends Helper {
52
52
  }
53
53
 
54
54
  /**
55
- * Writes test to file
55
+ * Writes text to file
56
56
  * @param {string} name
57
57
  * @param {string} text
58
58
  */
@@ -81,6 +81,8 @@ class GraphQL extends Helper {
81
81
  'Content-Type': 'application/json',
82
82
  });
83
83
 
84
+ request.headers = { ...this.headers, ...request.headers };
85
+
84
86
  if (this.config.onRequest) {
85
87
  await this.config.onRequest(request);
86
88
  }
@@ -200,5 +202,28 @@ class GraphQL extends Helper {
200
202
  _setRequestTimeout(newTimeout) {
201
203
  this.options.timeout = newTimeout;
202
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
+ }
203
228
  }
204
229
  module.exports = GraphQL;
@@ -300,16 +300,16 @@ class JSONResponse extends Helper {
300
300
  *
301
301
  * I.seeResponseMatchesJsonSchema(joi => {
302
302
  * return joi.object({
303
- * name: joi.string();
304
- * id: joi.number();
303
+ * name: joi.string(),
304
+ * id: joi.number()
305
305
  * })
306
306
  * });
307
307
  *
308
308
  * // or pass a valid schema
309
- * const joi = require('joi);
309
+ * const joi = require('joi');
310
310
  *
311
311
  * I.seeResponseMatchesJsonSchema(joi.object({
312
- * name: joi.string();
312
+ * name: joi.string(),
313
313
  * id: joi.number();
314
314
  * });
315
315
  * ```
@@ -694,7 +694,7 @@ class Nightmare extends Helper {
694
694
  async appendField(field, value) {
695
695
  const el = await findField.call(this, field);
696
696
  assertElementExists(el, field, 'Field');
697
- return this.browser.enterText(el, value, false)
697
+ return this.browser.enterText(el, value.toString(), false)
698
698
  .wait(this.options.waitForAction);
699
699
  }
700
700
 
@@ -702,14 +702,16 @@ class Nightmare extends Helper {
702
702
  * {{> seeInField }}
703
703
  */
704
704
  async seeInField(field, value) {
705
- return proceedSeeInField.call(this, 'assert', field, value);
705
+ const _value = (typeof value === 'boolean') ? value : value.toString();
706
+ return proceedSeeInField.call(this, 'assert', field, _value);
706
707
  }
707
708
 
708
709
  /**
709
710
  * {{> dontSeeInField }}
710
711
  */
711
712
  async dontSeeInField(field, value) {
712
- return proceedSeeInField.call(this, 'negate', field, value);
713
+ const _value = (typeof value === 'boolean') ? value : value.toString();
714
+ return proceedSeeInField.call(this, 'negate', field, _value);
713
715
  }
714
716
 
715
717
  /**
@@ -1261,8 +1263,11 @@ class Nightmare extends Helper {
1261
1263
  const body = document.body;
1262
1264
  const html = document.documentElement;
1263
1265
  window.scrollTo(0, Math.max(
1264
- body.scrollHeight, body.offsetHeight,
1265
- html.clientHeight, html.scrollHeight, html.offsetHeight
1266
+ body.scrollHeight,
1267
+ body.offsetHeight,
1268
+ html.clientHeight,
1269
+ html.scrollHeight,
1270
+ html.offsetHeight
1266
1271
  ));
1267
1272
  });
1268
1273
  /* eslint-enable */
@@ -0,0 +1,126 @@
1
+ const Helper = require('@codeceptjs/helper');
2
+ const AiAssistant = require('../ai');
3
+ const standardActingHelpers = require('../plugin/standardActingHelpers');
4
+ const Container = require('../container');
5
+ const { splitByChunks, minifyHtml } = require('../html');
6
+
7
+ /**
8
+ * OpenAI Helper for CodeceptJS.
9
+ *
10
+ * This helper class provides integration with the OpenAI GPT-3.5 or 4 language model for generating responses to questions or prompts within the context of web pages. It allows you to interact with the GPT-3.5 model to obtain intelligent responses based on HTML fragments or general prompts.
11
+ * This helper should be enabled with any web helpers like Playwright or Puppeteer or WebDrvier to ensure the HTML context is available.
12
+ *
13
+ * ## Configuration
14
+ *
15
+ * This helper should be configured in codecept.json or codecept.conf.js
16
+ *
17
+ * * `chunkSize`: (optional, default: 80000) - The maximum number of characters to send to the OpenAI API at once. We split HTML fragments by 8000 chars to not exceed token limit. Increase this value if you use GPT-4.
18
+ */
19
+ class OpenAI extends Helper {
20
+ constructor(config) {
21
+ super(config);
22
+ this.aiAssistant = new AiAssistant();
23
+
24
+ this.options = {
25
+ chunkSize: 80000,
26
+ };
27
+ this.options = { ...this.options, ...config };
28
+ }
29
+
30
+ _beforeSuite() {
31
+ const helpers = Container.helpers();
32
+
33
+ for (const helperName of standardActingHelpers) {
34
+ if (Object.keys(helpers).indexOf(helperName) > -1) {
35
+ this.helper = helpers[helperName];
36
+ break;
37
+ }
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Asks the OpenAI GPT language model a question based on the provided prompt within the context of the current page's HTML.
43
+ *
44
+ * ```js
45
+ * I.askGptOnPage('what does this page do?');
46
+ * ```
47
+ *
48
+ * @async
49
+ * @param {string} prompt - The question or prompt to ask the GPT model.
50
+ * @returns {Promise<string>} - A Promise that resolves to the generated responses from the GPT model, joined by newlines.
51
+ */
52
+ async askGptOnPage(prompt) {
53
+ const html = await this.helper.grabSource();
54
+
55
+ const htmlChunks = splitByChunks(html, this.options.chunkSize);
56
+
57
+ if (htmlChunks.length > 1) this.debug(`Splitting HTML into ${htmlChunks.length} chunks`);
58
+
59
+ const responses = [];
60
+
61
+ for (const chunk of htmlChunks) {
62
+ const messages = [
63
+ { role: 'user', content: prompt },
64
+ { role: 'user', content: `Within this HTML: ${minifyHtml(chunk)}` },
65
+ ];
66
+
67
+ if (htmlChunks.length > 1) messages.push({ role: 'user', content: 'If action is not possible on this page, do not propose anything, I will send another HTML fragment' });
68
+
69
+ const response = await this.aiAssistant.createCompletion(messages);
70
+
71
+ console.log(response);
72
+
73
+ responses.push(response);
74
+ }
75
+
76
+ return responses.join('\n\n');
77
+ }
78
+
79
+ /**
80
+ * Asks the OpenAI GPT-3.5 language model a question based on the provided prompt within the context of a specific HTML fragment on the current page.
81
+ *
82
+ * ```js
83
+ * I.askGptOnPageFragment('describe features of this screen', '.screen');
84
+ * ```
85
+ *
86
+ * @async
87
+ * @param {string} prompt - The question or prompt to ask the GPT-3.5 model.
88
+ * @param {string} locator - The locator or selector used to identify the HTML fragment on the page.
89
+ * @returns {Promise<string>} - A Promise that resolves to the generated response from the GPT model.
90
+ */
91
+ async askGptOnPageFragment(prompt, locator) {
92
+ const html = await this.helper.grabHTMLFrom(locator);
93
+
94
+ const messages = [
95
+ { role: 'user', content: prompt },
96
+ { role: 'user', content: `Within this HTML: ${minifyHtml(html)}` },
97
+ ];
98
+
99
+ const response = await this.aiAssistant.createCompletion(messages);
100
+
101
+ console.log(response);
102
+
103
+ return response;
104
+ }
105
+
106
+ /**
107
+ * Send a general request to ChatGPT and return response.
108
+ * @param {string} prompt
109
+ * @returns {Promise<string>} - A Promise that resolves to the generated response from the GPT model.
110
+ */
111
+ async askGptGeneralPrompt(prompt) {
112
+ const messages = [
113
+ { role: 'user', content: prompt },
114
+ ];
115
+
116
+ const completion = await this.aiAssistant.createCompletion(messages);
117
+
118
+ const response = completion?.data?.choices[0]?.message?.content;
119
+
120
+ console.log(response);
121
+
122
+ return response;
123
+ }
124
+ }
125
+
126
+ module.exports = OpenAI;