codeceptjs 3.6.0-beta.1.ai-healers → 3.6.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.
Files changed (130) hide show
  1. package/README.md +2 -2
  2. package/bin/codecept.js +2 -1
  3. package/docs/webapi/dontSeeTraffic.mustache +13 -0
  4. package/docs/webapi/flushNetworkTraffics.mustache +5 -0
  5. package/docs/webapi/grabRecordedNetworkTraffics.mustache +10 -0
  6. package/docs/webapi/seeTraffic.mustache +36 -0
  7. package/docs/webapi/startRecordingTraffic.mustache +8 -0
  8. package/docs/webapi/startRecordingWebSocketMessages.mustache +8 -0
  9. package/docs/webapi/stopRecordingTraffic.mustache +5 -0
  10. package/docs/webapi/stopRecordingWebSocketMessages.mustache +7 -0
  11. package/docs/webapi/waitForCookie.mustache +9 -0
  12. package/lib/actor.js +6 -3
  13. package/lib/command/dryRun.js +44 -13
  14. package/lib/helper/Appium.js +36 -12
  15. package/lib/helper/Expect.js +11 -8
  16. package/lib/helper/JSONResponse.js +8 -8
  17. package/lib/helper/MockServer.js +221 -0
  18. package/lib/helper/Playwright.js +107 -371
  19. package/lib/helper/Puppeteer.js +404 -71
  20. package/lib/helper/REST.js +4 -1
  21. package/lib/helper/WebDriver.js +189 -13
  22. package/lib/helper/errors/ElementAssertion.js +38 -0
  23. package/lib/helper/extras/PlaywrightReactVueLocator.js +6 -1
  24. package/lib/helper/network/actions.js +123 -0
  25. package/lib/helper/network/utils.js +187 -0
  26. package/lib/locator.js +36 -5
  27. package/lib/pause.js +4 -9
  28. package/lib/plugin/coverage.js +112 -99
  29. package/lib/step.js +3 -1
  30. package/package.json +49 -38
  31. package/typings/index.d.ts +19 -2
  32. package/typings/promiseBasedTypes.d.ts +505 -41
  33. package/typings/types.d.ts +531 -43
  34. package/docs/advanced.md +0 -351
  35. package/docs/ai.md +0 -365
  36. package/docs/api.md +0 -323
  37. package/docs/basics.md +0 -979
  38. package/docs/bdd.md +0 -539
  39. package/docs/best.md +0 -237
  40. package/docs/books.md +0 -37
  41. package/docs/bootstrap.md +0 -135
  42. package/docs/build/AI.js +0 -124
  43. package/docs/build/ApiDataFactory.js +0 -410
  44. package/docs/build/Appium.js +0 -2027
  45. package/docs/build/Expect.js +0 -422
  46. package/docs/build/FileSystem.js +0 -228
  47. package/docs/build/GraphQL.js +0 -229
  48. package/docs/build/GraphQLDataFactory.js +0 -309
  49. package/docs/build/JSONResponse.js +0 -338
  50. package/docs/build/Mochawesome.js +0 -71
  51. package/docs/build/Nightmare.js +0 -2152
  52. package/docs/build/OpenAI.js +0 -126
  53. package/docs/build/Playwright.js +0 -5110
  54. package/docs/build/Protractor.js +0 -2706
  55. package/docs/build/Puppeteer.js +0 -3905
  56. package/docs/build/REST.js +0 -344
  57. package/docs/build/TestCafe.js +0 -2125
  58. package/docs/build/WebDriver.js +0 -4240
  59. package/docs/changelog.md +0 -2572
  60. package/docs/commands.md +0 -266
  61. package/docs/community-helpers.md +0 -58
  62. package/docs/configuration.md +0 -157
  63. package/docs/continuous-integration.md +0 -22
  64. package/docs/custom-helpers.md +0 -306
  65. package/docs/data.md +0 -379
  66. package/docs/detox.md +0 -235
  67. package/docs/docker.md +0 -136
  68. package/docs/email.md +0 -183
  69. package/docs/examples.md +0 -149
  70. package/docs/heal.md +0 -186
  71. package/docs/helpers/ApiDataFactory.md +0 -266
  72. package/docs/helpers/Appium.md +0 -1374
  73. package/docs/helpers/Detox.md +0 -586
  74. package/docs/helpers/Expect.md +0 -275
  75. package/docs/helpers/FileSystem.md +0 -152
  76. package/docs/helpers/GraphQL.md +0 -151
  77. package/docs/helpers/GraphQLDataFactory.md +0 -226
  78. package/docs/helpers/JSONResponse.md +0 -254
  79. package/docs/helpers/Mochawesome.md +0 -8
  80. package/docs/helpers/MockRequest.md +0 -377
  81. package/docs/helpers/Nightmare.md +0 -1305
  82. package/docs/helpers/OpenAI.md +0 -70
  83. package/docs/helpers/Playwright.md +0 -2759
  84. package/docs/helpers/Polly.md +0 -44
  85. package/docs/helpers/Protractor.md +0 -1769
  86. package/docs/helpers/Puppeteer-firefox.md +0 -86
  87. package/docs/helpers/Puppeteer.md +0 -2317
  88. package/docs/helpers/REST.md +0 -218
  89. package/docs/helpers/TestCafe.md +0 -1321
  90. package/docs/helpers/WebDriver.md +0 -2547
  91. package/docs/hooks.md +0 -340
  92. package/docs/index.md +0 -111
  93. package/docs/installation.md +0 -75
  94. package/docs/internal-api.md +0 -266
  95. package/docs/locators.md +0 -339
  96. package/docs/mobile-react-native-locators.md +0 -67
  97. package/docs/mobile.md +0 -338
  98. package/docs/pageobjects.md +0 -291
  99. package/docs/parallel.md +0 -400
  100. package/docs/playwright.md +0 -632
  101. package/docs/plugins.md +0 -1247
  102. package/docs/puppeteer.md +0 -316
  103. package/docs/quickstart.md +0 -162
  104. package/docs/react.md +0 -70
  105. package/docs/reports.md +0 -392
  106. package/docs/secrets.md +0 -36
  107. package/docs/shadow.md +0 -68
  108. package/docs/shared/keys.mustache +0 -31
  109. package/docs/shared/react.mustache +0 -1
  110. package/docs/testcafe.md +0 -174
  111. package/docs/translation.md +0 -247
  112. package/docs/tutorial.md +0 -271
  113. package/docs/typescript.md +0 -180
  114. package/docs/ui.md +0 -59
  115. package/docs/videos.md +0 -28
  116. package/docs/visual.md +0 -202
  117. package/docs/vue.md +0 -143
  118. package/docs/webdriver.md +0 -701
  119. package/docs/wiki/Books-&-Posts.md +0 -27
  120. package/docs/wiki/Community-Helpers-&-Plugins.md +0 -53
  121. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -61
  122. package/docs/wiki/Examples.md +0 -145
  123. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
  124. package/docs/wiki/Home.md +0 -16
  125. package/docs/wiki/Migration-to-Appium-v2---CodeceptJS.md +0 -83
  126. package/docs/wiki/Release-Process.md +0 -24
  127. package/docs/wiki/Roadmap.md +0 -23
  128. package/docs/wiki/Tests.md +0 -1393
  129. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
  130. package/docs/wiki/Videos.md +0 -19
package/docs/heal.md DELETED
@@ -1,186 +0,0 @@
1
- # Self-Healing Tests
2
-
3
- Browser and Mobile tests can fail for vareity of reasons. However, on a big projects there are about 5-10 causes of flaky tests. The more you work and understand your end-to-end tests the more you learn patterns of failure. And after the research you understand how a test could have been fixed: to reload a page, to click that button once again, restart API request. If by looking into a failure you understand what, as a user, you would do to fix that error, then maybe you could teach your tests to heal themselves.
4
-
5
- ## What is Healing
6
-
7
- **Healing defines the way how a test reacts to failure**. You can define multiple healing recipes that could take all needed information: error message, failed test, step, page URL, HTML, etc. A healing recipe can perform some action to fix the failing test on the fly and continue its execution.
8
-
9
- ![](/img/healing.png)
10
-
11
- Let's start with an example the most basic healing recipe. If after a click test has failed, try to reload page, and continue.
12
-
13
- ```js
14
- heal.addRecipe('reload', {
15
- priority: 10,
16
- steps: ['click'],
17
- fn: async () => {
18
- return ({ I }) => {
19
- I.refreshPage();
20
- };
21
- },
22
- });
23
- ```
24
-
25
- Sure, this won't always work and probably won't be useful on every project. But let's follow the idea: if a click has failed, probably the button is not on a page, maybe it is an issue of rendering, maybe some other element overlapped our button, so if we try to reload page we can continue test execution. At least, this is what manual QA would do if they will run the following test in a browser. They will try to reload a page before reporting "it has failed".
26
-
27
- So if it is a long end-2-end test that implements user journey, it is more valuable to continue its execution when possible, then fixing a minor issues like overlapping elements. Healing like this can improve the stability of a test.
28
-
29
- The example above is only one way a test can be healed. But you can define as many heal recipes as you like. What heal recipe would be effective in your case is depends on a system you test, so **there are no pre-defined heal recipes**.
30
-
31
- ## Healing Patterns
32
-
33
- There are some ideas where healing can be useful to you:
34
-
35
- * **Networking**. If a test depends on a remote resource, and fails because this resource is not available, you may try to send API request to restore that resource before throwing an error.
36
- * **Data Consistency**. A test may fail because you noticed the data glitch in a system. Instead of failing a test you may try to clean up the data and try again to proceed.
37
- * **UI Change**. If there is a planned UI migration of a component, for instance Button was changed to Dropdown. You can prepare test so if it fails clicking Button it can try to do so with Dropdown.
38
- * **Do it again**. If you know, that going one step back and trying to do same actions may solve the issue, you can do so from healers. For instance, a modal didn't render correctly, so you can close it and try to click to open it again.
39
-
40
- ## Healing vs Retries
41
-
42
- Unlike retries heal recipes has following benefits:
43
-
44
- * Heal recipes are **declarative**, they are not added directly into into the test code. This keeps test clean and scenario-focused,
45
- * Retry can only re-run failed step(s), but heal recipe can **perform wide set of actions**
46
- * Heal recipe **can react to any step of any test**. So if you catch a common error and you can heal it, you won't need to guess where it can be thrown.
47
-
48
- ## How to Start Healing
49
-
50
- To enable healing, you need to define healing recipes and enable heal plugin.
51
-
52
- Create basic healing recipes using this command:
53
-
54
- ```
55
- npx codeceptjs geenrate:heal
56
- ```
57
-
58
- or
59
-
60
- ```
61
- npx codeceptjs gr
62
- ```
63
-
64
- this will generate `recipes.js` (or `recipes.ts`) in the root directory. Provided default recipe include [AI healing](#ai-healing) and `clickAndType` recipe that replaces `fillField` with `click`+`type`. Use them as examples to write your own heal recipes that will fit for application you are testing.
65
-
66
- Require `recipes` file and add `heal` plugin to `codecept.conf` file:
67
-
68
- ```js
69
-
70
- require('./heal')
71
-
72
- exports.config = {
73
- // ...
74
- plugins: {
75
- heal: {
76
- enabled: true
77
- }
78
- }
79
- }
80
- ```
81
-
82
- > Please note that, healing has no sense while developing tests, so it won't work in `--debug` mode.
83
-
84
- ## Writing Recipes
85
-
86
- Custom heal recipes can be added by running `heal.addRecipe()` function. By default it should be added to `recipes.js` (or `recipes.ts`) file.
87
-
88
- Let's see what recipe consist of:
89
-
90
- ```js
91
- heal.addRecipe('reloadPageOnUserAccount', {
92
- // recipe priority
93
- // which recipe should be tried first
94
- priority: 10,
95
-
96
- // an array of steps which may cause the error
97
- // after which a recipe should be activate
98
- steps: [
99
- 'click',
100
- ],
101
-
102
- // if you need some additional information like URL of a page,
103
- // or its HTML, you can add this context to healing function by
104
- // defining `prepare` list of variable
105
- prepare: {
106
- url: ({ I }) => I.grabCurrentUrl(),
107
- html: ({ I }) => I.grabHTMLFrom('body'),
108
- // don't add variables that you won't use inside the recipe
109
- },
110
-
111
- // probably we want to execute recipes only on some tests
112
- // so you can set a string or regex which will check if a test title matches the name
113
- // in this case we execute recipe only on tests that have "@flaky" in their name
114
- grep: '@flaky',
115
-
116
- // function to launch to heal the
117
- fn: async ({
118
- // standard context variables
119
- step, test, error, prevSteps,
120
-
121
- // variables coming from prepare function
122
- html, url,
123
-
124
- }) => {
125
- const stepArgs = step.args;
126
-
127
- // at this point we can decide, should we provide a healing recipe or not
128
- // for instance, if URL is not the one we can heal at, we should not provide any recipes
129
- if (!url.includes('/user/acccount')) return;
130
-
131
- // otherwise we return a function that will be executed
132
- return ({ I }) => {
133
- // this is a very basic example action
134
- // probably you should do something more sophisticated
135
- // to heal the test
136
- I.reloadPage();
137
- I.wait(1);
138
- };
139
- },
140
- });
141
- ```
142
-
143
- Let's briefly sum up the properties of a recipe:
144
-
145
- * `grep` - selects tests by their name to apply heal to
146
- * `steps` - defines on which steps a recipe should react
147
- * `priority` - sets the order of recipes being applied
148
- * `prepare` - declare variables from a context, which can be used for healing
149
- * `fn` - a function to be applied for healing. It takes all context params: `test`, `step`, `error`, `prevSteps` and returns return either a function or a markdown text with recipes (used by AI healers). If no recipes match the context should not return anything;
150
-
151
-
152
- ## AI Healing
153
-
154
- AI can be used to heal failed tests. Large Language Models can analyze HTML of a failed test and provide a suggestion what actions should be performed instead. This can be helpful when running tests on CI as AI can make basic decisions to stabilize failing tests.
155
-
156
- > Use **OpenAI, Azure OpenAI, Claude**, or any of other LLM that can take a prompt, analyze request and provide valid JS code which can be executed by CodeceptJS as a healing suggestion.
157
-
158
- AI healing recipe is created within `recipes.js` file:
159
-
160
- ```js
161
- heal.addRecipe('ai', {
162
- priority: 10,
163
- prepare: {
164
- html: ({ I }) => I.grabHTMLFrom('body'),
165
- },
166
- steps: [
167
- 'click',
168
- 'fillField',
169
- 'appendField',
170
- 'selectOption',
171
- 'attachFile',
172
- 'checkOption',
173
- 'uncheckOption',
174
- 'doubleClick',
175
- ],
176
- fn: async (args) => {
177
- return ai.healFailedStep(args);
178
- },
179
- });
180
- ```
181
-
182
- As you usee, it will be activated on failed steps and will use HTML of a page as additional information. The prompt, error, and the HTML will be sent to AI provider you configured.
183
-
184
- Learn more how you can [configure AI provider](./ai).
185
-
186
- To activate the AI healer don't forget to run tests with `--ai` flag.
@@ -1,266 +0,0 @@
1
- ---
2
- permalink: /helpers/ApiDataFactory
3
- editLink: false
4
- sidebar: auto
5
- title: ApiDataFactory
6
- ---
7
-
8
- <!-- Generated by documentation.js. Update this documentation by updating the source code. -->
9
-
10
- ## ApiDataFactory
11
-
12
- **Extends Helper**
13
-
14
- Helper for managing remote data using REST API.
15
- Uses data generators like [rosie][1] or factory girl to create new record.
16
-
17
- By defining a factory you set the rules of how data is generated.
18
- This data will be saved on server via REST API and deleted in the end of a test.
19
-
20
- ## Use Case
21
-
22
- Acceptance tests interact with a websites using UI and real browser.
23
- There is no way to create data for a specific test other than from user interface.
24
- That makes tests slow and fragile. Instead of testing a single feature you need to follow all creation/removal process.
25
-
26
- This helper solves this problem.
27
- Most of web application have API, and it can be used to create and delete test records.
28
- By combining REST API with Factories you can easily create records for tests:
29
-
30
- ```js
31
- I.have('user', { login: 'davert', email: 'davert@mail.com' });
32
- let id = await I.have('post', { title: 'My first post'});
33
- I.haveMultiple('comment', 3, {post_id: id});
34
- ```
35
-
36
- To make this work you need
37
-
38
- 1. REST API endpoint which allows to perform create / delete requests and
39
- 2. define data generation rules
40
-
41
- ### Setup
42
-
43
- Install [Rosie][1] and [Faker][2] libraries.
44
-
45
- ```sh
46
- npm i rosie @faker-js/faker --save-dev
47
- ```
48
-
49
- Create a factory file for a resource.
50
-
51
- See the example for Posts factories:
52
-
53
- ```js
54
- // tests/factories/posts.js
55
-
56
- const { Factory } = require('rosie');
57
- const { faker } = require('@faker-js/faker');
58
-
59
- module.exports = new Factory()
60
- // no need to set id, it will be set by REST API
61
- .attr('author', () => faker.name.findName())
62
- .attr('title', () => faker.lorem.sentence())
63
- .attr('body', () => faker.lorem.paragraph());
64
- ```
65
-
66
- For more options see [rosie documentation][1].
67
-
68
- Then configure ApiDataHelper to match factories and REST API:
69
-
70
- ### Configuration
71
-
72
- ApiDataFactory has following config options:
73
-
74
- - `endpoint`: base URL for the API to send requests to.
75
- - `cleanup` (default: true): should inserted records be deleted up after tests
76
- - `factories`: list of defined factories
77
- - `returnId` (default: false): return id instead of a complete response when creating items.
78
- - `headers`: list of headers
79
- - `REST`: configuration for REST requests
80
-
81
- See the example:
82
-
83
- ```js
84
- ApiDataFactory: {
85
- endpoint: "http://user.com/api",
86
- cleanup: true,
87
- headers: {
88
- 'Content-Type': 'application/json',
89
- 'Accept': 'application/json',
90
- },
91
- factories: {
92
- post: {
93
- uri: "/posts",
94
- factory: "./factories/post",
95
- },
96
- comment: {
97
- factory: "./factories/comment",
98
- create: { post: "/comments/create" },
99
- delete: { post: "/comments/delete/{id}" },
100
- fetchId: (data) => data.result.id
101
- }
102
- }
103
- }
104
- ```
105
-
106
- It is required to set REST API `endpoint` which is the baseURL for all API requests.
107
- Factory file is expected to be passed via `factory` option.
108
-
109
- This Helper uses [REST][3] helper and accepts its configuration in "REST" section.
110
- For instance, to set timeout you should add:
111
-
112
- ```js
113
- "ApiDataFactory": {
114
- "REST": {
115
- "timeout": "100000",
116
- }
117
- }
118
- ```
119
-
120
- ### Requests
121
-
122
- By default to create a record ApiDataFactory will use endpoint and plural factory name:
123
-
124
- - create: `POST {endpoint}/{resource} data`
125
- - delete: `DELETE {endpoint}/{resource}/id`
126
-
127
- Example (`endpoint`: `http://app.com/api`):
128
-
129
- - create: POST request to `http://app.com/api/users`
130
- - delete: DELETE request to `http://app.com/api/users/1`
131
-
132
- This behavior can be configured with following options:
133
-
134
- - `uri`: set different resource uri. Example: `uri: account` => `http://app.com/api/account`.
135
- - `create`: override create options. Expected format: `{ method: uri }`. Example: `{ "post": "/users/create" }`
136
- - `delete`: override delete options. Expected format: `{ method: uri }`. Example: `{ "post": "/users/delete/{id}" }`
137
-
138
- Requests can also be overridden with a function which returns [axois request config][4].
139
-
140
- ```js
141
- create: (data) => ({ method: 'post', url: '/posts', data }),
142
- delete: (id) => ({ method: 'delete', url: '/posts', data: { id } })
143
- ```
144
-
145
- Requests can be updated on the fly by using `onRequest` function. For instance, you can pass in current session from a cookie.
146
-
147
- ```js
148
- onRequest: async (request) => {
149
- // using global codeceptjs instance
150
- let cookie = await codeceptjs.container.helpers('WebDriver').grabCookie('session');
151
- request.headers = { Cookie: `session=${cookie.value}` };
152
- }
153
- ```
154
-
155
- ### Responses
156
-
157
- By default `I.have()` returns a promise with a created data:
158
-
159
- ```js
160
- let client = await I.have('client');
161
- ```
162
-
163
- Ids of created records are collected and used in the end of a test for the cleanup.
164
- If you need to receive `id` instead of full response enable `returnId` in a helper config:
165
-
166
- ```js
167
- // returnId: false
168
- let clientId = await I.have('client');
169
- // clientId == 1
170
-
171
- // returnId: true
172
- let clientId = await I.have('client');
173
- // client == { name: 'John', email: 'john@snow.com' }
174
- ```
175
-
176
- By default `id` property of response is taken. This behavior can be changed by setting `fetchId` function in a factory config.
177
-
178
- ```js
179
- factories: {
180
- post: {
181
- uri: "/posts",
182
- factory: "./factories/post",
183
- fetchId: (data) => data.result.posts[0].id
184
- }
185
- }
186
- ```
187
-
188
- ## Methods
189
-
190
- ### Parameters
191
-
192
- - `config`
193
-
194
- ### _requestCreate
195
-
196
- Executes request to create a record in API.
197
- Can be replaced from a in custom helper.
198
-
199
- #### Parameters
200
-
201
- - `factory` **any**
202
- - `data` **any**
203
-
204
- ### _requestDelete
205
-
206
- Executes request to delete a record in API
207
- Can be replaced from a custom helper.
208
-
209
- #### Parameters
210
-
211
- - `factory` **any**
212
- - `id` **any**
213
-
214
- ### have
215
-
216
- Generates a new record using factory and saves API request to store it.
217
-
218
- ```js
219
- // create a user
220
- I.have('user');
221
- // create user with defined email
222
- // and receive it when inside async function
223
- const user = await I.have('user', { email: 'user@user.com'});
224
- // create a user with options that will not be included in the final request
225
- I.have('user', { }, { age: 33, height: 55 })
226
- ```
227
-
228
- #### Parameters
229
-
230
- - `factory` **any** factory to use
231
- - `params` **any?** predefined parameters
232
- - `options` **any?** options for programmatically generate the attributes
233
-
234
- Returns **[Promise][5]&lt;any>**
235
-
236
- ### haveMultiple
237
-
238
- Generates bunch of records and saves multiple API requests to store them.
239
-
240
- ```js
241
- // create 3 posts
242
- I.haveMultiple('post', 3);
243
-
244
- // create 3 posts by one author
245
- I.haveMultiple('post', 3, { author: 'davert' });
246
-
247
- // create 3 posts by one author with options
248
- I.haveMultiple('post', 3, { author: 'davert' }, { publish_date: '01.01.1997' });
249
- ```
250
-
251
- #### Parameters
252
-
253
- - `factory` **any**
254
- - `times` **any**
255
- - `params` **any?**
256
- - `options` **any?**
257
-
258
- [1]: https://github.com/rosiejs/rosie
259
-
260
- [2]: https://www.npmjs.com/package/faker
261
-
262
- [3]: http://codecept.io/helpers/REST/
263
-
264
- [4]: https://github.com/axios/axios#request-config
265
-
266
- [5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise