codeceptjs 4.0.0-rc.9 → 4.0.0

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 (314) hide show
  1. package/README.md +9 -10
  2. package/bin/codecept.js +15 -2
  3. package/bin/codeceptq.js +49 -0
  4. package/bin/mcp-server.js +751 -172
  5. package/docs/advanced.md +201 -0
  6. package/docs/agents.md +181 -0
  7. package/docs/ai.md +489 -0
  8. package/docs/aitrace.md +266 -0
  9. package/docs/api.md +332 -0
  10. package/docs/architecture.md +235 -0
  11. package/docs/assertions.md +415 -0
  12. package/docs/auth.md +318 -0
  13. package/docs/basics.md +424 -0
  14. package/docs/bdd.md +539 -0
  15. package/docs/best.md +240 -0
  16. package/docs/bootstrap.md +132 -0
  17. package/docs/commands.md +352 -0
  18. package/docs/community-helpers.md +63 -0
  19. package/docs/configuration.md +185 -0
  20. package/docs/continuous-integration.md +431 -0
  21. package/docs/custom-helpers.md +297 -0
  22. package/docs/data.md +448 -0
  23. package/docs/debugging.md +332 -0
  24. package/docs/detox.md +235 -0
  25. package/docs/docker.md +107 -0
  26. package/docs/effects.md +179 -0
  27. package/docs/element-based-testing.md +295 -0
  28. package/docs/element-selection.md +125 -0
  29. package/docs/els.md +328 -0
  30. package/docs/environment-variables.md +131 -0
  31. package/docs/examples.md +160 -0
  32. package/docs/heal.md +213 -0
  33. package/docs/helpers/ApiDataFactory.md +267 -0
  34. package/docs/helpers/Appium.md +1419 -0
  35. package/docs/helpers/Detox.md +665 -0
  36. package/docs/helpers/ExpectHelper.md +275 -0
  37. package/docs/helpers/FileSystem.md +152 -0
  38. package/docs/helpers/GraphQL.md +152 -0
  39. package/docs/helpers/GraphQLDataFactory.md +226 -0
  40. package/docs/helpers/JSONResponse.md +255 -0
  41. package/docs/helpers/MockRequest.md +377 -0
  42. package/docs/helpers/Playwright.md +2970 -0
  43. package/docs/helpers/Puppeteer-firefox.md +86 -0
  44. package/docs/helpers/Puppeteer.md +2583 -0
  45. package/docs/helpers/REST.md +289 -0
  46. package/docs/helpers/WebDriver.md +2639 -0
  47. package/docs/hooks.md +148 -0
  48. package/docs/index.md +111 -0
  49. package/docs/installation.md +121 -0
  50. package/docs/internal-test-server.md +89 -0
  51. package/docs/locators.md +355 -0
  52. package/docs/mcp.md +485 -0
  53. package/docs/migrate-from-cypress.md +98 -0
  54. package/docs/migrate-from-java.md +108 -0
  55. package/docs/migrate-from-protractor.md +101 -0
  56. package/docs/migrate-from-testcafe.md +99 -0
  57. package/docs/migration-4.md +743 -0
  58. package/docs/mobile.md +338 -0
  59. package/docs/pageobjects.md +399 -0
  60. package/docs/parallel.md +187 -0
  61. package/docs/playwright.md +714 -0
  62. package/docs/plugins/aiTrace.md +49 -0
  63. package/docs/plugins/analyze.md +66 -0
  64. package/docs/plugins/auth.md +241 -0
  65. package/docs/plugins/autoDelay.md +48 -0
  66. package/docs/plugins/browser.md +41 -0
  67. package/docs/plugins/coverage.md +39 -0
  68. package/docs/plugins/customLocator.md +119 -0
  69. package/docs/plugins/customReporter.md +16 -0
  70. package/docs/plugins/expose.md +75 -0
  71. package/docs/plugins/heal.md +44 -0
  72. package/docs/plugins/junitReporter.md +51 -0
  73. package/docs/plugins/pageInfo.md +34 -0
  74. package/docs/plugins/pause.md +43 -0
  75. package/docs/plugins/pauseOnFail.md +18 -0
  76. package/docs/plugins/retryFailedStep.md +75 -0
  77. package/docs/plugins/screencast.md +55 -0
  78. package/docs/plugins/screenshot.md +58 -0
  79. package/docs/plugins/screenshotOnFail.md +18 -0
  80. package/docs/plugins/stepTimeout.md +65 -0
  81. package/docs/plugins.md +87 -0
  82. package/docs/puppeteer.md +314 -0
  83. package/docs/quickstart.md +120 -0
  84. package/docs/reports.md +198 -0
  85. package/docs/retry.md +311 -0
  86. package/docs/secrets.md +150 -0
  87. package/docs/sessions.md +80 -0
  88. package/docs/shadow.md +68 -0
  89. package/docs/store.md +94 -0
  90. package/docs/test-structure.md +275 -0
  91. package/docs/timeouts.md +183 -0
  92. package/docs/translation.md +247 -0
  93. package/docs/tutorial.md +323 -0
  94. package/docs/typescript.md +159 -0
  95. package/docs/web-element.md +251 -0
  96. package/docs/webdriver.md +641 -0
  97. package/docs/within.md +55 -0
  98. package/lib/actor.js +1 -36
  99. package/lib/ai.js +3 -2
  100. package/lib/aria.js +260 -0
  101. package/lib/assertions.js +18 -0
  102. package/lib/codecept.js +7 -7
  103. package/lib/command/check.js +2 -1
  104. package/lib/command/dryRun.js +24 -5
  105. package/lib/command/generate.js +2 -0
  106. package/lib/command/gherkin/snippets.js +5 -4
  107. package/lib/command/init.js +248 -266
  108. package/lib/command/list.js +150 -10
  109. package/lib/command/query.js +218 -0
  110. package/lib/command/run-multiple.js +3 -2
  111. package/lib/command/run-workers.js +1 -14
  112. package/lib/command/run.js +3 -17
  113. package/lib/command/utils.js +14 -0
  114. package/lib/command/workers/runTests.js +11 -15
  115. package/lib/config.js +77 -4
  116. package/lib/container.js +97 -15
  117. package/lib/effects.js +17 -0
  118. package/lib/element/WebElement.js +194 -2
  119. package/lib/els.js +12 -6
  120. package/lib/globals.js +32 -19
  121. package/lib/heal.js +7 -4
  122. package/lib/helper/ApiDataFactory.js +2 -1
  123. package/lib/helper/FileSystem.js +3 -2
  124. package/lib/helper/GraphQLDataFactory.js +2 -1
  125. package/lib/helper/Playwright.js +63 -70
  126. package/lib/helper/Puppeteer.js +20 -109
  127. package/lib/helper/WebDriver.js +13 -30
  128. package/lib/helper/errors/NonFocusedType.js +8 -0
  129. package/lib/helper/extras/Download.js +45 -0
  130. package/lib/helper/extras/PlaywrightLocator.js +10 -0
  131. package/lib/helper/extras/elementSelection.js +10 -3
  132. package/lib/helper/extras/focusCheck.js +43 -0
  133. package/lib/helper/extras/richTextEditor.js +178 -0
  134. package/lib/history.js +3 -2
  135. package/lib/html.js +90 -16
  136. package/lib/index.js +9 -1
  137. package/lib/listener/config.js +6 -4
  138. package/lib/listener/emptyRun.js +2 -1
  139. package/lib/listener/helpers.js +4 -1
  140. package/lib/listener/mocha.js +2 -1
  141. package/lib/listener/pageobjects.js +43 -0
  142. package/lib/listener/result.js +3 -2
  143. package/lib/locator.js +126 -16
  144. package/lib/mocha/cli.js +4 -2
  145. package/lib/mocha/factory.js +7 -2
  146. package/lib/mocha/inject.js +1 -1
  147. package/lib/mocha/scenarioConfig.js +2 -1
  148. package/lib/mocha/ui.js +5 -6
  149. package/lib/parser.js +2 -2
  150. package/lib/pause.js +38 -4
  151. package/lib/plugin/aiTrace.js +96 -103
  152. package/lib/plugin/analyze.js +9 -9
  153. package/lib/plugin/auth.js +3 -3
  154. package/lib/plugin/browser.js +77 -0
  155. package/lib/plugin/expose.js +159 -0
  156. package/lib/plugin/heal.js +47 -3
  157. package/lib/plugin/junitReporter.js +303 -0
  158. package/lib/plugin/pageInfo.js +54 -52
  159. package/lib/plugin/pause.js +131 -0
  160. package/lib/plugin/pauseOnFail.js +11 -33
  161. package/lib/plugin/retryFailedStep.js +15 -13
  162. package/lib/plugin/screencast.js +289 -0
  163. package/lib/plugin/screenshot.js +558 -0
  164. package/lib/plugin/screenshotOnFail.js +9 -170
  165. package/lib/plugin/stepTimeout.js +3 -2
  166. package/lib/recorder.js +1 -1
  167. package/lib/rerun.js +2 -1
  168. package/lib/result.js +2 -1
  169. package/lib/step/base.js +10 -9
  170. package/lib/step/comment.js +2 -2
  171. package/lib/step/config.js +7 -0
  172. package/lib/step/helper.js +4 -4
  173. package/lib/step/meta.js +3 -3
  174. package/lib/step/record.js +5 -5
  175. package/lib/store.js +72 -3
  176. package/lib/translation.js +2 -1
  177. package/lib/utils/mask_data.js +2 -1
  178. package/lib/utils/pluginParser.js +151 -0
  179. package/lib/utils/trace.js +297 -0
  180. package/lib/utils.js +29 -3
  181. package/lib/workers.js +14 -22
  182. package/package.json +17 -14
  183. package/typings/index.d.ts +0 -5
  184. package/docs/webapi/amOnPage.mustache +0 -11
  185. package/docs/webapi/appendField.mustache +0 -16
  186. package/docs/webapi/attachFile.mustache +0 -24
  187. package/docs/webapi/blur.mustache +0 -18
  188. package/docs/webapi/checkOption.mustache +0 -13
  189. package/docs/webapi/clearCookie.mustache +0 -9
  190. package/docs/webapi/clearField.mustache +0 -14
  191. package/docs/webapi/click.mustache +0 -29
  192. package/docs/webapi/clickLink.mustache +0 -8
  193. package/docs/webapi/closeCurrentTab.mustache +0 -7
  194. package/docs/webapi/closeOtherTabs.mustache +0 -8
  195. package/docs/webapi/dontSee.mustache +0 -11
  196. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  197. package/docs/webapi/dontSeeCookie.mustache +0 -8
  198. package/docs/webapi/dontSeeCurrentPathEquals.mustache +0 -10
  199. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  200. package/docs/webapi/dontSeeElement.mustache +0 -12
  201. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  202. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  203. package/docs/webapi/dontSeeInField.mustache +0 -16
  204. package/docs/webapi/dontSeeInSource.mustache +0 -8
  205. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  206. package/docs/webapi/dontSeeTraffic.mustache +0 -13
  207. package/docs/webapi/doubleClick.mustache +0 -13
  208. package/docs/webapi/downloadFile.mustache +0 -12
  209. package/docs/webapi/dragAndDrop.mustache +0 -9
  210. package/docs/webapi/dragSlider.mustache +0 -11
  211. package/docs/webapi/executeAsyncScript.mustache +0 -24
  212. package/docs/webapi/executeScript.mustache +0 -26
  213. package/docs/webapi/fillField.mustache +0 -21
  214. package/docs/webapi/flushNetworkTraffics.mustache +0 -5
  215. package/docs/webapi/focus.mustache +0 -13
  216. package/docs/webapi/forceClick.mustache +0 -28
  217. package/docs/webapi/forceRightClick.mustache +0 -18
  218. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  219. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  220. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  221. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  222. package/docs/webapi/grabCookie.mustache +0 -11
  223. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  224. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  225. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  226. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  227. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  228. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  229. package/docs/webapi/grabGeoLocation.mustache +0 -8
  230. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  231. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  232. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  233. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  234. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  235. package/docs/webapi/grabPopupText.mustache +0 -5
  236. package/docs/webapi/grabRecordedNetworkTraffics.mustache +0 -10
  237. package/docs/webapi/grabSource.mustache +0 -8
  238. package/docs/webapi/grabTextFrom.mustache +0 -10
  239. package/docs/webapi/grabTextFromAll.mustache +0 -9
  240. package/docs/webapi/grabTitle.mustache +0 -8
  241. package/docs/webapi/grabValueFrom.mustache +0 -9
  242. package/docs/webapi/grabValueFromAll.mustache +0 -8
  243. package/docs/webapi/grabWebElement.mustache +0 -9
  244. package/docs/webapi/grabWebElements.mustache +0 -9
  245. package/docs/webapi/moveCursorTo.mustache +0 -16
  246. package/docs/webapi/openNewTab.mustache +0 -7
  247. package/docs/webapi/pressKey.mustache +0 -12
  248. package/docs/webapi/pressKeyDown.mustache +0 -12
  249. package/docs/webapi/pressKeyUp.mustache +0 -12
  250. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  251. package/docs/webapi/refreshPage.mustache +0 -6
  252. package/docs/webapi/resizeWindow.mustache +0 -6
  253. package/docs/webapi/rightClick.mustache +0 -14
  254. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  255. package/docs/webapi/saveScreenshot.mustache +0 -12
  256. package/docs/webapi/say.mustache +0 -10
  257. package/docs/webapi/scrollIntoView.mustache +0 -11
  258. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  259. package/docs/webapi/scrollPageToTop.mustache +0 -6
  260. package/docs/webapi/scrollTo.mustache +0 -12
  261. package/docs/webapi/see.mustache +0 -11
  262. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  263. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  264. package/docs/webapi/seeCookie.mustache +0 -8
  265. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  266. package/docs/webapi/seeCurrentPathEquals.mustache +0 -10
  267. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  268. package/docs/webapi/seeElement.mustache +0 -12
  269. package/docs/webapi/seeElementInDOM.mustache +0 -8
  270. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  271. package/docs/webapi/seeInField.mustache +0 -17
  272. package/docs/webapi/seeInPopup.mustache +0 -8
  273. package/docs/webapi/seeInSource.mustache +0 -7
  274. package/docs/webapi/seeInTitle.mustache +0 -8
  275. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  276. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  277. package/docs/webapi/seeTextEquals.mustache +0 -9
  278. package/docs/webapi/seeTitleEquals.mustache +0 -8
  279. package/docs/webapi/seeTraffic.mustache +0 -36
  280. package/docs/webapi/selectOption.mustache +0 -26
  281. package/docs/webapi/setCookie.mustache +0 -16
  282. package/docs/webapi/setGeoLocation.mustache +0 -12
  283. package/docs/webapi/startRecordingTraffic.mustache +0 -8
  284. package/docs/webapi/startRecordingWebSocketMessages.mustache +0 -8
  285. package/docs/webapi/stopRecordingTraffic.mustache +0 -5
  286. package/docs/webapi/stopRecordingWebSocketMessages.mustache +0 -7
  287. package/docs/webapi/switchTo.mustache +0 -9
  288. package/docs/webapi/switchToNextTab.mustache +0 -10
  289. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  290. package/docs/webapi/type.mustache +0 -21
  291. package/docs/webapi/uncheckOption.mustache +0 -13
  292. package/docs/webapi/wait.mustache +0 -8
  293. package/docs/webapi/waitForClickable.mustache +0 -11
  294. package/docs/webapi/waitForCookie.mustache +0 -9
  295. package/docs/webapi/waitForDetached.mustache +0 -10
  296. package/docs/webapi/waitForDisabled.mustache +0 -6
  297. package/docs/webapi/waitForElement.mustache +0 -11
  298. package/docs/webapi/waitForEnabled.mustache +0 -6
  299. package/docs/webapi/waitForFunction.mustache +0 -17
  300. package/docs/webapi/waitForInvisible.mustache +0 -10
  301. package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
  302. package/docs/webapi/waitForText.mustache +0 -13
  303. package/docs/webapi/waitForValue.mustache +0 -10
  304. package/docs/webapi/waitForVisible.mustache +0 -10
  305. package/docs/webapi/waitInUrl.mustache +0 -9
  306. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  307. package/docs/webapi/waitToHide.mustache +0 -10
  308. package/docs/webapi/waitUrlEquals.mustache +0 -10
  309. package/lib/helper/AI.js +0 -214
  310. package/lib/helper/Mochawesome.js +0 -96
  311. package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -52
  312. package/lib/helper/extras/React.js +0 -65
  313. package/lib/plugin/stepByStepReport.js +0 -431
  314. package/lib/plugin/subtitles.js +0 -89
package/lib/helper/AI.js DELETED
@@ -1,214 +0,0 @@
1
- import HelperModule from '@codeceptjs/helper'
2
- import ora from 'ora-classic'
3
- import fs from 'fs'
4
- import path from 'path'
5
- import ai from '../ai.js'
6
- import Container from '../container.js'
7
- import { splitByChunks, minifyHtml } from '../html.js'
8
- import { beautify } from '../utils.js'
9
- import output from '../output.js'
10
- import { registerVariable } from '../pause.js'
11
-
12
- const standardActingHelpers = Container.STANDARD_ACTING_HELPERS
13
-
14
- const gtpRole = {
15
- user: 'user',
16
- }
17
-
18
- /**
19
- * AI Helper for CodeceptJS.
20
- *
21
- * This helper class provides integration with the AI 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.
22
- * This helper should be enabled with any web helpers like Playwright or Puppeteer or WebDriver to ensure the HTML context is available.
23
- *
24
- * Use it only in development mode. It is recommended to run it only inside pause() mode.
25
- *
26
- * ## Configuration
27
- *
28
- * This helper should be configured in codecept.conf.{js|ts}
29
- *
30
- * * `chunkSize`: (optional, default: 80000) - The maximum number of characters to send to the AI API at once. We split HTML fragments by 8000 chars to not exceed token limit. Increase this value if you use GPT-4.
31
- */
32
- class AI extends Helper {
33
- constructor(config) {
34
- super(config)
35
- this.aiAssistant = ai
36
-
37
- this.options = {
38
- chunkSize: 80000,
39
- }
40
- this.options = { ...this.options, ...config }
41
- this.aiAssistant.enable(this.config)
42
- }
43
-
44
- _beforeSuite() {
45
- const helpers = Container.helpers()
46
-
47
- for (const helperName of standardActingHelpers) {
48
- if (Object.keys(helpers).indexOf(helperName) > -1) {
49
- this.helper = helpers[helperName]
50
- break
51
- }
52
- }
53
- }
54
-
55
- /**
56
- * Asks the AI GPT language model a question based on the provided prompt within the context of the current page's HTML.
57
- *
58
- * ```js
59
- * I.askGptOnPage('what does this page do?');
60
- * ```
61
- *
62
- * @async
63
- * @param {string} prompt - The question or prompt to ask the GPT model.
64
- * @returns {Promise<string>} - A Promise that resolves to the generated responses from the GPT model, joined by newlines.
65
- */
66
- async askGptOnPage(prompt) {
67
- const html = await this.helper.grabSource()
68
-
69
- const htmlChunks = splitByChunks(html, this.options.chunkSize)
70
-
71
- if (htmlChunks.length > 1) this.debug(`Splitting HTML into ${htmlChunks.length} chunks`)
72
-
73
- const responses = []
74
-
75
- for (const chunk of htmlChunks) {
76
- const messages = [
77
- { role: gtpRole.user, content: prompt },
78
- { role: gtpRole.user, content: `Within this HTML: ${await minifyHtml(chunk)}` },
79
- ]
80
-
81
- if (htmlChunks.length > 1)
82
- messages.push({
83
- role: 'user',
84
- content: 'If action is not possible on this page, do not propose anything, I will send another HTML fragment',
85
- })
86
-
87
- const response = await this._processAIRequest(messages)
88
-
89
- output.print(response)
90
-
91
- responses.push(response)
92
- }
93
-
94
- return responses.join('\n\n')
95
- }
96
-
97
- /**
98
- * Asks the AI a question based on the provided prompt within the context of a specific HTML fragment on the current page.
99
- *
100
- * ```js
101
- * I.askGptOnPageFragment('describe features of this screen', '.screen');
102
- * ```
103
- *
104
- * @async
105
- * @param {string} prompt - The question or prompt to ask the GPT-3.5 model.
106
- * @param {string} locator - The locator or selector used to identify the HTML fragment on the page.
107
- * @returns {Promise<string>} - A Promise that resolves to the generated response from the GPT model.
108
- */
109
- async askGptOnPageFragment(prompt, locator) {
110
- const html = await this.helper.grabHTMLFrom(locator)
111
-
112
- const messages = [
113
- { role: gtpRole.user, content: prompt },
114
- { role: gtpRole.user, content: `Within this HTML: ${await minifyHtml(html)}` },
115
- ]
116
-
117
- const response = await this._processAIRequest(messages)
118
-
119
- output.print(response)
120
-
121
- return response
122
- }
123
-
124
- /**
125
- * Send a general request to AI and return response.
126
- * @param {string} prompt
127
- * @returns {Promise<string>} - A Promise that resolves to the generated response from the GPT model.
128
- */
129
- async askGptGeneralPrompt(prompt) {
130
- const messages = [{ role: gtpRole.user, content: prompt }]
131
-
132
- const response = await this._processAIRequest(messages)
133
-
134
- output.print(response)
135
-
136
- return response
137
- }
138
-
139
- /**
140
- * Generates PageObject for current page using AI.
141
- *
142
- * It saves the PageObject to the output directory. You can review the page object and adjust it as needed and move to pages directory.
143
- * Prompt can be customized in a global config file.
144
- *
145
- * ```js
146
- * // create page object for whole page
147
- * I.askForPageObject('home');
148
- *
149
- * // create page object with extra prompt
150
- * I.askForPageObject('home', 'implement signIn(username, password) method');
151
- *
152
- * // create page object for a specific element
153
- * I.askForPageObject('home', null, '.detail');
154
- * ```
155
- *
156
- * Asks for a page object based on the provided page name, locator, and extra prompt.
157
- *
158
- * @async
159
- * @param {string} pageName - The name of the page to retrieve the object for.
160
- * @param {string|null} [extraPrompt=null] - An optional extra prompt for additional context or information.
161
- * @param {string|null} [locator=null] - An optional locator to find a specific element on the page.
162
- * @returns {Promise<Object>} A promise that resolves to the requested page object.
163
- */
164
- async askForPageObject(pageName, extraPrompt = null, locator = null) {
165
- const spinner = ora(' Processing AI request...').start()
166
-
167
- try {
168
- const html = locator ? await this.helper.grabHTMLFrom(locator) : await this.helper.grabSource()
169
- await this.aiAssistant.setHtmlContext(html)
170
- const response = await this.aiAssistant.generatePageObject(extraPrompt, locator)
171
- spinner.stop()
172
-
173
- if (!response[0]) {
174
- output.error('No response from AI')
175
- return ''
176
- }
177
-
178
- const code = beautify(response[0])
179
-
180
- output.print('----- Generated PageObject ----')
181
- output.print(code)
182
- output.print('-------------------------------')
183
-
184
- const fileName = path.join(output_dir, `${pageName}Page-${Date.now()}.js`)
185
-
186
- output.print(output.styles.bold(`Page object for ${pageName} is saved to ${output.styles.bold(fileName)}`))
187
- fs.writeFileSync(fileName, code)
188
-
189
- try {
190
- registerVariable('page', require(fileName))
191
- output.success('Page object registered for this session as `page` variable')
192
- output.print('Use `=>page.methodName()` in shell to run methods of page object')
193
- output.print('Use `click(page.locatorName)` to check locators of page object')
194
- } catch (err) {
195
- output.error('Error while registering page object')
196
- output.error(err.message)
197
- }
198
-
199
- return code
200
- } catch (e) {
201
- spinner.stop()
202
- throw Error(`Something went wrong! ${e.message}`)
203
- }
204
- }
205
-
206
- async _processAIRequest(messages) {
207
- const spinner = ora(' Processing AI request...').start()
208
- const response = await this.aiAssistant.createCompletion(messages)
209
- spinner.stop()
210
- return response
211
- }
212
- }
213
-
214
- export default AI
@@ -1,96 +0,0 @@
1
- let currentTest
2
- let currentSuite
3
-
4
- import Helper from '@codeceptjs/helper'
5
- import { createRequire } from 'module'
6
- import { clearString } from '../utils.js'
7
- import { testToFileName } from '../mocha/test.js'
8
-
9
- class Mochawesome extends Helper {
10
- constructor(config) {
11
- super(config)
12
-
13
- // set defaults
14
- this.options = {
15
- uniqueScreenshotNames: false,
16
- disableScreenshots: false,
17
- }
18
-
19
- // ESM-compatible require for CommonJS module
20
- const require = createRequire(import.meta.url)
21
- this._addContext = require('mochawesome/addContext')
22
-
23
- this._createConfig(config)
24
- }
25
-
26
- _createConfig(config) {
27
- // override defaults with config
28
- Object.assign(this.options, config)
29
- }
30
-
31
- _beforeSuite(suite) {
32
- currentSuite = suite
33
- currentTest = ''
34
- }
35
-
36
- _before() {
37
- if (currentSuite && currentSuite.ctx) {
38
- currentTest = { test: currentSuite.ctx.currentTest }
39
- }
40
- }
41
-
42
- _test(test) {
43
- // If this is a retried test, we want to add context to the retried test
44
- // but also potentially preserve context from the original test
45
- const originalTest = test.retriedTest && test.retriedTest()
46
- if (originalTest) {
47
- // This is a retried test - use the retried test for context
48
- currentTest = { test }
49
-
50
- // Optionally copy context from original test if it exists
51
- // Note: mochawesome context is stored in test.ctx, but we need to be careful
52
- // not to break the mocha context structure
53
- } else {
54
- // Normal test (not a retry)
55
- currentTest = { test }
56
- }
57
- }
58
-
59
- _failed(test) {
60
- if (this.options.disableScreenshots) return
61
- let fileName
62
- // Get proper name if we are fail on hook
63
- if (test.ctx?.test?.type === 'hook') {
64
- currentTest = { test: test.ctx.test }
65
- // ignore retries if we are in hook
66
- test._retries = -1
67
- fileName = clearString(`${test.title}_${currentTest.test.title}`)
68
- } else {
69
- currentTest = { test }
70
- fileName = testToFileName(test)
71
- }
72
- if (this.options.uniqueScreenshotNames) {
73
- fileName = testToFileName(test, { unique: true })
74
- }
75
- if (test._retries < 1 || test._retries === test.retryNum) {
76
- fileName = `${fileName}.failed.png`
77
- return this._addContext(currentTest, fileName)
78
- }
79
- }
80
-
81
- addMochawesomeContext(context) {
82
- if (currentTest === '') currentTest = { test: currentSuite.ctx.test }
83
-
84
- // For retried tests, make sure we're adding context to the current (retried) test
85
- // not the original test
86
- let targetTest = currentTest
87
- if (currentTest.test && currentTest.test.retriedTest && currentTest.test.retriedTest()) {
88
- // This test has been retried, make sure we're using the current test for context
89
- targetTest = { test: currentTest.test }
90
- }
91
-
92
- return this._addContext(targetTest, context)
93
- }
94
- }
95
-
96
- export default Mochawesome
@@ -1,52 +0,0 @@
1
- async function findReact(matcher, locator) {
2
- // Handle both Locator objects and raw locator objects
3
- const reactLocator = locator.locator || locator
4
- let _locator = `_react=${reactLocator.react}`;
5
- let props = '';
6
-
7
- if (reactLocator.props) {
8
- props += propBuilder(reactLocator.props);
9
- _locator += props;
10
- }
11
- return matcher.locator(_locator).all();
12
- }
13
-
14
- async function findVue(matcher, locator) {
15
- // Handle both Locator objects and raw locator objects
16
- const vueLocator = locator.locator || locator
17
- let _locator = `_vue=${vueLocator.vue}`;
18
- let props = '';
19
-
20
- if (vueLocator.props) {
21
- props += propBuilder(vueLocator.props);
22
- _locator += props;
23
- }
24
- return matcher.locator(_locator).all();
25
- }
26
-
27
- async function findByPlaywrightLocator(matcher, locator) {
28
- // Handle both Locator objects and raw locator objects
29
- const pwLocator = locator.locator || locator
30
- if (pwLocator && pwLocator.toString && pwLocator.toString().includes(process.env.testIdAttribute)) {
31
- return matcher.getByTestId(pwLocator.pw.value.split('=')[1]);
32
- }
33
- const pwValue = typeof pwLocator.pw === 'string' ? pwLocator.pw : pwLocator.pw
34
- return matcher.locator(pwValue).all();
35
- }
36
-
37
- function propBuilder(props) {
38
- let _props = '';
39
-
40
- for (const [key, value] of Object.entries(props)) {
41
- if (typeof value === 'object') {
42
- for (const [k, v] of Object.entries(value)) {
43
- _props += `[${key}.${k} = "${v}"]`;
44
- }
45
- } else {
46
- _props += `[${key} = "${value}"]`;
47
- }
48
- }
49
- return _props;
50
- }
51
-
52
- export { findReact, findVue, findByPlaywrightLocator };
@@ -1,65 +0,0 @@
1
- import fs from 'fs'
2
-
3
- let resqScript
4
-
5
- export default async function findReact(matcher, locator) {
6
- if (!resqScript) resqScript = fs.readFileSync(new URL('resq', import.meta.resolve('resq')).pathname)
7
- await matcher.evaluate(resqScript.toString())
8
- await matcher.evaluate(() => window.resq.waitToLoadReact())
9
- const arrayHandle = await matcher.evaluateHandle(
10
- obj => {
11
- const { selector, props, state } = obj
12
-
13
- let elements = window.resq.resq$$(selector)
14
- if (Object.keys(props).length) {
15
- elements = elements.byProps(props)
16
- }
17
- if (Object.keys(state).length) {
18
- elements = elements.byState(state)
19
- }
20
-
21
- if (!elements.length) {
22
- return []
23
- }
24
-
25
- // resq returns an array of HTMLElements if the React component is a fragment
26
- // this avoids having nested arrays of nodes which the driver does not understand
27
- // [[div, div], [div, div]] => [div, div, div, div]
28
- let nodes = []
29
-
30
- elements.forEach(element => {
31
- let { node, isFragment } = element
32
-
33
- if (!node) {
34
- isFragment = true
35
- node = element.children
36
- }
37
-
38
- if (isFragment) {
39
- nodes = nodes.concat(node)
40
- } else {
41
- nodes.push(node)
42
- }
43
- })
44
-
45
- return [...nodes]
46
- },
47
- {
48
- selector: locator.react,
49
- props: locator.props || {},
50
- state: locator.state || {},
51
- },
52
- )
53
-
54
- const properties = await arrayHandle.getProperties()
55
- await arrayHandle.dispose()
56
- const result = []
57
- for (const property of properties.values()) {
58
- const elementHandle = property.asElement()
59
- if (elementHandle) {
60
- result.push(elementHandle)
61
- }
62
- }
63
-
64
- return result
65
- }