codeceptjs 4.0.0-rc.2 → 4.0.0-rc.21

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 (296) hide show
  1. package/README.md +39 -27
  2. package/bin/codecept.js +15 -2
  3. package/bin/codeceptq.js +49 -0
  4. package/bin/mcp-server.js +1189 -0
  5. package/docs/advanced.md +201 -0
  6. package/docs/agents.md +181 -0
  7. package/docs/ai.md +537 -0
  8. package/docs/aitrace.md +266 -0
  9. package/docs/api.md +332 -0
  10. package/docs/assertions.md +415 -0
  11. package/docs/auth.md +318 -0
  12. package/docs/basics.md +424 -0
  13. package/docs/bdd.md +539 -0
  14. package/docs/best.md +240 -0
  15. package/docs/bootstrap.md +132 -0
  16. package/docs/commands.md +352 -0
  17. package/docs/community-helpers.md +63 -0
  18. package/docs/configuration.md +230 -0
  19. package/docs/continuous-integration.md +497 -0
  20. package/docs/custom-helpers.md +297 -0
  21. package/docs/data.md +448 -0
  22. package/docs/debugging.md +332 -0
  23. package/docs/detox.md +235 -0
  24. package/docs/docker.md +136 -0
  25. package/docs/effects.md +179 -0
  26. package/docs/element-based-testing.md +295 -0
  27. package/docs/element-selection.md +125 -0
  28. package/docs/els.md +328 -0
  29. package/docs/environment-variables.md +131 -0
  30. package/docs/examples.md +161 -0
  31. package/docs/heal.md +213 -0
  32. package/docs/helpers/ApiDataFactory.md +267 -0
  33. package/docs/helpers/Appium.md +1405 -0
  34. package/docs/helpers/Detox.md +665 -0
  35. package/docs/helpers/ExpectHelper.md +275 -0
  36. package/docs/helpers/FileSystem.md +152 -0
  37. package/docs/helpers/GraphQL.md +152 -0
  38. package/docs/helpers/GraphQLDataFactory.md +226 -0
  39. package/docs/helpers/JSONResponse.md +255 -0
  40. package/docs/helpers/Mochawesome.md +8 -0
  41. package/docs/helpers/MockRequest.md +377 -0
  42. package/docs/helpers/MockServer.md +212 -0
  43. package/docs/helpers/Playwright.md +2969 -0
  44. package/docs/helpers/Polly.md +44 -0
  45. package/docs/helpers/Protractor.md +1769 -0
  46. package/docs/helpers/Puppeteer-firefox.md +86 -0
  47. package/docs/helpers/Puppeteer.md +2690 -0
  48. package/docs/helpers/REST.md +289 -0
  49. package/docs/helpers/SoftExpectHelper.md +352 -0
  50. package/docs/helpers/WebDriver.md +2682 -0
  51. package/docs/hooks.md +339 -0
  52. package/docs/index.md +111 -0
  53. package/docs/installation.md +83 -0
  54. package/docs/internal-api.md +265 -0
  55. package/docs/internal-test-server.md +89 -0
  56. package/docs/locators.md +355 -0
  57. package/docs/mcp.md +485 -0
  58. package/docs/migration-4.md +556 -0
  59. package/docs/mobile.md +338 -0
  60. package/docs/pageobjects.md +399 -0
  61. package/docs/parallel.md +585 -0
  62. package/docs/playwright.md +714 -0
  63. package/docs/plugins.md +866 -0
  64. package/docs/puppeteer.md +314 -0
  65. package/docs/quickstart.md +120 -0
  66. package/docs/react.md +70 -0
  67. package/docs/reports.md +483 -0
  68. package/docs/retry.md +274 -0
  69. package/docs/secrets.md +150 -0
  70. package/docs/sessions.md +80 -0
  71. package/docs/shadow.md +68 -0
  72. package/docs/test-structure.md +275 -0
  73. package/docs/timeouts.md +183 -0
  74. package/docs/translation.md +247 -0
  75. package/docs/tutorial.md +271 -0
  76. package/docs/typescript.md +374 -0
  77. package/docs/web-element.md +251 -0
  78. package/docs/webdriver.md +708 -0
  79. package/docs/within.md +55 -0
  80. package/lib/ai.js +3 -2
  81. package/lib/aria.js +260 -0
  82. package/lib/assertions.js +18 -0
  83. package/lib/codecept.js +27 -24
  84. package/lib/command/check.js +2 -1
  85. package/lib/command/dryRun.js +24 -5
  86. package/lib/command/generate.js +2 -0
  87. package/lib/command/gherkin/snippets.js +5 -4
  88. package/lib/command/init.js +248 -269
  89. package/lib/command/list.js +150 -10
  90. package/lib/command/query.js +218 -0
  91. package/lib/command/run-multiple.js +2 -0
  92. package/lib/command/run-workers.js +2 -14
  93. package/lib/command/run.js +3 -17
  94. package/lib/command/utils.js +14 -0
  95. package/lib/command/workers/runTests.js +10 -10
  96. package/lib/config.js +77 -4
  97. package/lib/container.js +114 -17
  98. package/lib/effects.js +17 -0
  99. package/lib/element/WebElement.js +246 -2
  100. package/lib/els.js +12 -6
  101. package/lib/globals.js +32 -19
  102. package/lib/heal.js +6 -3
  103. package/lib/helper/ApiDataFactory.js +2 -1
  104. package/lib/helper/Appium.js +8 -8
  105. package/lib/helper/FileSystem.js +3 -2
  106. package/lib/helper/GraphQLDataFactory.js +2 -1
  107. package/lib/helper/Playwright.js +233 -162
  108. package/lib/helper/Puppeteer.js +208 -76
  109. package/lib/helper/WebDriver.js +173 -68
  110. package/lib/helper/errors/MultipleElementsFound.js +27 -110
  111. package/lib/helper/errors/NonFocusedType.js +8 -0
  112. package/lib/helper/extras/Download.js +45 -0
  113. package/lib/helper/extras/PlaywrightReactVueLocator.js +45 -36
  114. package/lib/helper/extras/elementSelection.js +58 -0
  115. package/lib/helper/extras/focusCheck.js +43 -0
  116. package/lib/helper/extras/richTextEditor.js +178 -0
  117. package/lib/helper/scripts/dropFile.js +11 -0
  118. package/lib/history.js +3 -2
  119. package/lib/html.js +103 -16
  120. package/lib/index.js +9 -1
  121. package/lib/listener/config.js +6 -4
  122. package/lib/listener/emptyRun.js +2 -1
  123. package/lib/listener/globalRetry.js +32 -6
  124. package/lib/listener/helpers.js +4 -1
  125. package/lib/listener/mocha.js +2 -1
  126. package/lib/listener/pageobjects.js +43 -0
  127. package/lib/listener/result.js +3 -2
  128. package/lib/locator.js +126 -3
  129. package/lib/mocha/cli.js +14 -2
  130. package/lib/mocha/factory.js +7 -2
  131. package/lib/mocha/inject.js +1 -1
  132. package/lib/mocha/scenarioConfig.js +2 -1
  133. package/lib/mocha/ui.js +5 -6
  134. package/lib/parser.js +2 -2
  135. package/lib/pause.js +38 -4
  136. package/lib/plugin/aiTrace.js +456 -0
  137. package/lib/plugin/analyze.js +6 -5
  138. package/lib/plugin/auth.js +3 -3
  139. package/lib/plugin/browser.js +77 -0
  140. package/lib/plugin/expose.js +159 -0
  141. package/lib/plugin/heal.js +47 -3
  142. package/lib/plugin/pageInfo.js +54 -52
  143. package/lib/plugin/pause.js +131 -0
  144. package/lib/plugin/pauseOnFail.js +10 -34
  145. package/lib/plugin/retryFailedStep.js +32 -22
  146. package/lib/plugin/screencast.js +289 -0
  147. package/lib/plugin/screenshot.js +563 -0
  148. package/lib/plugin/screenshotOnFail.js +8 -171
  149. package/lib/rerun.js +2 -1
  150. package/lib/result.js +2 -1
  151. package/lib/step/base.js +3 -2
  152. package/lib/step/config.js +15 -2
  153. package/lib/step/record.js +2 -2
  154. package/lib/store.js +72 -3
  155. package/lib/translation.js +2 -1
  156. package/lib/utils/mask_data.js +2 -1
  157. package/lib/utils/pluginParser.js +151 -0
  158. package/lib/utils/trace.js +297 -0
  159. package/lib/utils.js +77 -3
  160. package/lib/workers.js +63 -25
  161. package/package.json +19 -13
  162. package/typings/index.d.ts +19 -5
  163. package/docs/webapi/amOnPage.mustache +0 -11
  164. package/docs/webapi/appendField.mustache +0 -11
  165. package/docs/webapi/attachFile.mustache +0 -12
  166. package/docs/webapi/blur.mustache +0 -18
  167. package/docs/webapi/checkOption.mustache +0 -13
  168. package/docs/webapi/clearCookie.mustache +0 -9
  169. package/docs/webapi/clearField.mustache +0 -9
  170. package/docs/webapi/click.mustache +0 -29
  171. package/docs/webapi/clickLink.mustache +0 -8
  172. package/docs/webapi/closeCurrentTab.mustache +0 -7
  173. package/docs/webapi/closeOtherTabs.mustache +0 -8
  174. package/docs/webapi/dontSee.mustache +0 -11
  175. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  176. package/docs/webapi/dontSeeCookie.mustache +0 -8
  177. package/docs/webapi/dontSeeCurrentPathEquals.mustache +0 -10
  178. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  179. package/docs/webapi/dontSeeElement.mustache +0 -8
  180. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  181. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  182. package/docs/webapi/dontSeeInField.mustache +0 -11
  183. package/docs/webapi/dontSeeInSource.mustache +0 -8
  184. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  185. package/docs/webapi/dontSeeTraffic.mustache +0 -13
  186. package/docs/webapi/doubleClick.mustache +0 -13
  187. package/docs/webapi/downloadFile.mustache +0 -12
  188. package/docs/webapi/dragAndDrop.mustache +0 -9
  189. package/docs/webapi/dragSlider.mustache +0 -11
  190. package/docs/webapi/executeAsyncScript.mustache +0 -24
  191. package/docs/webapi/executeScript.mustache +0 -26
  192. package/docs/webapi/fillField.mustache +0 -16
  193. package/docs/webapi/flushNetworkTraffics.mustache +0 -5
  194. package/docs/webapi/focus.mustache +0 -13
  195. package/docs/webapi/forceClick.mustache +0 -28
  196. package/docs/webapi/forceRightClick.mustache +0 -18
  197. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  198. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  199. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  200. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  201. package/docs/webapi/grabCookie.mustache +0 -11
  202. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  203. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  204. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  205. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  206. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  207. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  208. package/docs/webapi/grabGeoLocation.mustache +0 -8
  209. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  210. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  211. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  212. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  213. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  214. package/docs/webapi/grabPopupText.mustache +0 -5
  215. package/docs/webapi/grabRecordedNetworkTraffics.mustache +0 -10
  216. package/docs/webapi/grabSource.mustache +0 -8
  217. package/docs/webapi/grabTextFrom.mustache +0 -10
  218. package/docs/webapi/grabTextFromAll.mustache +0 -9
  219. package/docs/webapi/grabTitle.mustache +0 -8
  220. package/docs/webapi/grabValueFrom.mustache +0 -9
  221. package/docs/webapi/grabValueFromAll.mustache +0 -8
  222. package/docs/webapi/grabWebElement.mustache +0 -9
  223. package/docs/webapi/grabWebElements.mustache +0 -9
  224. package/docs/webapi/moveCursorTo.mustache +0 -12
  225. package/docs/webapi/openNewTab.mustache +0 -7
  226. package/docs/webapi/pressKey.mustache +0 -12
  227. package/docs/webapi/pressKeyDown.mustache +0 -12
  228. package/docs/webapi/pressKeyUp.mustache +0 -12
  229. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  230. package/docs/webapi/refreshPage.mustache +0 -6
  231. package/docs/webapi/resizeWindow.mustache +0 -6
  232. package/docs/webapi/rightClick.mustache +0 -14
  233. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  234. package/docs/webapi/saveScreenshot.mustache +0 -12
  235. package/docs/webapi/say.mustache +0 -10
  236. package/docs/webapi/scrollIntoView.mustache +0 -11
  237. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  238. package/docs/webapi/scrollPageToTop.mustache +0 -6
  239. package/docs/webapi/scrollTo.mustache +0 -12
  240. package/docs/webapi/see.mustache +0 -11
  241. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  242. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  243. package/docs/webapi/seeCookie.mustache +0 -8
  244. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  245. package/docs/webapi/seeCurrentPathEquals.mustache +0 -10
  246. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  247. package/docs/webapi/seeElement.mustache +0 -8
  248. package/docs/webapi/seeElementInDOM.mustache +0 -8
  249. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  250. package/docs/webapi/seeInField.mustache +0 -12
  251. package/docs/webapi/seeInPopup.mustache +0 -8
  252. package/docs/webapi/seeInSource.mustache +0 -7
  253. package/docs/webapi/seeInTitle.mustache +0 -8
  254. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  255. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  256. package/docs/webapi/seeTextEquals.mustache +0 -9
  257. package/docs/webapi/seeTitleEquals.mustache +0 -8
  258. package/docs/webapi/seeTraffic.mustache +0 -36
  259. package/docs/webapi/selectOption.mustache +0 -21
  260. package/docs/webapi/setCookie.mustache +0 -16
  261. package/docs/webapi/setGeoLocation.mustache +0 -12
  262. package/docs/webapi/startRecordingTraffic.mustache +0 -8
  263. package/docs/webapi/startRecordingWebSocketMessages.mustache +0 -8
  264. package/docs/webapi/stopRecordingTraffic.mustache +0 -5
  265. package/docs/webapi/stopRecordingWebSocketMessages.mustache +0 -7
  266. package/docs/webapi/switchTo.mustache +0 -9
  267. package/docs/webapi/switchToNextTab.mustache +0 -10
  268. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  269. package/docs/webapi/type.mustache +0 -21
  270. package/docs/webapi/uncheckOption.mustache +0 -13
  271. package/docs/webapi/wait.mustache +0 -8
  272. package/docs/webapi/waitForClickable.mustache +0 -11
  273. package/docs/webapi/waitForCookie.mustache +0 -9
  274. package/docs/webapi/waitForDetached.mustache +0 -10
  275. package/docs/webapi/waitForDisabled.mustache +0 -6
  276. package/docs/webapi/waitForElement.mustache +0 -11
  277. package/docs/webapi/waitForEnabled.mustache +0 -6
  278. package/docs/webapi/waitForFunction.mustache +0 -17
  279. package/docs/webapi/waitForInvisible.mustache +0 -10
  280. package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
  281. package/docs/webapi/waitForText.mustache +0 -13
  282. package/docs/webapi/waitForValue.mustache +0 -10
  283. package/docs/webapi/waitForVisible.mustache +0 -10
  284. package/docs/webapi/waitInUrl.mustache +0 -9
  285. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  286. package/docs/webapi/waitToHide.mustache +0 -10
  287. package/docs/webapi/waitUrlEquals.mustache +0 -10
  288. package/lib/helper/AI.js +0 -214
  289. package/lib/listener/enhancedGlobalRetry.js +0 -110
  290. package/lib/plugin/enhancedRetryFailedStep.js +0 -99
  291. package/lib/plugin/htmlReporter.js +0 -3648
  292. package/lib/plugin/stepByStepReport.js +0 -427
  293. package/lib/plugin/subtitles.js +0 -89
  294. package/lib/retryCoordinator.js +0 -207
  295. package/typings/promiseBasedTypes.d.ts +0 -9469
  296. package/typings/types.d.ts +0 -11402
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,110 +0,0 @@
1
- import event from '../event.js'
2
- import output from '../output.js'
3
- import Config from '../config.js'
4
- import { isNotSet } from '../utils.js'
5
-
6
- const hooks = ['Before', 'After', 'BeforeSuite', 'AfterSuite']
7
-
8
- /**
9
- * Priority levels for retry mechanisms (higher number = higher priority)
10
- * This ensures consistent behavior when multiple retry mechanisms are active
11
- */
12
- const RETRY_PRIORITIES = {
13
- MANUAL_STEP: 100, // I.retry() or step.retry() - highest priority
14
- STEP_PLUGIN: 50, // retryFailedStep plugin
15
- SCENARIO_CONFIG: 30, // Global scenario retry config
16
- FEATURE_CONFIG: 20, // Global feature retry config
17
- HOOK_CONFIG: 10, // Hook retry config - lowest priority
18
- }
19
-
20
- /**
21
- * Enhanced global retry mechanism that coordinates with other retry types
22
- */
23
- export default function () {
24
- event.dispatcher.on(event.suite.before, suite => {
25
- let retryConfig = Config.get('retry')
26
- if (!retryConfig) return
27
-
28
- if (Number.isInteger(+retryConfig)) {
29
- // is number - apply as feature-level retry
30
- const retryNum = +retryConfig
31
- output.log(`[Global Retry] Feature retries: ${retryNum}`)
32
-
33
- // Only set if not already set by higher priority mechanism
34
- if (isNotSet(suite.retries())) {
35
- suite.retries(retryNum)
36
- suite.opts.retryPriority = RETRY_PRIORITIES.FEATURE_CONFIG
37
- }
38
- return
39
- }
40
-
41
- if (!Array.isArray(retryConfig)) {
42
- retryConfig = [retryConfig]
43
- }
44
-
45
- for (const config of retryConfig) {
46
- if (config.grep) {
47
- if (!suite.title.includes(config.grep)) continue
48
- }
49
-
50
- // Handle hook retries with priority awareness
51
- hooks
52
- .filter(hook => !!config[hook])
53
- .forEach(hook => {
54
- const retryKey = `retry${hook}`
55
- if (isNotSet(suite.opts[retryKey])) {
56
- suite.opts[retryKey] = config[hook]
57
- suite.opts[`${retryKey}Priority`] = RETRY_PRIORITIES.HOOK_CONFIG
58
- }
59
- })
60
-
61
- // Handle feature-level retries
62
- if (config.Feature) {
63
- if (isNotSet(suite.retries()) || (suite.opts.retryPriority || 0) <= RETRY_PRIORITIES.FEATURE_CONFIG) {
64
- suite.retries(config.Feature)
65
- suite.opts.retryPriority = RETRY_PRIORITIES.FEATURE_CONFIG
66
- output.log(`[Global Retry] Feature retries: ${config.Feature}`)
67
- }
68
- }
69
- }
70
- })
71
-
72
- event.dispatcher.on(event.test.before, test => {
73
- let retryConfig = Config.get('retry')
74
- if (!retryConfig) return
75
-
76
- if (Number.isInteger(+retryConfig)) {
77
- // Only set if not already set by higher priority mechanism
78
- if (test.retries() === -1) {
79
- test.retries(retryConfig)
80
- test.opts.retryPriority = RETRY_PRIORITIES.SCENARIO_CONFIG
81
- output.log(`[Global Retry] Scenario retries: ${retryConfig}`)
82
- }
83
- return
84
- }
85
-
86
- if (!Array.isArray(retryConfig)) {
87
- retryConfig = [retryConfig]
88
- }
89
-
90
- retryConfig = retryConfig.filter(config => !!config.Scenario)
91
-
92
- for (const config of retryConfig) {
93
- if (config.grep) {
94
- if (!test.fullTitle().includes(config.grep)) continue
95
- }
96
-
97
- if (config.Scenario) {
98
- // Respect priority system
99
- if (test.retries() === -1 || (test.opts.retryPriority || 0) <= RETRY_PRIORITIES.SCENARIO_CONFIG) {
100
- test.retries(config.Scenario)
101
- test.opts.retryPriority = RETRY_PRIORITIES.SCENARIO_CONFIG
102
- output.log(`[Global Retry] Scenario retries: ${config.Scenario}`)
103
- }
104
- }
105
- }
106
- })
107
- }
108
-
109
- // Export priority constants for use by other retry mechanisms
110
- export { RETRY_PRIORITIES }
@@ -1,99 +0,0 @@
1
- import event from '../event.js'
2
- import recorder from '../recorder.js'
3
- import store from '../store.js'
4
- import output from '../output.js'
5
- import { RETRY_PRIORITIES } from '../retryCoordinator.js'
6
-
7
- const defaultConfig = {
8
- retries: 3,
9
- defaultIgnoredSteps: ['amOnPage', 'wait*', 'send*', 'execute*', 'run*', 'have*'],
10
- factor: 1.5,
11
- ignoredSteps: [],
12
- }
13
-
14
- /**
15
- * Enhanced retryFailedStep plugin that coordinates with other retry mechanisms
16
- *
17
- * This plugin provides step-level retries and coordinates with global retry settings
18
- * to avoid conflicts and provide predictable behavior.
19
- */
20
- export default config => {
21
- config = Object.assign({}, defaultConfig, config)
22
- config.ignoredSteps = config.ignoredSteps.concat(config.defaultIgnoredSteps)
23
- const customWhen = config.when
24
-
25
- let enableRetry = false
26
-
27
- const when = err => {
28
- if (!enableRetry) return false
29
- if (store.debugMode) return false
30
- if (!store.autoRetries) return false
31
- if (customWhen) return customWhen(err)
32
- return true
33
- }
34
- config.when = when
35
-
36
- event.dispatcher.on(event.step.started, step => {
37
- // if a step is ignored - return
38
- for (const ignored of config.ignoredSteps) {
39
- if (step.name === ignored) return
40
- if (ignored instanceof RegExp) {
41
- if (step.name.match(ignored)) return
42
- } else if (ignored.indexOf('*') && step.name.startsWith(ignored.slice(0, -1))) return
43
- }
44
- enableRetry = true // enable retry for a step
45
- })
46
-
47
- event.dispatcher.on(event.step.finished, () => {
48
- enableRetry = false
49
- })
50
-
51
- event.dispatcher.on(event.test.before, test => {
52
- // pass disableRetryFailedStep is a preferred way to disable retries
53
- // test.disableRetryFailedStep is used for backward compatibility
54
- if (test.opts.disableRetryFailedStep || test.disableRetryFailedStep) {
55
- store.autoRetries = false
56
- output.log(`[Step Retry] Disabled for test: ${test.title}`)
57
- return // disable retry when a test is not active
58
- }
59
-
60
- // Check if step retries should be disabled due to higher priority scenario retries
61
- const scenarioRetries = test.retries()
62
- const stepRetryPriority = RETRY_PRIORITIES.STEP_PLUGIN
63
- const scenarioPriority = test.opts.retryPriority || 0
64
-
65
- if (scenarioRetries > 0 && config.deferToScenarioRetries !== false) {
66
- // Scenario retries are configured with higher or equal priority
67
- // Option 1: Disable step retries (conservative approach)
68
- store.autoRetries = false
69
- output.log(`[Step Retry] Deferred to scenario retries (${scenarioRetries} retries)`)
70
- return
71
-
72
- // Option 2: Reduce step retries to avoid excessive total retries
73
- // const reducedStepRetries = Math.max(1, Math.floor(config.retries / scenarioRetries))
74
- // config.retries = reducedStepRetries
75
- // output.log(`[Step Retry] Reduced to ${reducedStepRetries} retries due to scenario retries (${scenarioRetries})`)
76
- }
77
-
78
- // this option is used to set the retries inside _before() block of helpers
79
- store.autoRetries = true
80
- test.opts.conditionalRetries = config.retries
81
- test.opts.stepRetryPriority = stepRetryPriority
82
-
83
- recorder.retry(config)
84
-
85
- output.log(`[Step Retry] Enabled with ${config.retries} retries for test: ${test.title}`)
86
- })
87
-
88
- // Add coordination info for debugging
89
- event.dispatcher.on(event.test.finished, test => {
90
- if (test.state === 'passed' && test.opts.conditionalRetries && store.autoRetries) {
91
- const stepRetries = test.opts.conditionalRetries || 0
92
- const scenarioRetries = test.retries() || 0
93
-
94
- if (stepRetries > 0 && scenarioRetries > 0) {
95
- output.log(`[Retry Coordination] Test used both step retries (${stepRetries}) and scenario retries (${scenarioRetries})`)
96
- }
97
- }
98
- })
99
- }