Skip to content

Commit e300b8d

Browse files
author
DavertMik
committed
Merge branch '4.x' into feat/mcp-capture-snapshot
Brings in the unified `on=` trigger framework (pluginParser.js), new screenshot/browser/pause plugins, and 4.x docs. Resolves aiTrace.js by combining the trace.js helpers (captureSnapshot, pickActingHelper, traceDirFor, artifactLinks) with 4.x's parsePluginArgs/ resolveTrigger entrypoint.
2 parents 754d3ea + 87a25ad commit e300b8d

79 files changed

Lines changed: 3414 additions & 1883 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,17 @@ Applicable helpers:
1313

1414
Applicable plugins:
1515

16-
- [ ] allure
16+
- [ ] aiTrace
1717
- [ ] autoDelay
1818
- [ ] autoLogin
1919
- [ ] customLocator
20-
- [ ] pauseOnFail
20+
- [ ] pause
2121
- [ ] coverage
22+
- [ ] heal
2223
- [ ] retryFailedStep
23-
- [ ] screenshotOnFail
24+
- [ ] screenshot
2425
- [ ] selenoid
25-
- [ ] stepByStepReport
2626
- [ ] stepTimeout
27-
- [ ] wdio
2827
- [ ] subtitles
2928

3029
## Type of change

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ yarn.lock
2727
/.vs
2828
typings/types.d.ts
2929
typings/promiseBasedTypes.d.ts
30-
reflection/
30+
reflection/
31+
skills/

.mocharc.cjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const path = require('path')
2+
3+
module.exports = {
4+
require: [path.join(__dirname, 'test', 'support', 'setup.mjs')],
5+
extension: ['js', 'mjs'],
6+
}

.mocharc.mjs

Lines changed: 0 additions & 10 deletions
This file was deleted.

bin/codecept.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,14 @@ program
9393
.option(commandFlags.config.flag, commandFlags.config.description)
9494
.action(commandHandler('../lib/command/interactive.js'))
9595

96-
program.command('list [path]').alias('l').description('List all actions for I.').action(commandHandler('../lib/command/list.js'))
96+
program
97+
.command('list [path]')
98+
.alias('l')
99+
.description('List all actions for I.')
100+
.option(commandFlags.config.flag, commandFlags.config.description)
101+
.option('--docs', 'show documentation for each action')
102+
.option('--action <name>', 'show docs for a single action (e.g. amOnPage or I.amOnPage)')
103+
.action(commandHandler('../lib/command/list.js'))
97104

98105
program
99106
.command('def [path]')

docs/ai.md

Lines changed: 8 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ So, instead of asking "write me a test" it can ask "write a test for **this** pa
2222
CodeceptJS AI can do the following:
2323

2424
- 🏋️‍♀️ **assist writing tests** in `pause()` or interactive shell mode
25-
- 📃 **generate page objects** in `pause()` or interactive shell mode
2625
- 🚑 **self-heal failing tests** (can be used on CI)
27-
- 💬 send arbitrary prompts to AI provider from any tested page attaching its HTML contents
2826

2927
![](/img/fill_form.gif)
3028

@@ -60,7 +58,7 @@ import { openai } from '@ai-sdk/openai'
6058
export default {
6159
// ... other config
6260
ai: {
63-
model: openai('gpt-4o-mini'),
61+
model: openai('gpt-5'),
6462
},
6563
}
6664
```
@@ -94,7 +92,7 @@ import { openai } from '@ai-sdk/openai'
9492

9593
export default {
9694
ai: {
97-
model: openai('gpt-4o-mini'),
95+
model: openai('gpt-5'),
9896
// or use gpt-4o, gpt-3.5-turbo, etc.
9997
},
10098
}
@@ -121,8 +119,8 @@ import { anthropic } from '@ai-sdk/anthropic'
121119

122120
export default {
123121
ai: {
124-
model: anthropic('claude-3-5-sonnet-20241022'),
125-
// or use claude-3-opus-20240229, claude-3-haiku-20240307, etc.
122+
model: anthropic('claude-sonnet-4-6'),
123+
// or use claude-opus-4-7, claude-haiku-4-5, etc.
126124
},
127125
}
128126
```
@@ -232,10 +230,9 @@ npx codeceptjs generate:heal
232230
Heal recipes should be included into `codecept.conf.js` or `codecept.conf.ts` config file:
233231

234232
```js
233+
import './heal.js'
235234

236-
require('./heal')
237-
238-
exports.config = {
235+
export const config = {
239236
// ... your codeceptjs config
240237
```
241238
@@ -385,125 +382,6 @@ Run tests with both AI and analyze enabled:
385382
npx codeceptjs run --ai
386383
```
387384
388-
## Arbitrary Prompts
389-
390-
What if you want to take AI on the journey of test automation and ask it questions while browsing pages?
391-
392-
This is possible with the new `AI` helper. Enable it in your config file in `helpers` section:
393-
394-
```js
395-
// inside codecept.conf
396-
helpers: {
397-
// Playwright, Puppeteer, or WebDrver helper should be enabled too
398-
Playwright: {
399-
},
400-
401-
AI: {}
402-
}
403-
```
404-
405-
AI helper will be automatically attached to Playwright, WebDriver, or another web helper you use. It includes the following methods:
406-
407-
- `askGptOnPage` - sends GPT prompt attaching the HTML of the page. Large pages will be split into chunks, according to `chunkSize` config. You will receive responses for all chunks.
408-
- `askGptOnPageFragment` - sends GPT prompt attaching the HTML of the specific element. This method is recommended over `askGptOnPage` as you can reduce the amount of data to be processed.
409-
- `askGptGeneralPrompt` - sends GPT prompt without HTML.
410-
- `askForPageObject` - creates PageObject for you, explained in next section.
411-
412-
`askGpt` methods won't remove non-interactive elements, so it is recommended to manually control the size of the sent HTML.
413-
414-
Here are some good use cases for this helper:
415-
416-
- get page summaries
417-
- inside pause mode navigate through your application and ask to document pages
418-
- etc...
419-
420-
```js
421-
// use it inside test or inside interactive pause
422-
// pretend you are technical writer asking for documentation
423-
const pageDoc = await I.askGptOnPageFragment('Act as technical writer, describe what is this page for', '#container')
424-
```
425-
426-
As of now, those use cases do not apply to test automation but maybe you can apply them to your testing setup.
427-
428-
## Generate PageObjects
429-
430-
Last but not the least. AI helper can be used to quickly prototype PageObjects on pages browsed within interactive session.
431-
432-
![](/img/ai_page_object.png)
433-
434-
Enable AI helper as explained in previous section and launch shell:
435-
436-
```
437-
npx codeceptjs shell --ai
438-
```
439-
440-
Also this is availble from `pause()` if AI helper is enabled,
441-
442-
Ensure that browser is started in window mode, then browse the web pages on your site.
443-
On a page you want to create PageObject execute `askForPageObject()` command. The only required parameter is the name of a page:
444-
445-
```js
446-
I.askForPageObject('login')
447-
```
448-
449-
This command sends request to AI provider should create valid CodeceptJS PageObject.
450-
Run it few times or switch AI provider if response is not satisfactory to you.
451-
452-
> You can change the style of PageObject and locator preferences by adjusting prompt in a config file
453-
454-
When completed successfully, page object is saved to **output** directory and loaded into the shell as `page` variable so locators and methods can be checked on the fly.
455-
456-
If page object has `signInButton` locator you can quickly check it by typing:
457-
458-
```js
459-
I.click(page.signInButton)
460-
```
461-
462-
If page object has `clickForgotPassword` method you can execute it as:
463-
464-
```js
465-
=> page.clickForgotPassword()
466-
```
467-
468-
Here is an example of a session:
469-
470-
```shell
471-
Page object for login is saved to .../output/loginPage-1718579784751.js
472-
Page object registered for this session as `page` variable
473-
Use `=>page.methodName()` in shell to run methods of page object
474-
Use `click(page.locatorName)` to check locators of page object
475-
476-
I.=>page.clickSignUp()
477-
I.click(page.signUpLink)
478-
I.=> page.enterPassword('asdasd')
479-
I.=> page.clickSignIn()
480-
```
481-
482-
You can improve prompt by passing custom request as a second parameter:
483-
484-
```js
485-
I.askForPageObject('login', 'implement signIn(username, password) method')
486-
```
487-
488-
To generate page object for the part of a page, pass in root locator as third parameter.
489-
490-
```js
491-
I.askForPageObject('login', '', '#auth')
492-
```
493-
494-
In this case, all generated locators, will use `#auth` as their root element.
495-
496-
Don't aim for perfect PageObjects but find a good enough one, which you can use for writing your tests.
497-
All created page objects are considered temporary, that's why saved to `output` directory.
498-
499-
Rename created PageObject to remove timestamp and move it from `output` to `pages` folder and include it into codecept.conf file:
500-
501-
```js
502-
include: {
503-
loginPage: "./pages/loginPage.js",
504-
// ...
505-
```
506-
507385
## Advanced Configuration
508386
509387
AI prompts and HTML compression can be configured inside `ai` section of `codecept.conf` file:
@@ -612,8 +490,8 @@ It is recommended to try HTML processing on one of your web pages before launchi
612490
To do that open the common page of your application and using DevTools copy the outerHTML of `<html>` element. Don't use `Page Source` for that, as it may not include dynamically added HTML elements. Save this HTML into a file and create a NodeJS script:
613491
614492
```js
615-
const { removeNonInteractiveElements } = require('codeceptjs/lib/html')
616-
const fs = require('fs')
493+
import { removeNonInteractiveElements } from 'codeceptjs/lib/html'
494+
import fs from 'fs'
617495

618496
const htmlOpts = {
619497
interactiveElements: ['a', 'input', 'button', 'select', 'textarea', 'label', 'option'],

docs/api.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,12 @@ Or you can use the browser cookies if you are running browser session.
119119
In this case use `setSharedCookies()` from `@codeceptjs/configure` package:
120120

121121
```js
122-
const { setSharedCookies } = require('@codeceptjs/configure');
122+
import { setSharedCookies } from '@codeceptjs/configure'
123123

124-
// add this before exports.config
125-
setSharedCookies();
124+
// call before exporting config
125+
setSharedCookies()
126126

127-
exports.config = {
127+
export const config = {
128128
// ...
129129
helpers: {
130130
// also works with Playwright or Puppeteer

0 commit comments

Comments
 (0)