codeceptjs 4.2.0 β 4.2.1-beta.1
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.
- package/README.md +2 -0
- package/bin/codecept.js +11 -0
- package/docs/agents.md +26 -1
- package/docs/ai.md +57 -0
- package/docs/alternative-browsers.md +175 -148
- package/docs/assertions.md +74 -0
- package/docs/bootstrap.md +2 -0
- package/docs/commands.md +45 -0
- package/docs/configuration.md +37 -0
- package/docs/debugging.md +1 -1
- package/docs/helpers/ApiDataFactory.md +20 -20
- package/docs/helpers/Appium.md +1615 -670
- package/docs/helpers/Decision.md +146 -0
- package/docs/helpers/GraphQL.md +31 -31
- package/docs/helpers/GraphQLDataFactory.md +20 -20
- package/docs/helpers/Kitesurf.md +1808 -25
- package/docs/helpers/Lightpanda.md +139 -0
- package/docs/helpers/Obscura.md +1799 -74
- package/docs/helpers/Playwright.md +490 -428
- package/docs/helpers/Puppeteer.md +317 -255
- package/docs/helpers/REST.md +43 -43
- package/docs/helpers/WebDriver.md +237 -175
- package/docs/installation.md +16 -0
- package/docs/mcp.md +7 -1
- package/docs/parallel.md +35 -1
- package/docs/plugins/pause.md +2 -1
- package/docs/plugins/sitemap.md +48 -0
- package/docs/plugins.md +4 -0
- package/lib/ai.js +81 -2
- package/lib/codecept.js +32 -2
- package/lib/command/init.js +22 -0
- package/lib/command/initAgent.js +78 -0
- package/lib/command/run-multiple.js +3 -0
- package/lib/command/run-workers.js +10 -3
- package/lib/command/run.js +3 -2
- package/lib/command/utils.js +15 -0
- package/lib/command/workers/runTests.js +10 -10
- package/lib/container.js +4 -2
- package/lib/effects.js +19 -1
- package/lib/helper/CDPBrowser.js +349 -1384
- package/lib/helper/Decision.js +256 -0
- package/lib/helper/Kitesurf.js +3 -21
- package/lib/helper/Lightpanda.js +137 -0
- package/lib/helper/Obscura.js +21 -238
- package/lib/helper/Playwright.js +6 -4
- package/lib/helper/Puppeteer.js +12 -7
- package/lib/helper/WebDriver.js +2 -1
- package/lib/listener/result.js +4 -0
- package/lib/mocha/bdd.js +19 -1
- package/lib/plugin/junitReporter.js +4 -1
- package/lib/plugin/pause.js +4 -1
- package/lib/plugin/sitemap.js +228 -0
- package/lib/recorder.js +19 -18
- package/lib/result.js +16 -0
- package/lib/step/base.js +12 -0
- package/lib/utils.js +2 -10
- package/lib/webServer.js +193 -0
- package/lib/workers.js +118 -31
- package/package.json +4 -2
- package/typings/index.d.ts +60 -7
- package/typings/promiseBasedTypes.d.ts +772 -824
- package/typings/types.d.ts +866 -833
- package/docs/helpers/CDPBrowser.md +0 -2138
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
| π Web | Puppeteer | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/puppeteer.yml) |
|
|
12
12
|
| π Web | WebDriver | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/webdriver.yml) |
|
|
13
13
|
| π Web | Obscura | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/obscura.yml) |
|
|
14
|
+
| π Web | Lightpanda | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/lightpanda.yml) |
|
|
14
15
|
| π± Mobile | Appium | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appium_Android.yml) |
|
|
15
16
|
|
|
16
17
|
# CodeceptJS [](https://stand-with-ukraine.pp.ua)
|
|
@@ -44,6 +45,7 @@ CodeceptJS uses **Helper** modules to provide actions to `I` object. Currently,
|
|
|
44
45
|
- [**Puppeteer**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Puppeteer.md) - uses Google Chrome's Puppeteer for fast headless testing.
|
|
45
46
|
- [**WebDriver**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/WebDriver.md) - uses [webdriverio](http://webdriver.io/) to run tests via WebDriver or Devtools protocol.
|
|
46
47
|
- [**Obscura**](https://codecept.io/helpers/Obscura) - drives the lightweight Obscura browser through Chrome DevTools Protocol. See [Alternative Browser Engines](https://codecept.io/alternative-browsers).
|
|
48
|
+
- [**Lightpanda**](https://codecept.io/helpers/Lightpanda) - drives the Lightpanda headless browser through Chrome DevTools Protocol. See [Alternative Browser Engines](https://codecept.io/alternative-browsers).
|
|
47
49
|
- [**Appium**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Appium.md) - for **mobile testing** with Appium
|
|
48
50
|
- [**Detox**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Detox.md) - This is a wrapper on top of Detox library, aimed to unify testing experience for CodeceptJS framework. Detox provides a grey box testing for mobile applications, playing especially well for React Native apps.
|
|
49
51
|
|
package/bin/codecept.js
CHANGED
|
@@ -78,8 +78,16 @@ program
|
|
|
78
78
|
.command('init [path]')
|
|
79
79
|
.description('Creates dummy config in current dir or [path]')
|
|
80
80
|
.option('-y, --yes', 'skip prompts and use defaults (Playwright + chromium, BASE_URL env for url)')
|
|
81
|
+
.option('--agent <name>', 'set up an AI coding agent: claude, codex, cursor, opencode')
|
|
81
82
|
.action(commandHandler('../lib/command/init.js'))
|
|
82
83
|
|
|
84
|
+
program
|
|
85
|
+
.command('init:agent [agent]')
|
|
86
|
+
.alias('init-agent')
|
|
87
|
+
.description('Set up CodeceptJS MCP server and skills for a coding agent: claude, codex, cursor, opencode')
|
|
88
|
+
.option('-y, --yes', 'skip prompts, requires [agent]')
|
|
89
|
+
.action(commandHandler('../lib/command/initAgent.js'))
|
|
90
|
+
|
|
83
91
|
program
|
|
84
92
|
.command('check')
|
|
85
93
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
@@ -178,6 +186,7 @@ program
|
|
|
178
186
|
.option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
|
|
179
187
|
.option('--shuffle', 'Shuffle the order in which test files run')
|
|
180
188
|
.option('--shard <index/total>', 'run only a fraction of tests (e.g., --shard 1/4)')
|
|
189
|
+
.option('--last-failed', 'run only tests that failed in the previous run')
|
|
181
190
|
|
|
182
191
|
// mocha options
|
|
183
192
|
.option('--colors', 'force enabling of colors')
|
|
@@ -207,8 +216,10 @@ program
|
|
|
207
216
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
208
217
|
.option('-g, --grep <pattern>', 'only run tests matching <pattern>')
|
|
209
218
|
.option('-i, --invert', 'inverts --grep matches')
|
|
219
|
+
.option('--last-failed', 'run only tests that failed in the previous run')
|
|
210
220
|
.option('-o, --override [value]', 'override current config options')
|
|
211
221
|
.option('--suites', 'parallel execution of suites not single tests')
|
|
222
|
+
.option('--serial <pattern>', 'run tests matching <pattern> one by one after parallel workers finish')
|
|
212
223
|
.option('--by <strategy>', 'test distribution strategy: "test" (pre-assign individual tests), "suite" (pre-assign test suites), or "pool" (dynamic distribution for optimal load balancing, recommended)')
|
|
213
224
|
.option(commandFlags.debug.flag, commandFlags.debug.description)
|
|
214
225
|
.option(commandFlags.verbose.flag, commandFlags.verbose.description)
|
package/docs/agents.md
CHANGED
|
@@ -25,7 +25,15 @@ CodeceptJS is token-efficient: it stores HTML, ARIA, logs, and HTTP request data
|
|
|
25
25
|
|
|
26
26
|
## Essential Setup
|
|
27
27
|
|
|
28
|
-
Two things make agent testing work: the **skills** that teach the agent CodeceptJS, and the **MCP server** that lets it drive the browser. Set both up once, from your project directory
|
|
28
|
+
Two things make agent testing work: the **skills** that teach the agent CodeceptJS, and the **MCP server** that lets it drive the browser. Set both up once, from your project directory:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx codeceptjs init:agent claude
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use `codex`, `cursor`, or `opencode` instead of `claude` for other agents, or omit the name to pick from a list. `npx codeceptjs init` offers the same step at the end.
|
|
35
|
+
|
|
36
|
+
### Manual setup
|
|
29
37
|
|
|
30
38
|
Install the skills:
|
|
31
39
|
|
|
@@ -165,6 +173,23 @@ After a failed run, the agent reads every trace under `output/`, clusters failur
|
|
|
165
173
|
|
|
166
174
|
If the fix held, the PR goes green. If it didn't, every edit is rolled back with `git checkout` and the report says which patterns the agent couldn't safely handle. No half-applied fixes left behind, no `retries: 3` masking the problem.
|
|
167
175
|
|
|
176
|
+
## Assertions in plain language
|
|
177
|
+
|
|
178
|
+
Some outcomes are hard to pin to a locator: "checkout form has all required fields", "success message is shown". Instead of building a fragile chain of `see*` checks, the agent can write the expected outcome as a statement with the [Decision helper](/assertions#decision-assertions):
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
I.decide([
|
|
182
|
+
'order summary lists the purchased items',
|
|
183
|
+
'success message is shown',
|
|
184
|
+
])
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The agent runs the statement on the live page like any other command and keeps it only if it passes. The test then checks it on every run.
|
|
188
|
+
|
|
189
|
+
To let the agent use decisions, [configure a decision model](/ai#configure-decision-models) and enable the Decision helper.
|
|
190
|
+
|
|
191
|
+
Decision models like [Jev](https://openrouter.ai/typesafe/jev-1.13) are built for this. They answer in a fraction of a second, cost a fraction of a cent per request, and return a probability instead of free text. That makes them fast and cheap enough to run on every CI build, and predictable enough to keep in a test.
|
|
192
|
+
|
|
168
193
|
## Skills bundle
|
|
169
194
|
|
|
170
195
|
Skills teach the agent best practices for using CodeceptJS. Plug them in when you develop tests with agents, and update them regularly to ensure you use CodeceptJS in the most effective way.
|
package/docs/ai.md
CHANGED
|
@@ -23,6 +23,7 @@ CodeceptJS AI can do the following:
|
|
|
23
23
|
|
|
24
24
|
- ποΈββοΈ **assist writing tests** in `pause()` or interactive shell mode
|
|
25
25
|
- π **self-heal failing tests** (can be used on CI)
|
|
26
|
+
- βοΈ **assert statements in plain language** with [decision models](#decision-assertions)
|
|
26
27
|
|
|
27
28
|

|
|
28
29
|
|
|
@@ -338,6 +339,62 @@ Run tests with both AI and analyze enabled:
|
|
|
338
339
|
npx codeceptjs run --ai
|
|
339
340
|
```
|
|
340
341
|
|
|
342
|
+
## Decision Assertions
|
|
343
|
+
|
|
344
|
+
Some checks are hard to express with locators: "checkout form has all required fields", "success message is shown". The [Decision helper](/helpers/Decision) asserts them in plain language:
|
|
345
|
+
|
|
346
|
+
```js
|
|
347
|
+
I.decide([
|
|
348
|
+
'checkout form has all required fields',
|
|
349
|
+
'submit button enabled',
|
|
350
|
+
])
|
|
351
|
+
I.decideVisually('sidebar is shown')
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
It uses a [decision model](https://openrouter.ai/models?output_modalities=decisions) like [Jev](https://openrouter.ai/typesafe/jev-1.13) instead of a chat model. A decision model reads the page and returns the probability that a statement is true. It is fast, costs a fraction of a cent per request, and gives a probability instead of free text, so a step passes or fails on a confidence threshold you set.
|
|
355
|
+
|
|
356
|
+
Decision models are separate from `ai.model`: decisions don't need `ai.model` or the `--ai` flag. CodeceptJS calls them with AI SDK [`experimental_decide`](https://ai-sdk.dev/docs/ai-sdk-core/decisions).
|
|
357
|
+
|
|
358
|
+
### Configure Decision Models
|
|
359
|
+
|
|
360
|
+
Decision models are served by the [OpenRouter Decisions API](https://openrouter.ai/models?output_modalities=decisions). Install the [OpenRouter provider](https://ai-sdk.dev/providers/community-providers/openrouter) `@openrouter/ai-sdk-provider`, set `OPENROUTER_API_KEY`, and create the decision model with `evaluationModel()` in `codecept.conf.js`:
|
|
361
|
+
|
|
362
|
+
```js
|
|
363
|
+
import { createOpenRouter } from '@openrouter/ai-sdk-provider'
|
|
364
|
+
|
|
365
|
+
const openrouter = createOpenRouter({
|
|
366
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
export default {
|
|
370
|
+
ai: {
|
|
371
|
+
decisionModel: {
|
|
372
|
+
model: openrouter.evaluationModel('typesafe/jev-1.13'),
|
|
373
|
+
confidence: 0.8,
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
helpers: {
|
|
377
|
+
Playwright: { url: 'http://localhost' },
|
|
378
|
+
Decision: {},
|
|
379
|
+
},
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
`model` is used by `I.decide`.
|
|
384
|
+
|
|
385
|
+
### Visual Decision Model
|
|
386
|
+
|
|
387
|
+
`I.decideVisually` sends a screenshot, so it needs a separate decision model with image input. Set it as `visualModel`:
|
|
388
|
+
|
|
389
|
+
```js
|
|
390
|
+
decisionModel: {
|
|
391
|
+
model: openrouter.evaluationModel('typesafe/jev-1.13'),
|
|
392
|
+
visualModel: openrouter.evaluationModel('cloudflare/clef'),
|
|
393
|
+
},
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
See [Decision Assertions](/assertions#decision-assertions) for all options and usage.
|
|
397
|
+
|
|
341
398
|
## Advanced Configuration
|
|
342
399
|
|
|
343
400
|
AI prompts and HTML compression can be configured inside `ai` section of `codecept.conf` file:
|
|
@@ -6,153 +6,180 @@ title: Alternative Browser Engines
|
|
|
6
6
|
# Alternative Browser Engines
|
|
7
7
|
|
|
8
8
|
::: warning Experimental
|
|
9
|
-
The `
|
|
9
|
+
The `Obscura`, `Lightpanda` and `Kitesurf` helpers are experimental. Keep a Playwright or WebDriver job for compatibility-critical tests.
|
|
10
10
|
:::
|
|
11
11
|
|
|
12
|
-
Playwright
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
##
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
12
|
+
Playwright drives full Chromium, Firefox and WebKit: the most accurate way to test what users see, at the cost of a heavy browser per worker. Alternative engines trade part of that accuracy for speed, a small footprint, or cloud scale. They are a good fit for functional tests (text appears, form submits, redirect happens, cookie is set) and a poor one for anything visual.
|
|
13
|
+
|
|
14
|
+
Your tests do not change. `I.amOnPage`, `I.click`, `I.fillField`, `I.see`, `I.seeElement` and the rest of the `I.*` web API work the same; you only swap the helper in the config. All engines below speak Chrome DevTools Protocol, so there is no `npx playwright install` step.
|
|
15
|
+
|
|
16
|
+
Compared to Playwright, none of them supports iframes (`switchTo`), multiple tabs, popups, `dragAndDrop`, `moveCursorTo`, or Playwright-only APIs such as `usePlaywrightTo` and `mockRoute`. Tag scenarios that need those and skip them on the alternative engine:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npx codeceptjs run --grep @playwright-only --invert
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
To see which `I.*` actions the configured engine supports:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npx codeceptjs list
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Obscura
|
|
29
|
+
|
|
30
|
+
[Obscura](https://github.com/h4ckf0r0day/obscura) is a lightweight open-source browser with a real V8 engine and its own rendering engine, distributed as a single binary for Linux, macOS and Windows. Unlike Lightpanda it renders: layout, visibility checks, screenshots and the `screencast` plugin work.
|
|
31
|
+
|
|
32
|
+
Limitations:
|
|
33
|
+
|
|
34
|
+
- `attachFile` does not upload files.
|
|
35
|
+
- Clicks inside nested shadow DOM do not work.
|
|
36
|
+
- `focus` and `blur` have no effect.
|
|
37
|
+
- Clipboard actions do not work.
|
|
38
|
+
- A `<select multiple>` submits only its first selected option.
|
|
39
|
+
- An element inside a `visibility: hidden` parent is reported as visible.
|
|
40
|
+
- Some computed styles (`cursor`, `user-select`) differ from Chromium.
|
|
41
|
+
- Rich text editors TinyMCE, Trix, Monaco and ProseMirror do not work.
|
|
42
|
+
|
|
43
|
+
### Setup
|
|
44
|
+
|
|
45
|
+
Install Obscura following the [official instructions](https://github.com/h4ckf0r0day/obscura#installation) and put `obscura` on `PATH`. Then enable the helper:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
// codecept.conf.js
|
|
49
|
+
export const config = {
|
|
50
|
+
helpers: {
|
|
51
|
+
Obscura: {
|
|
52
|
+
url: 'http://localhost:3000',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If the binary is not on `PATH`, set `binaryPath` in the config or the `OBSCURA_PATH` environment variable.
|
|
59
|
+
|
|
60
|
+
### Usage
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
npx codeceptjs run
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The helper starts `obscura serve` on a free port before the first test and stops it after the last one, like Playwright manages Chromium. Each worker gets its own instance:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
npx codeceptjs run-workers 8
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
To connect to an Obscura you started yourself, set `endpoint`; the helper then never starts or stops it:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
obscura serve --port 9222 --allow-private-network --allow-file-access
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
Obscura: {
|
|
80
|
+
url: 'http://localhost:3000',
|
|
81
|
+
endpoint: 'http://127.0.0.1:9222',
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
All options: [Obscura helper reference](/helpers/Obscura).
|
|
86
|
+
|
|
87
|
+
## Lightpanda
|
|
88
|
+
|
|
89
|
+
[Lightpanda](https://lightpanda.io) is an open-source headless browser built from scratch for automation. It runs your app's JavaScript in V8 but never paints anything, which makes it start in milliseconds and use a fraction of Chromium's memory. It computes enough layout for `seeElement`, `waitForVisible` and other visibility checks.
|
|
90
|
+
|
|
91
|
+
Limitations:
|
|
92
|
+
|
|
93
|
+
- No screenshots: `saveScreenshot`, failure screenshots and the `screencast` plugin do not work.
|
|
94
|
+
- No scrolling: `scrollTo` and `scrollPageToBottom` have no effect.
|
|
95
|
+
- `clickXY` does not work.
|
|
96
|
+
- Clipboard actions do not work.
|
|
97
|
+
- Computed styles cover `display`, `visibility` and `opacity`; other CSS properties are unreliable.
|
|
98
|
+
- Rich text editors TinyMCE, Trix and Monaco do not work.
|
|
99
|
+
- Linux and macOS only; on Windows use WSL2.
|
|
100
|
+
- Licensed under AGPL-3.0. It runs as a separate process, so it does not affect the license of your tests.
|
|
101
|
+
|
|
102
|
+
### Setup
|
|
103
|
+
|
|
104
|
+
Install Lightpanda following the [official instructions](https://lightpanda.io/docs/open-source/installation) and put `lightpanda` on `PATH`. Then enable the helper:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
// codecept.conf.js
|
|
108
|
+
export const config = {
|
|
109
|
+
helpers: {
|
|
110
|
+
Lightpanda: {
|
|
111
|
+
url: 'http://localhost:3000',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
If the binary is not on `PATH`, set `binaryPath` in the config or the `LIGHTPANDA_PATH` environment variable.
|
|
118
|
+
|
|
119
|
+
### Usage
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
npx codeceptjs run
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The helper starts `lightpanda serve` on a free port with telemetry turned off, and stops it after the last test. Each worker gets its own instance:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
npx codeceptjs run-workers 8
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
To connect to a Lightpanda you started yourself, set `endpoint`; the helper then never starts or stops it:
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
LIGHTPANDA_DISABLE_TELEMETRY=true lightpanda serve --host 127.0.0.1 --port 9222
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```js
|
|
138
|
+
Lightpanda: {
|
|
139
|
+
url: 'http://localhost:3000',
|
|
140
|
+
endpoint: 'http://127.0.0.1:9222',
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
All options: [Lightpanda helper reference](/helpers/Lightpanda).
|
|
145
|
+
|
|
146
|
+
## Kitesurf
|
|
147
|
+
|
|
148
|
+
[Kitesurf](https://blog.cloudflare.com/kitesurf/) is Cloudflare's browser running on Cloudflare Workers, with a real layout and rendering pipeline. Sessions start in about a second and nothing runs on your machine, so the number of parallel browsers is limited only by how far your suite splits.
|
|
149
|
+
|
|
150
|
+
Limitations:
|
|
151
|
+
|
|
152
|
+
- Cloud only, currently a free beta.
|
|
153
|
+
- The browser cannot reach `localhost`: test a deployed environment or expose your app with a tunnel such as `cloudflared tunnel --url http://localhost:3000`.
|
|
154
|
+
|
|
155
|
+
### Setup
|
|
156
|
+
|
|
157
|
+
Enable [Cloudflare Browser Run](https://developers.cloudflare.com/browser-run/) and create an API token with the **Browser Rendering β Edit** permission. Export the credentials:
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
export CF_ACCOUNT_ID=your-account-id
|
|
161
|
+
export CF_API_TOKEN=your-api-token
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Then enable the helper:
|
|
165
|
+
|
|
166
|
+
```js
|
|
167
|
+
// codecept.conf.js
|
|
168
|
+
export const config = {
|
|
169
|
+
helpers: {
|
|
170
|
+
Kitesurf: {
|
|
171
|
+
url: 'https://staging.myapp.com',
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Usage
|
|
178
|
+
|
|
179
|
+
Every worker opens its own cloud session:
|
|
180
|
+
|
|
181
|
+
```sh
|
|
182
|
+
npx codeceptjs run-workers 16
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
All options: [Kitesurf helper reference](/helpers/Kitesurf).
|
package/docs/assertions.md
CHANGED
|
@@ -397,6 +397,79 @@ If two checks failed, the scenario fails with a single aggregated message like:
|
|
|
397
397
|
expected soft assertions '[expected web application to include "You must accept the terms", expected element (.summary-error) to be visible]' to be empty
|
|
398
398
|
```
|
|
399
399
|
|
|
400
|
+
## Decision Assertions
|
|
401
|
+
|
|
402
|
+
Some checks are hard to express with locators: "checkout form has all required fields", "success message is shown", "sidebar is shown". The [Decision helper](/helpers/Decision) asserts such statements in plain language with a decision model.
|
|
403
|
+
|
|
404
|
+
A [decision model](https://openrouter.ai/models?output_modalities=decisions), like [Jev](https://openrouter.ai/typesafe/jev-1.13), does not generate text. It reads the page and returns the probability that a statement is true. This makes it a good fit for assertions:
|
|
405
|
+
|
|
406
|
+
- **Fast.** One request returns in a fraction of a second, so a decision step runs about as fast as a regular browser step.
|
|
407
|
+
- **Cost-efficient.** A request costs a fraction of a cent. You can run decision assertions in every CI build.
|
|
408
|
+
- **Reliable.** The answer is a probability, not free text. There is nothing to parse, and you choose how confident the model must be for the step to pass.
|
|
409
|
+
|
|
410
|
+
Configure the decision model in `ai.decisionModel` as described in [Configure Decision Models](/ai#configure-decision-models), and enable the helper next to your browser helper:
|
|
411
|
+
|
|
412
|
+
```js
|
|
413
|
+
helpers: {
|
|
414
|
+
Playwright: { url: 'http://localhost' },
|
|
415
|
+
Decision: {},
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
`ai.decisionModel` accepts:
|
|
420
|
+
|
|
421
|
+
| Option | Default | Description |
|
|
422
|
+
|---|---|---|
|
|
423
|
+
| `model` | | decision model for `I.decide` |
|
|
424
|
+
| `visualModel` | | decision model with image input for `I.decideVisually` |
|
|
425
|
+
| `confidence` | `0.7` | minimal probability for a statement to pass |
|
|
426
|
+
| `timeout` | `15000` | request timeout in ms |
|
|
427
|
+
| `maxLength` | `12000` | maximal length of ARIA snapshot or HTML sent to the model |
|
|
428
|
+
|
|
429
|
+
Any model from the [OpenRouter decision models](https://openrouter.ai/models?output_modalities=decisions) list can be used with `openrouter.evaluationModel()`. Decisions don't need the `--ai` flag, and `ai.model` is not required.
|
|
430
|
+
|
|
431
|
+
Then assert statements about the current page:
|
|
432
|
+
|
|
433
|
+
```js
|
|
434
|
+
I.decide('top level navigation is available')
|
|
435
|
+
|
|
436
|
+
I.decide([
|
|
437
|
+
'checkout form has all required fields',
|
|
438
|
+
'success message is shown',
|
|
439
|
+
'submit button enabled',
|
|
440
|
+
'cancel button present',
|
|
441
|
+
])
|
|
442
|
+
|
|
443
|
+
I.decideVisually('sidebar is shown')
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
`I.decide` sends the page URL, title and ARIA snapshot to the model. A statement passes when its probability reaches `confidence`. A list of statements is checked in one request, and every statement must pass. The failure message lists the statements that failed, with their probabilities:
|
|
447
|
+
|
|
448
|
+
```
|
|
449
|
+
expected page to satisfy "success message is shown" (12%) with confidence of 70%
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
`I.decideVisually` also sends a screenshot, so it needs a [visual decision model](/ai#visual-decision-model) with image input, like [Clef](https://openrouter.ai/cloudflare/clef), set as `visualModel`. Visual decisions are experimental.
|
|
453
|
+
|
|
454
|
+
To turn decisions off without removing the helper, set its `mode`:
|
|
455
|
+
|
|
456
|
+
| Mode | Behavior |
|
|
457
|
+
|---|---|
|
|
458
|
+
| `assert` | default, fails the step when a statement is not confirmed |
|
|
459
|
+
| `report` | requests the model but never fails, even on API errors; results and errors are added to the step as a comment |
|
|
460
|
+
| `skip` | does not request the model, every decision passes |
|
|
461
|
+
|
|
462
|
+
```js
|
|
463
|
+
helpers: {
|
|
464
|
+
Playwright: { url: 'http://localhost' },
|
|
465
|
+
Decision: { mode: process.env.CI ? 'assert' : 'skip' },
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
A failed decision is not retried by the [retryFailedStep](/plugins/retryFailedStep) plugin: asking again would cost another request and return the same answer. Only connection errors and timeouts are retried.
|
|
470
|
+
|
|
471
|
+
Use decision assertions for what a page means, and built-in assertions for exact values. `I.see('Total: $42.00')` is still the right check for a price.
|
|
472
|
+
|
|
400
473
|
## Choosing an Approach
|
|
401
474
|
|
|
402
475
|
| You want to check⦠| Use |
|
|
@@ -412,4 +485,5 @@ expected soft assertions '[expected web application to include "You must accept
|
|
|
412
485
|
| A matcher the above do not cover | `grab*` + `chai` / `jest` / `node:assert` |
|
|
413
486
|
| A **reusable, project-specific** check | [Custom helper](/custom-helpers) with `see*` method using `codeceptjs/assertions` |
|
|
414
487
|
| Many independent checks in one run | `hopeThat` from `codeceptjs/effects` |
|
|
488
|
+
| A statement that is hard to express with locators | [Decision helper](#decision-assertions) β `I.decide`, `I.decideVisually` |
|
|
415
489
|
| Hiding values from logs | `secret()` |
|
package/docs/bootstrap.md
CHANGED
|
@@ -10,6 +10,8 @@ you can use the `bootstrap` and `teardown` config. Use it to start and stop a we
|
|
|
10
10
|
|
|
11
11
|
When using the [parallel execution](/parallel) mode, there are two additional hooks available; `bootstrapAll` and `teardownAll`. See [bootstrapAll & teardownAll](#bootstrapall-teardownall) for more information.
|
|
12
12
|
|
|
13
|
+
> To start and stop the application under test, use the [`webServer`](/configuration#web-server) option instead of writing bootstrap code.
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
### Example: Bootstrap & Teardown
|
|
15
17
|
|