codeceptjs 4.0.0-rc.18 → 4.0.0-rc.19
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/bin/codecept.js +5 -1
- package/bin/codeceptq.js +49 -0
- package/bin/mcp-server.js +250 -82
- package/docs/advanced.md +201 -0
- package/docs/agents.md +159 -0
- package/docs/ai.md +537 -0
- package/docs/aitrace.md +266 -0
- package/docs/api.md +332 -0
- package/docs/assertions.md +415 -0
- package/docs/auth.md +318 -0
- package/docs/basics.md +424 -0
- package/docs/bdd.md +539 -0
- package/docs/best.md +240 -0
- package/docs/bootstrap.md +132 -0
- package/docs/commands.md +352 -0
- package/docs/community-helpers.md +63 -0
- package/docs/configuration.md +230 -0
- package/docs/continuous-integration.md +497 -0
- package/docs/custom-helpers.md +297 -0
- package/docs/data.md +448 -0
- package/docs/debugging.md +332 -0
- package/docs/detox.md +235 -0
- package/docs/docker.md +136 -0
- package/docs/effects.md +179 -0
- package/docs/element-based-testing.md +295 -0
- package/docs/element-selection.md +125 -0
- package/docs/els.md +328 -0
- package/docs/examples.md +161 -0
- package/docs/heal.md +213 -0
- package/docs/helpers/ApiDataFactory.md +267 -0
- package/docs/helpers/Appium.md +1405 -0
- package/docs/helpers/Detox.md +665 -0
- package/docs/helpers/ExpectHelper.md +275 -0
- package/docs/helpers/FileSystem.md +152 -0
- package/docs/helpers/GraphQL.md +152 -0
- package/docs/helpers/GraphQLDataFactory.md +226 -0
- package/docs/helpers/JSONResponse.md +255 -0
- package/docs/helpers/Mochawesome.md +8 -0
- package/docs/helpers/MockRequest.md +377 -0
- package/docs/helpers/MockServer.md +212 -0
- package/docs/helpers/Playwright.md +2969 -0
- package/docs/helpers/Polly.md +44 -0
- package/docs/helpers/Protractor.md +1769 -0
- package/docs/helpers/Puppeteer-firefox.md +86 -0
- package/docs/helpers/Puppeteer.md +2690 -0
- package/docs/helpers/REST.md +289 -0
- package/docs/helpers/SoftExpectHelper.md +352 -0
- package/docs/helpers/WebDriver.md +2682 -0
- package/docs/hooks.md +339 -0
- package/docs/index.md +111 -0
- package/docs/installation.md +83 -0
- package/docs/internal-api.md +265 -0
- package/docs/internal-test-server.md +89 -0
- package/docs/locators.md +355 -0
- package/docs/mcp.md +485 -0
- package/docs/migration-4.md +556 -0
- package/docs/mobile.md +338 -0
- package/docs/pageobjects.md +399 -0
- package/docs/parallel.md +585 -0
- package/docs/playwright.md +714 -0
- package/docs/plugins.md +866 -0
- package/docs/puppeteer.md +314 -0
- package/docs/quickstart.md +120 -0
- package/docs/react.md +70 -0
- package/docs/reports.md +483 -0
- package/docs/retry.md +274 -0
- package/docs/secrets.md +150 -0
- package/docs/sessions.md +80 -0
- package/docs/shadow.md +68 -0
- package/docs/test-structure.md +275 -0
- package/docs/timeouts.md +183 -0
- package/docs/translation.md +247 -0
- package/docs/tutorial.md +271 -0
- package/docs/typescript.md +374 -0
- package/docs/web-element.md +251 -0
- package/docs/webdriver.md +708 -0
- package/docs/within.md +55 -0
- package/lib/command/dryRun.js +9 -3
- package/lib/command/init.js +247 -266
- package/lib/command/query.js +218 -0
- package/lib/config.js +9 -0
- package/lib/element/WebElement.js +37 -0
- package/lib/globals.js +11 -10
- package/lib/helper/Playwright.js +4 -1
- package/lib/html.js +3 -0
- package/lib/index.js +9 -1
- package/lib/locator.js +2 -2
- package/lib/mocha/factory.js +5 -1
- package/lib/mocha/inject.js +1 -1
- package/lib/parser.js +2 -2
- package/lib/plugin/browser.js +2 -1
- package/lib/plugin/expose.js +159 -0
- package/lib/workers.js +1 -15
- package/package.json +7 -5
- package/docs/webapi/amOnPage.mustache +0 -11
- package/docs/webapi/appendField.mustache +0 -16
- package/docs/webapi/attachFile.mustache +0 -24
- package/docs/webapi/blur.mustache +0 -18
- package/docs/webapi/checkOption.mustache +0 -13
- package/docs/webapi/clearCookie.mustache +0 -9
- package/docs/webapi/clearField.mustache +0 -14
- package/docs/webapi/click.mustache +0 -29
- package/docs/webapi/clickLink.mustache +0 -8
- package/docs/webapi/closeCurrentTab.mustache +0 -7
- package/docs/webapi/closeOtherTabs.mustache +0 -8
- package/docs/webapi/dontSee.mustache +0 -11
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/dontSeeCookie.mustache +0 -8
- package/docs/webapi/dontSeeCurrentPathEquals.mustache +0 -10
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
- package/docs/webapi/dontSeeElement.mustache +0 -12
- package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
- package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
- package/docs/webapi/dontSeeInField.mustache +0 -16
- package/docs/webapi/dontSeeInSource.mustache +0 -8
- package/docs/webapi/dontSeeInTitle.mustache +0 -8
- package/docs/webapi/dontSeeTraffic.mustache +0 -13
- package/docs/webapi/doubleClick.mustache +0 -13
- package/docs/webapi/downloadFile.mustache +0 -12
- package/docs/webapi/dragAndDrop.mustache +0 -9
- package/docs/webapi/dragSlider.mustache +0 -11
- package/docs/webapi/executeAsyncScript.mustache +0 -24
- package/docs/webapi/executeScript.mustache +0 -26
- package/docs/webapi/fillField.mustache +0 -21
- package/docs/webapi/flushNetworkTraffics.mustache +0 -5
- package/docs/webapi/focus.mustache +0 -13
- package/docs/webapi/forceClick.mustache +0 -28
- package/docs/webapi/forceRightClick.mustache +0 -18
- package/docs/webapi/grabAllWindowHandles.mustache +0 -7
- package/docs/webapi/grabAttributeFrom.mustache +0 -10
- package/docs/webapi/grabAttributeFromAll.mustache +0 -9
- package/docs/webapi/grabBrowserLogs.mustache +0 -9
- package/docs/webapi/grabCookie.mustache +0 -11
- package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
- package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
- package/docs/webapi/grabCurrentUrl.mustache +0 -9
- package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
- package/docs/webapi/grabElementBoundingRect.mustache +0 -20
- package/docs/webapi/grabGeoLocation.mustache +0 -8
- package/docs/webapi/grabHTMLFrom.mustache +0 -10
- package/docs/webapi/grabHTMLFromAll.mustache +0 -9
- package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
- package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
- package/docs/webapi/grabPageScrollPosition.mustache +0 -8
- package/docs/webapi/grabPopupText.mustache +0 -5
- package/docs/webapi/grabRecordedNetworkTraffics.mustache +0 -10
- package/docs/webapi/grabSource.mustache +0 -8
- package/docs/webapi/grabTextFrom.mustache +0 -10
- package/docs/webapi/grabTextFromAll.mustache +0 -9
- package/docs/webapi/grabTitle.mustache +0 -8
- package/docs/webapi/grabValueFrom.mustache +0 -9
- package/docs/webapi/grabValueFromAll.mustache +0 -8
- package/docs/webapi/grabWebElement.mustache +0 -9
- package/docs/webapi/grabWebElements.mustache +0 -9
- package/docs/webapi/moveCursorTo.mustache +0 -16
- package/docs/webapi/openNewTab.mustache +0 -7
- package/docs/webapi/pressKey.mustache +0 -12
- package/docs/webapi/pressKeyDown.mustache +0 -12
- package/docs/webapi/pressKeyUp.mustache +0 -12
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
- package/docs/webapi/refreshPage.mustache +0 -6
- package/docs/webapi/resizeWindow.mustache +0 -6
- package/docs/webapi/rightClick.mustache +0 -14
- package/docs/webapi/saveElementScreenshot.mustache +0 -10
- package/docs/webapi/saveScreenshot.mustache +0 -12
- package/docs/webapi/say.mustache +0 -10
- package/docs/webapi/scrollIntoView.mustache +0 -11
- package/docs/webapi/scrollPageToBottom.mustache +0 -6
- package/docs/webapi/scrollPageToTop.mustache +0 -6
- package/docs/webapi/scrollTo.mustache +0 -12
- package/docs/webapi/see.mustache +0 -11
- package/docs/webapi/seeAttributesOnElements.mustache +0 -9
- package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/seeCookie.mustache +0 -8
- package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
- package/docs/webapi/seeCurrentPathEquals.mustache +0 -10
- package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
- package/docs/webapi/seeElement.mustache +0 -12
- package/docs/webapi/seeElementInDOM.mustache +0 -8
- package/docs/webapi/seeFileDownloaded.mustache +0 -23
- package/docs/webapi/seeInCurrentUrl.mustache +0 -8
- package/docs/webapi/seeInField.mustache +0 -17
- package/docs/webapi/seeInPopup.mustache +0 -8
- package/docs/webapi/seeInSource.mustache +0 -7
- package/docs/webapi/seeInTitle.mustache +0 -8
- package/docs/webapi/seeNumberOfElements.mustache +0 -11
- package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/seeTextEquals.mustache +0 -9
- package/docs/webapi/seeTitleEquals.mustache +0 -8
- package/docs/webapi/seeTraffic.mustache +0 -36
- package/docs/webapi/selectOption.mustache +0 -26
- package/docs/webapi/setCookie.mustache +0 -16
- package/docs/webapi/setGeoLocation.mustache +0 -12
- package/docs/webapi/startRecordingTraffic.mustache +0 -8
- package/docs/webapi/startRecordingWebSocketMessages.mustache +0 -8
- package/docs/webapi/stopRecordingTraffic.mustache +0 -5
- package/docs/webapi/stopRecordingWebSocketMessages.mustache +0 -7
- package/docs/webapi/switchTo.mustache +0 -9
- package/docs/webapi/switchToNextTab.mustache +0 -10
- package/docs/webapi/switchToPreviousTab.mustache +0 -10
- package/docs/webapi/type.mustache +0 -21
- package/docs/webapi/uncheckOption.mustache +0 -13
- package/docs/webapi/wait.mustache +0 -8
- package/docs/webapi/waitForClickable.mustache +0 -11
- package/docs/webapi/waitForCookie.mustache +0 -9
- package/docs/webapi/waitForDetached.mustache +0 -10
- package/docs/webapi/waitForDisabled.mustache +0 -6
- package/docs/webapi/waitForElement.mustache +0 -11
- package/docs/webapi/waitForEnabled.mustache +0 -6
- package/docs/webapi/waitForFunction.mustache +0 -17
- package/docs/webapi/waitForInvisible.mustache +0 -10
- package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
- package/docs/webapi/waitForText.mustache +0 -13
- package/docs/webapi/waitForValue.mustache +0 -10
- package/docs/webapi/waitForVisible.mustache +0 -10
- package/docs/webapi/waitInUrl.mustache +0 -9
- package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/waitToHide.mustache +0 -10
- package/docs/webapi/waitUrlEquals.mustache +0 -10
package/docs/aitrace.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
---
|
|
2
|
+
permalink: /aitrace
|
|
3
|
+
title: AI Trace Plugin
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AI Trace Plugin
|
|
7
|
+
|
|
8
|
+
AI Trace Plugin generates AI-friendly trace files for debugging with AI agents like Claude Code.
|
|
9
|
+
|
|
10
|
+
When a test fails, you need to understand what went wrong: what the page looked like, what elements were present, what errors occurred, and what led to the failure. This plugin automatically captures all that information and organizes it in a format optimized for AI analysis.
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
Enable the plugin in your `codecept.conf.js`:
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
export const config = {
|
|
18
|
+
tests: './*_test.js',
|
|
19
|
+
output: './output',
|
|
20
|
+
helpers: {
|
|
21
|
+
Playwright: {
|
|
22
|
+
url: 'https://example.com',
|
|
23
|
+
// Optional: Enable HAR/trace for HTTP capture
|
|
24
|
+
recordHar: {
|
|
25
|
+
mode: 'minimal',
|
|
26
|
+
content: 'embed',
|
|
27
|
+
},
|
|
28
|
+
trace: 'on',
|
|
29
|
+
keepTraceForPassedTests: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
plugins: {
|
|
33
|
+
aiTrace: {
|
|
34
|
+
enabled: true,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Run tests:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx codeceptjs run
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
After test execution, trace files are created in `output/trace_*/trace.md`.
|
|
47
|
+
|
|
48
|
+
## Artifacts Created
|
|
49
|
+
|
|
50
|
+
For each test, a `trace_<sha256>` directory is created with the following files:
|
|
51
|
+
|
|
52
|
+
**trace.md** - AI-friendly markdown file with test execution history
|
|
53
|
+
|
|
54
|
+
**0000_step_name_screenshot.png** - Screenshot for each step (file names include step names)
|
|
55
|
+
|
|
56
|
+
**0000_step_name_page.html** - Full HTML of the page at each step. Processed through a `minify -> clean -> beautify` pipeline so the file is multi-line indented, free of `<script>` / `<style>` / `<noscript>` content, free of inline `style=""` attributes, and free of trash class names (Tailwind utilities, framework-generated `v-*` / `ember-*`, hashed classes, scoped `xl:hidden`-style classes). Semantic attributes (`id`, `aria-*`, `data-*`, `role`, etc.) are preserved.
|
|
57
|
+
|
|
58
|
+
**0000_step_name_aria.txt** - ARIA accessibility snapshot (AI-readable structure without HTML noise; Playwright only)
|
|
59
|
+
|
|
60
|
+
**0000_step_name_console.json** - Browser console logs, normalized to plain `{ type, text }` objects (Playwright `ConsoleMessage` instances are coerced via their `.type()` / `.text()` methods so the JSON file is genuinely useful — not full of empty objects).
|
|
61
|
+
|
|
62
|
+
When HAR or trace recording is enabled in your helper config, links to those files are also included.
|
|
63
|
+
|
|
64
|
+
**Note:** Artifact files are named using step names for easier identification (e.g., `0000_I_see_Product_screenshot.png` instead of just `0000_screenshot.png`).
|
|
65
|
+
|
|
66
|
+
**Storage state:** Cookies and `localStorage` are intentionally **not** captured per-step by `aiTrace` (they rarely change between actions, so per-step `_storage.json` files would be noise). Use the `pageInfo` plugin or the MCP `snapshot()` tool when you need a storage snapshot.
|
|
67
|
+
|
|
68
|
+
## Trace File Format
|
|
69
|
+
|
|
70
|
+
The `trace.md` file contains a structured execution log with links to all artifacts:
|
|
71
|
+
|
|
72
|
+
```markdown
|
|
73
|
+
file: /path/to/test.js
|
|
74
|
+
name: My test scenario
|
|
75
|
+
time: 3.45s
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
I am on page "https://example.com"
|
|
79
|
+
> navigated to https://example.com/
|
|
80
|
+
> [HTML](./0000_I_am_on_page_https_example.com_page.html)
|
|
81
|
+
> [ARIA Snapshot](./0000_I_am_on_page_https_example.com_aria.txt)
|
|
82
|
+
> [Screenshot](./0000_I_am_on_page_https_example.com_screenshot.png)
|
|
83
|
+
> [Browser Logs](./0000_I_am_on_page_https_example.com_console.json) (7 entries)
|
|
84
|
+
> HTTP: see [HAR file](../har/...) for network requests
|
|
85
|
+
|
|
86
|
+
I see "Welcome"
|
|
87
|
+
> navigated to https://example.com/
|
|
88
|
+
> [HTML](./0001_I_see_Welcome_page.html)
|
|
89
|
+
> [ARIA Snapshot](./0001_I_see_Welcome_aria.txt)
|
|
90
|
+
> [Screenshot](./0001_I_see_Welcome_screenshot.png)
|
|
91
|
+
> [Browser Logs](./0001_I_see_Welcome_console.json) (0 entries)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Files are named with step descriptions for easier navigation and debugging.
|
|
95
|
+
|
|
96
|
+
## Configuration
|
|
97
|
+
|
|
98
|
+
### Basic Configuration
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
plugins: {
|
|
102
|
+
aiTrace: {
|
|
103
|
+
enabled: true,
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Advanced Configuration
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
plugins: {
|
|
112
|
+
aiTrace: {
|
|
113
|
+
enabled: true,
|
|
114
|
+
|
|
115
|
+
// Artifact capture options
|
|
116
|
+
captureHTML: true, // Save HTML for each step
|
|
117
|
+
captureARIA: true, // Save ARIA snapshots
|
|
118
|
+
captureBrowserLogs: true, // Save console logs
|
|
119
|
+
captureHTTP: true, // Links to HAR/trace files
|
|
120
|
+
captureDebugOutput: true, // CodeceptJS debug messages
|
|
121
|
+
|
|
122
|
+
// Screenshot options
|
|
123
|
+
fullPageScreenshots: false, // Full page or viewport only
|
|
124
|
+
|
|
125
|
+
// Output options
|
|
126
|
+
output: './output', // Where to save traces
|
|
127
|
+
deleteSuccessful: false, // Delete traces for passed tests
|
|
128
|
+
|
|
129
|
+
// Step filtering
|
|
130
|
+
ignoreSteps: [
|
|
131
|
+
/^grab/, // Ignore all grab* steps
|
|
132
|
+
/^wait/, // Ignore all wait* steps
|
|
133
|
+
],
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Configuration Options
|
|
139
|
+
|
|
140
|
+
| Option | Type | Default | Description |
|
|
141
|
+
|--------|------|---------|-------------|
|
|
142
|
+
| `enabled` | boolean | `false` | Enable/disable the plugin |
|
|
143
|
+
| `captureHTML` | boolean | `true` | Capture HTML for each step |
|
|
144
|
+
| `captureARIA` | boolean | `true` | Capture ARIA snapshots |
|
|
145
|
+
| `captureBrowserLogs` | boolean | `true` | Capture browser console logs |
|
|
146
|
+
| `captureHTTP` | boolean | `true` | Capture HTTP requests (requires HAR/trace) |
|
|
147
|
+
| `captureDebugOutput` | boolean | `true` | Capture CodeceptJS debug output |
|
|
148
|
+
| `fullPageScreenshots` | boolean | `false` | Use full page screenshots |
|
|
149
|
+
| `output` | string | `'./output'` | Directory for trace files |
|
|
150
|
+
| `deleteSuccessful` | boolean | `false` | Delete traces for passed tests |
|
|
151
|
+
| `ignoreSteps` | array | `[]` | Steps to ignore (regex patterns) |
|
|
152
|
+
|
|
153
|
+
## Best Practices
|
|
154
|
+
|
|
155
|
+
### Optimize for Failing Tests
|
|
156
|
+
|
|
157
|
+
Save disk space by only keeping traces for failed tests:
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
plugins: {
|
|
161
|
+
aiTrace: {
|
|
162
|
+
enabled: true,
|
|
163
|
+
deleteSuccessful: true, // Only keep failing tests
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Ignore Noise
|
|
169
|
+
|
|
170
|
+
Don't capture logs for `grab` and `wait` steps:
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
plugins: {
|
|
174
|
+
aiTrace: {
|
|
175
|
+
enabled: true,
|
|
176
|
+
ignoreSteps: [/^grab/, /^wait/],
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Selective Artifact Capture
|
|
182
|
+
|
|
183
|
+
Capture only what you need to reduce file sizes:
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
plugins: {
|
|
187
|
+
aiTrace: {
|
|
188
|
+
enabled: true,
|
|
189
|
+
captureHTML: false, // Skip HTML (saves ~500KB per step)
|
|
190
|
+
captureARIA: true, // Keep ARIA (only ~16KB)
|
|
191
|
+
captureBrowserLogs: false, // Skip console logs
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Enable HTTP Capture
|
|
197
|
+
|
|
198
|
+
For network debugging, enable HAR/trace in your helper:
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
helpers: {
|
|
202
|
+
Playwright: {
|
|
203
|
+
recordHar: {
|
|
204
|
+
mode: 'minimal',
|
|
205
|
+
content: 'embed',
|
|
206
|
+
},
|
|
207
|
+
trace: 'on',
|
|
208
|
+
keepTraceForPassedTests: true,
|
|
209
|
+
},
|
|
210
|
+
plugins: {
|
|
211
|
+
aiTrace: {
|
|
212
|
+
enabled: true,
|
|
213
|
+
captureHTTP: true, // Links to HAR/trace files
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Using with AI Agents
|
|
220
|
+
|
|
221
|
+
The trace format is optimized for AI agents like Claude Code. When debugging a failing test, just point the AI agent to the `trace.md` file - it will read the file and all linked artifacts automatically to analyze the failure.
|
|
222
|
+
|
|
223
|
+
## Troubleshooting
|
|
224
|
+
|
|
225
|
+
### No trace files created
|
|
226
|
+
|
|
227
|
+
**Possible causes:**
|
|
228
|
+
1. Plugin not enabled
|
|
229
|
+
2. No steps executed
|
|
230
|
+
3. Tests skipped
|
|
231
|
+
|
|
232
|
+
**Solution:**
|
|
233
|
+
```bash
|
|
234
|
+
# Check if plugin is enabled
|
|
235
|
+
grep -A 5 "aiTrace" codecept.conf.js
|
|
236
|
+
|
|
237
|
+
# Run with verbose output
|
|
238
|
+
npx codeceptjs run --verbose
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### ARIA snapshots missing
|
|
242
|
+
|
|
243
|
+
**Possible cause:** Helper doesn't support `grabAriaSnapshot`
|
|
244
|
+
|
|
245
|
+
**Solution:** Use Playwright or update to latest CodeceptJS
|
|
246
|
+
|
|
247
|
+
### HAR files missing
|
|
248
|
+
|
|
249
|
+
**Possible cause:** HAR/trace not enabled in helper config
|
|
250
|
+
|
|
251
|
+
**Solution:**
|
|
252
|
+
```javascript
|
|
253
|
+
helpers: {
|
|
254
|
+
Playwright: {
|
|
255
|
+
recordHar: { mode: 'minimal' },
|
|
256
|
+
trace: 'on',
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Related
|
|
262
|
+
|
|
263
|
+
- [AI Features](/ai) - AI-powered testing features
|
|
264
|
+
- [Plugins](/plugins) - All available plugins
|
|
265
|
+
- [Configuration](/configuration) - General configuration
|
|
266
|
+
- [Playwright Helper](/playwright) - Playwright-specific configuration
|
package/docs/api.md
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
---
|
|
2
|
+
permalink: /api
|
|
3
|
+
title: API Testing
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## API Testing
|
|
7
|
+
|
|
8
|
+
CodeceptJS provides a way to write tests in declarative manner for REST and GraphQL APIs.
|
|
9
|
+
|
|
10
|
+
Take a look:
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
I.sendGetRequest('/users/1');
|
|
14
|
+
// returns { "user": { "name": "jon" }, "projects": [] }
|
|
15
|
+
I.seeResponseCodeIsSuccessful();
|
|
16
|
+
I.seeResponseContainsKeys(['user', 'projects']);
|
|
17
|
+
I.seeResponseContainsJson({ user: { name: 'jon' } });
|
|
18
|
+
I.seeResponseMatchesJsonSchema($ => {
|
|
19
|
+
return $.object(
|
|
20
|
+
user: $.object({
|
|
21
|
+
name: $.string(),
|
|
22
|
+
}),
|
|
23
|
+
projects: $.array()
|
|
24
|
+
)
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
In this code we checked API request for:
|
|
28
|
+
|
|
29
|
+
* status code
|
|
30
|
+
* data inclusion
|
|
31
|
+
* data structure
|
|
32
|
+
|
|
33
|
+
These are the things you should generally test your APIs for.
|
|
34
|
+
|
|
35
|
+
> 🤓 It is recommended to check only invariable parts of responses. Check for required fields and only values you control. For instance, it is not recommended to check id fields, date fields, as they can be frequently changed.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
Install CodeceptJS if it is not installed yet.
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
npm i codeceptjs --save-dev
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Initialize CodeceptJS and select REST or GraphQL helper when asked for a helper:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
npx codeceptjs init
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
Ensure that inside `codecept.conf.js` in helpers section `REST` or `GraphQL` helpers are enabled.
|
|
54
|
+
|
|
55
|
+
* If you use `REST` helper add `JSONResponse` helper below with no extra config:
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
// inside codecept.conf.js
|
|
59
|
+
// ...
|
|
60
|
+
helpers: {
|
|
61
|
+
REST: {
|
|
62
|
+
endpoint: 'http://localhost:3000/api'
|
|
63
|
+
},
|
|
64
|
+
// .. add JSONResponse helper here
|
|
65
|
+
JSONResponse: {}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
* If you use `GraphQL` helper add `JSONResponse` helper, configuring it to use GraphQL for requests:
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
helpers: {
|
|
72
|
+
GraphQL: {
|
|
73
|
+
endpoint: 'http://localhost:3000/graphql'
|
|
74
|
+
},
|
|
75
|
+
// .. add JSONResponse helper here
|
|
76
|
+
JSONResponse: {
|
|
77
|
+
requestHelper: 'GraphQL',
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Originally, REST and GraphQL helpers were not designed for API testing.
|
|
83
|
+
They were used to perform API requests for browser tests. As so, they lack assertion methods to API responses.
|
|
84
|
+
|
|
85
|
+
[`JSONResponse`](/helpers/JSONResponse/) helper adds response assertions.
|
|
86
|
+
|
|
87
|
+
> 💡 In CodeceptJS assertions start with `see` prefix. Learn more about assertions by [opening reference for JSONResponse](/helpers/JSONResponse/) helper.
|
|
88
|
+
|
|
89
|
+
Generate TypeScript definitions to get auto-completions for JSONResponse:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
npx codeceptjs def
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
After helpers were configured and typings were generated, you can start writing first API test. By default, CodeceptJS saves tests in `tests` directory and uses `*_test.js` suffix. The `init` command created the first test for you to start.
|
|
96
|
+
|
|
97
|
+
> Check [API Examples](https://github.com/codeceptjs/api-examples) to see tests implementations.
|
|
98
|
+
|
|
99
|
+
## Requests
|
|
100
|
+
|
|
101
|
+
[REST](/helpers/REST/) or [GraphQL](/helpers/GraphQL/) helpers implement methods for making API requests.
|
|
102
|
+
Both helpers send requests via HTTP protocol from CodeceptJS process.
|
|
103
|
+
For most cases, you will need to have authentication. It can be passed via headers, which can be added to helper's configuration in `codecept.conf.js`.
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
helpers: {
|
|
107
|
+
REST: {
|
|
108
|
+
defaultHeaders: {
|
|
109
|
+
// use Bearer Authorization
|
|
110
|
+
'Authorization': 'Bearer 11111',
|
|
111
|
+
'Content-Type': 'application/json',
|
|
112
|
+
'Accept': 'application/json',
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Or you can use the browser cookies if you are running browser session.
|
|
119
|
+
In this case use `setSharedCookies()` from `@codeceptjs/configure` package:
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
import { setSharedCookies } from '@codeceptjs/configure'
|
|
123
|
+
|
|
124
|
+
// call before exporting config
|
|
125
|
+
setSharedCookies()
|
|
126
|
+
|
|
127
|
+
export const config = {
|
|
128
|
+
// ...
|
|
129
|
+
helpers: {
|
|
130
|
+
// also works with Playwright or Puppeteer
|
|
131
|
+
WebDriver: {
|
|
132
|
+
//...
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
REST: {
|
|
136
|
+
// ...
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### REST
|
|
143
|
+
|
|
144
|
+
REST helper can send GET/POST/PATCH/etc requests to REST API endpoint:
|
|
145
|
+
|
|
146
|
+
* [`I.sendGetRequest()`](/helpers/REST#sendGetRequest)
|
|
147
|
+
* [`I.sendPostRequest()`](/helpers/REST#sendPostRequest)
|
|
148
|
+
* [`I.sendPutRequest()`](/helpers/REST#sendPutRequest)
|
|
149
|
+
* [`I.sendPatchRequest()`](/helpers/REST#sendPatchRequest)
|
|
150
|
+
* [`I.sendDeleteRequest()`](/helpers/REST#sendDeleteRequest)
|
|
151
|
+
* [`I.sendDeleteRequestWithPayload()`](/helpers/REST#sendDeleteRequestWithPayload)
|
|
152
|
+
* ...
|
|
153
|
+
|
|
154
|
+
Authentication headers can be set in [helper's config](https://codecept.io/helpers/REST/#configuration) or per test with headers or special methods like `I.amBearerAuthenticated`.
|
|
155
|
+
|
|
156
|
+
Example:
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
Feature('Users endpoint')
|
|
160
|
+
|
|
161
|
+
Scenario('create user', ({ I }) => {
|
|
162
|
+
// this way we pass Bearer token
|
|
163
|
+
I.amBearerAuthenticated(secret('token-is-here'));
|
|
164
|
+
// for custom authorization with headers use
|
|
165
|
+
// I.haveRequestHeaders method
|
|
166
|
+
|
|
167
|
+
// here we send a POST request
|
|
168
|
+
const response = await I.sendPostRequest('/users', {
|
|
169
|
+
name: 'joe',
|
|
170
|
+
email: 'joe@mail.com'
|
|
171
|
+
});
|
|
172
|
+
// usually we won't need direct access to response object for API testing
|
|
173
|
+
// but you can obtain it from request
|
|
174
|
+
|
|
175
|
+
// check the last request was successful
|
|
176
|
+
// this method introduced by JSONResponse helper
|
|
177
|
+
I.seeResponseCodeIsSuccessful();
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### GraphQL
|
|
182
|
+
|
|
183
|
+
GraphQL have request format different then in REST API, but the response format is the same.
|
|
184
|
+
It's plain old JSON. This why `JSONResponse` helper works for both API types.
|
|
185
|
+
Configure authorization headers in `codecept.conf.js` and make your first query:
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
Feature('Users endpoint')
|
|
189
|
+
|
|
190
|
+
Scenario('get user by query', ({ I }) => {
|
|
191
|
+
// make GraphQL query or mutation
|
|
192
|
+
const resp = await I.sendQuery('{ user(id: 0) { id name email }}');
|
|
193
|
+
I.seeResponseCodeIsSuccessful();
|
|
194
|
+
|
|
195
|
+
// GraphQL always returns key data as part of response
|
|
196
|
+
I.seeResponseContainsKeys(['data']);
|
|
197
|
+
|
|
198
|
+
// check data for partial inclusion
|
|
199
|
+
I.seeResponseContainsJson({
|
|
200
|
+
data: {
|
|
201
|
+
user: {
|
|
202
|
+
name: 'john doe',
|
|
203
|
+
email: 'johnd@mutex.com',
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
GraphQL helper has two methods available:
|
|
211
|
+
|
|
212
|
+
* [`I.sendQuery()`](/helpers/GraphQL#sendQuery)
|
|
213
|
+
* [`I.sendMutation()`](/helpers/GraphQL#sendMutation)
|
|
214
|
+
|
|
215
|
+
## Assertions
|
|
216
|
+
|
|
217
|
+
`JSONResponse` provides set of assertions for responses in JSON format. These assertions were designed to check only invariable parts of responses. So instead of checking that response equals to the one provided, we will check for data inclusion and structure matching.
|
|
218
|
+
|
|
219
|
+
For most of cases, you won't need to perform assertions by accessing `response` object directly. All assretions are performed under hood inside `JSONResponse` module. It is recommended to keep it that way, to keep tests readable and make test log to contain all assertions.
|
|
220
|
+
|
|
221
|
+
```js
|
|
222
|
+
Scenario('I make API call', ({ I }) => {
|
|
223
|
+
// request was made by REST
|
|
224
|
+
// or by GraphQL helper
|
|
225
|
+
|
|
226
|
+
// check that response code is 2xx
|
|
227
|
+
I.seeResponseCodeIsSuccessful();
|
|
228
|
+
|
|
229
|
+
// check that response contains keys
|
|
230
|
+
I.seeResponseContainsKeys(['data', 'pages', 'meta']);
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Response Status Codes
|
|
235
|
+
|
|
236
|
+
[Response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) can be checked to be equal to some value or to be in a specific range.
|
|
237
|
+
To check that response code is `200` call `I.seeResponseCodeIs`:
|
|
238
|
+
|
|
239
|
+
```js
|
|
240
|
+
I.seeResponseCodeIs(200);
|
|
241
|
+
```
|
|
242
|
+
But because other response codes in 2xx range are also valid responses, you can use `seeResponseCodeIsSuccessful()` which will match 200 (OK), 201 (Created), 206 (Partial Content) and others. Methods to check 3xx, 4xx, 5xx response statuses also available.
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
// matches 200, 201, 202, ... 206
|
|
246
|
+
I.seeResponseCodeIsSuccessful();
|
|
247
|
+
|
|
248
|
+
// matches 300...308
|
|
249
|
+
I.seeResponseCodeIsRedirection();
|
|
250
|
+
|
|
251
|
+
// matches 400..451
|
|
252
|
+
I.seeResponseCodeIsClientError();
|
|
253
|
+
|
|
254
|
+
// matches 500-511
|
|
255
|
+
I.seeResponseCodeIsServerError();
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Structure
|
|
259
|
+
|
|
260
|
+
The most basic thing to check in response is existence of keys in JSON object. Use [`I.seeResponseContainsKeys()`](/helpers/JSONResponse#seeResponseContainsKeys) method for it:
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
// response is { "name": "joe", "email": "joe@joe.com" }
|
|
264
|
+
I.seeResponseContainsKeys(['name', 'email']);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
> ℹ️ If response is an array, it will check that every element in array have provided keys
|
|
268
|
+
|
|
269
|
+
However, this is a very naive approach. It won't work for arrays or nested objects.
|
|
270
|
+
To check complex JSON structures `JSONResponse` helper uses [`Zod`](https://zod.dev) library.
|
|
271
|
+
It has rich API to validate JSON by the schema defined using JavaScript.
|
|
272
|
+
|
|
273
|
+
```js
|
|
274
|
+
// import zod library,
|
|
275
|
+
// it is installed with CodeceptJS
|
|
276
|
+
import { z } from 'zod';
|
|
277
|
+
|
|
278
|
+
// create schema definition using Zod API
|
|
279
|
+
const schema = z.object({
|
|
280
|
+
email: z.string().email(),
|
|
281
|
+
phone: z.string().regex(/^\d{3}-\d{3}-\d{4}$/),
|
|
282
|
+
birthday: z.string().datetime().max(new Date('2004-01-01'))
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// check that response matches that schema
|
|
286
|
+
I.seeResponseMatchesJsonSchema(schema);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> 📋 **Migration Note**: CodeceptJS has migrated from Joi to Zod v4 for JSON schema validation.
|
|
290
|
+
> If you have existing tests using Joi, please update them:
|
|
291
|
+
> * Replace `const Joi = require('joi')` with `import { z } from 'zod'`
|
|
292
|
+
> * Replace `Joi.object().keys({...})` with `z.object({...})`
|
|
293
|
+
> * Replace `Joi.string().email()` with `z.string().email()`
|
|
294
|
+
> * Replace `Joi.date()` with appropriate `z.string()` or `z.date()` types
|
|
295
|
+
> * See [Zod documentation](https://zod.dev) for complete API reference
|
|
296
|
+
|
|
297
|
+
### Data Inclusion
|
|
298
|
+
|
|
299
|
+
To check that response contains expected data use `I.seeResponseContainsJson` method.
|
|
300
|
+
It will check the response data for partial match.
|
|
301
|
+
|
|
302
|
+
```js
|
|
303
|
+
I.seeResponseContainsJson({
|
|
304
|
+
user: {
|
|
305
|
+
email: 'user@user.com'
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
> ℹ️ If response is an array, it will check that at least one element in array matches JSON
|
|
311
|
+
|
|
312
|
+
To perform arbitrary assertions on a response object use `seeResponseValidByCallback`.
|
|
313
|
+
It allows you to do any kind of assertions by using `expect` from [`chai`](https://www.chaijs.com) library.
|
|
314
|
+
|
|
315
|
+
```js
|
|
316
|
+
I.seeResponseValidByCallback(({ data, status, expect }) => {
|
|
317
|
+
// we receive data and expect to combine them for good assertion
|
|
318
|
+
expect(data.users.length).to.be.gte(10);
|
|
319
|
+
})
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Extending JSONResponse
|
|
323
|
+
|
|
324
|
+
To add more assertions it is recommended to create a custom helper.
|
|
325
|
+
Inside it you can get access to latest JSON response:
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
// inside a custom helper
|
|
329
|
+
makeSomeCustomAssertion() {
|
|
330
|
+
const response = this.helpers.JSONResponse.response;
|
|
331
|
+
}
|
|
332
|
+
```
|