codeceptjs 4.0.0-beta.4 → 4.0.0-beta.5
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 +134 -119
- package/bin/codecept.js +12 -2
- package/bin/test-server.js +53 -0
- package/docs/webapi/clearCookie.mustache +1 -1
- package/lib/actor.js +66 -102
- package/lib/ai.js +130 -121
- package/lib/assert/empty.js +3 -5
- package/lib/assert/equal.js +4 -7
- package/lib/assert/include.js +4 -6
- package/lib/assert/throws.js +2 -4
- package/lib/assert/truth.js +2 -2
- package/lib/codecept.js +139 -87
- package/lib/command/check.js +201 -0
- package/lib/command/configMigrate.js +2 -4
- package/lib/command/definitions.js +8 -26
- package/lib/command/generate.js +10 -14
- package/lib/command/gherkin/snippets.js +75 -73
- package/lib/command/gherkin/steps.js +1 -1
- package/lib/command/info.js +42 -8
- package/lib/command/init.js +13 -12
- package/lib/command/interactive.js +10 -2
- package/lib/command/list.js +1 -1
- package/lib/command/run-multiple/chunk.js +48 -45
- package/lib/command/run-multiple.js +12 -35
- package/lib/command/run-workers.js +21 -58
- package/lib/command/utils.js +5 -6
- package/lib/command/workers/runTests.js +262 -220
- package/lib/container.js +386 -238
- package/lib/data/context.js +10 -13
- package/lib/data/dataScenarioConfig.js +8 -8
- package/lib/data/dataTableArgument.js +6 -6
- package/lib/data/table.js +5 -11
- package/lib/effects.js +223 -0
- package/lib/element/WebElement.js +327 -0
- package/lib/els.js +158 -0
- package/lib/event.js +21 -17
- package/lib/heal.js +88 -80
- package/lib/helper/AI.js +2 -1
- package/lib/helper/ApiDataFactory.js +3 -6
- package/lib/helper/Appium.js +47 -51
- package/lib/helper/FileSystem.js +3 -3
- package/lib/helper/GraphQLDataFactory.js +3 -3
- package/lib/helper/JSONResponse.js +75 -37
- package/lib/helper/Mochawesome.js +31 -9
- package/lib/helper/Nightmare.js +35 -53
- package/lib/helper/Playwright.js +262 -267
- package/lib/helper/Protractor.js +54 -77
- package/lib/helper/Puppeteer.js +246 -260
- package/lib/helper/REST.js +5 -17
- package/lib/helper/TestCafe.js +21 -44
- package/lib/helper/WebDriver.js +151 -170
- package/lib/helper/extras/Popup.js +22 -22
- package/lib/helper/testcafe/testcafe-utils.js +26 -27
- package/lib/listener/emptyRun.js +55 -0
- package/lib/listener/exit.js +7 -10
- package/lib/listener/{retry.js → globalRetry.js} +5 -5
- package/lib/listener/globalTimeout.js +165 -0
- package/lib/listener/helpers.js +15 -15
- package/lib/listener/mocha.js +1 -1
- package/lib/listener/result.js +12 -0
- package/lib/listener/retryEnhancer.js +85 -0
- package/lib/listener/steps.js +32 -18
- package/lib/listener/store.js +20 -0
- package/lib/mocha/asyncWrapper.js +231 -0
- package/lib/{interfaces → mocha}/bdd.js +3 -3
- package/lib/mocha/cli.js +308 -0
- package/lib/mocha/factory.js +104 -0
- package/lib/{interfaces → mocha}/featureConfig.js +32 -12
- package/lib/{interfaces → mocha}/gherkin.js +26 -28
- package/lib/mocha/hooks.js +112 -0
- package/lib/mocha/index.js +12 -0
- package/lib/mocha/inject.js +29 -0
- package/lib/{interfaces → mocha}/scenarioConfig.js +31 -7
- package/lib/mocha/suite.js +82 -0
- package/lib/mocha/test.js +181 -0
- package/lib/mocha/types.d.ts +42 -0
- package/lib/mocha/ui.js +232 -0
- package/lib/output.js +82 -62
- package/lib/pause.js +160 -138
- package/lib/plugin/analyze.js +396 -0
- package/lib/plugin/auth.js +435 -0
- package/lib/plugin/autoDelay.js +8 -8
- package/lib/plugin/autoLogin.js +3 -338
- package/lib/plugin/commentStep.js +6 -1
- package/lib/plugin/coverage.js +10 -19
- package/lib/plugin/customLocator.js +3 -3
- package/lib/plugin/customReporter.js +52 -0
- package/lib/plugin/eachElement.js +1 -1
- package/lib/plugin/fakerTransform.js +1 -1
- package/lib/plugin/heal.js +36 -9
- package/lib/plugin/htmlReporter.js +1947 -0
- package/lib/plugin/pageInfo.js +140 -0
- package/lib/plugin/retryFailedStep.js +17 -18
- package/lib/plugin/retryTo.js +2 -113
- package/lib/plugin/screenshotOnFail.js +17 -58
- package/lib/plugin/selenoid.js +15 -35
- package/lib/plugin/standardActingHelpers.js +4 -1
- package/lib/plugin/stepByStepReport.js +56 -17
- package/lib/plugin/stepTimeout.js +5 -12
- package/lib/plugin/subtitles.js +4 -4
- package/lib/plugin/tryTo.js +3 -102
- package/lib/plugin/wdio.js +8 -10
- package/lib/recorder.js +155 -124
- package/lib/rerun.js +43 -42
- package/lib/result.js +161 -0
- package/lib/secret.js +1 -1
- package/lib/step/base.js +239 -0
- package/lib/step/comment.js +10 -0
- package/lib/step/config.js +50 -0
- package/lib/step/func.js +46 -0
- package/lib/step/helper.js +50 -0
- package/lib/step/meta.js +99 -0
- package/lib/step/record.js +74 -0
- package/lib/step/retry.js +11 -0
- package/lib/step/section.js +55 -0
- package/lib/step.js +21 -332
- package/lib/steps.js +50 -0
- package/lib/store.js +37 -5
- package/lib/template/heal.js +2 -11
- package/lib/test-server.js +323 -0
- package/lib/timeout.js +66 -0
- package/lib/utils.js +351 -218
- package/lib/within.js +75 -55
- package/lib/workerStorage.js +2 -1
- package/lib/workers.js +386 -276
- package/package.json +76 -70
- package/translations/de-DE.js +4 -3
- package/translations/fr-FR.js +4 -3
- package/translations/index.js +1 -0
- package/translations/it-IT.js +4 -3
- package/translations/ja-JP.js +4 -3
- package/translations/nl-NL.js +76 -0
- package/translations/pl-PL.js +4 -3
- package/translations/pt-BR.js +4 -3
- package/translations/ru-RU.js +4 -3
- package/translations/utils.js +9 -0
- package/translations/zh-CN.js +4 -3
- package/translations/zh-TW.js +4 -3
- package/typings/index.d.ts +188 -186
- package/typings/promiseBasedTypes.d.ts +18 -705
- package/typings/types.d.ts +301 -804
- package/lib/cli.js +0 -256
- package/lib/helper/ExpectHelper.js +0 -391
- package/lib/helper/SoftExpectHelper.js +0 -381
- package/lib/listener/artifacts.js +0 -19
- package/lib/listener/timeout.js +0 -109
- package/lib/mochaFactory.js +0 -113
- package/lib/plugin/debugErrors.js +0 -67
- package/lib/scenario.js +0 -224
- package/lib/ui.js +0 -236
package/README.md
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
[](https://stand-with-ukraine.pp.ua)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
3
|
[<img src="https://img.shields.io/badge/slack-@codeceptjs-purple.svg?logo=slack">](https://join.slack.com/t/codeceptjs/shared_invite/enQtMzA5OTM4NDM2MzA4LWE4MThhN2NmYTgxNTU5MTc4YzAyYWMwY2JkMmZlYWI5MWQ2MDM5MmRmYzZmYmNiNmY5NTAzM2EwMGIwOTNhOGQ) [<img src="https://img.shields.io/badge/discourse-codeceptjs-purple">](https://codecept.discourse.group) [![NPM version][npm-image]][npm-url] [<img src="https://img.shields.io/badge/dockerhub-images-blue.svg?logo=codeceptjs">](https://hub.docker.com/r/codeceptjs/codeceptjs)
|
|
6
|
-
[](https://github.com/codeceptjs/CodeceptJS/edit/3.x/docs/ai.md) [](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
|
|
4
|
+
[](https://github.com/codeceptjs/CodeceptJS/edit/3.x/docs/ai.md) [](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
|
|
7
5
|
|
|
8
|
-
Build Status
|
|
6
|
+
## Build Status
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Web
|
|
14
|
-
[](https://github.com/codeceptjs/CodeceptJS/actions/workflows/testcafe.yml)
|
|
8
|
+
| Type | Engine | Status |
|
|
9
|
+
| --------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
10
|
+
| 🌐 Web | Playwright | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/playwright.yml) |
|
|
11
|
+
| 🌐 Web | Puppeteer | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/puppeteer.yml) |
|
|
12
|
+
| 🌐 Web | WebDriver | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/webdriver.yml) |
|
|
13
|
+
| 🌐 Web | TestCafe | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/testcafe.yml) |
|
|
14
|
+
| 📱 Mobile | Appium | [](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appium_Android.yml) |
|
|
18
15
|
|
|
19
16
|
# CodeceptJS [](https://stand-with-ukraine.pp.ua)
|
|
20
17
|
|
|
@@ -27,28 +24,28 @@ It abstracts browser interaction to simple steps that are written from a user's
|
|
|
27
24
|
A simple test that verifies the "Welcome" text is present on a main page of a site will look like:
|
|
28
25
|
|
|
29
26
|
```js
|
|
30
|
-
Feature('CodeceptJS demo')
|
|
27
|
+
Feature('CodeceptJS demo')
|
|
31
28
|
|
|
32
29
|
Scenario('check Welcome page on site', ({ I }) => {
|
|
33
|
-
I.amOnPage('/')
|
|
34
|
-
I.see('Welcome')
|
|
35
|
-
})
|
|
30
|
+
I.amOnPage('/')
|
|
31
|
+
I.see('Welcome')
|
|
32
|
+
})
|
|
36
33
|
```
|
|
37
34
|
|
|
38
35
|
CodeceptJS tests are:
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
- **Synchronous**. You don't need to care about callbacks or promises or test scenarios which are linear. But, your tests should be linear.
|
|
38
|
+
- Written from **user's perspective**. Every action is a method of `I`. That makes test easy to read, write and maintain even for non-tech persons.
|
|
39
|
+
- Backend **API agnostic**. We don't know which WebDriver implementation is running this test.
|
|
43
40
|
|
|
44
41
|
CodeceptJS uses **Helper** modules to provide actions to `I` object. Currently, CodeceptJS has these helpers:
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
- [**Playwright**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Playwright.md) - is a Node library to automate the Chromium, WebKit and Firefox browsers with a single API.
|
|
44
|
+
- [**Puppeteer**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Puppeteer.md) - uses Google Chrome's Puppeteer for fast headless testing.
|
|
45
|
+
- [**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
|
+
- [**TestCafe**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/TestCafe.md) - cheap and fast cross-browser test automation.
|
|
47
|
+
- [**Appium**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Appium.md) - for **mobile testing** with Appium
|
|
48
|
+
- [**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.
|
|
52
49
|
|
|
53
50
|
And more to come...
|
|
54
51
|
|
|
@@ -58,17 +55,18 @@ CodeceptJS is a successor of [Codeception](http://codeception.com), a popular fu
|
|
|
58
55
|
With CodeceptJS your scenario-driven functional and acceptance tests will be as simple and clean as they can be.
|
|
59
56
|
You don't need to worry about asynchronous nature of NodeJS or about various APIs of Playwright, Selenium, Puppeteer, TestCafe, etc. as CodeceptJS unifies them and makes them work as they are synchronous.
|
|
60
57
|
|
|
61
|
-
|
|
62
58
|
## Features
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
59
|
+
|
|
60
|
+
- 🪄 **AI-powered** with GPT features to assist and heal failing tests.
|
|
61
|
+
- ☕ Based on [Mocha](https://mochajs.org/) testing framework.
|
|
62
|
+
- 💼 Designed for scenario driven acceptance testing in BDD-style.
|
|
63
|
+
- 💻 Uses ES6 natively without transpiler.
|
|
64
|
+
- Also plays nice with TypeScript.
|
|
65
|
+
- </> Smart locators: use names, labels, matching text, CSS or XPath to locate elements.
|
|
66
|
+
- 🌐 Interactive debugging shell: pause test at any point and try different commands in a browser.
|
|
67
|
+
- ⚡ **Parallel testing** with dynamic test pooling for optimal load balancing and performance.
|
|
68
|
+
- 📊 **Built-in HTML Reporter** with interactive dashboard, step-by-step execution details, and comprehensive test analytics.
|
|
69
|
+
- Easily create tests, pageobjects, stepobjects with CLI generators.
|
|
72
70
|
|
|
73
71
|
## Installation
|
|
74
72
|
|
|
@@ -105,7 +103,8 @@ npx codeceptjs def .
|
|
|
105
103
|
Later you can even automagically update Type Definitions to include your own custom [helpers methods](docs/helpers.md).
|
|
106
104
|
|
|
107
105
|
Note:
|
|
108
|
-
|
|
106
|
+
|
|
107
|
+
- CodeceptJS requires Node.js version `12+` or later.
|
|
109
108
|
|
|
110
109
|
## Usage
|
|
111
110
|
|
|
@@ -116,18 +115,18 @@ Learn CodeceptJS by examples. Let's assume we have CodeceptJS installed and WebD
|
|
|
116
115
|
Let's see how we can handle basic form testing:
|
|
117
116
|
|
|
118
117
|
```js
|
|
119
|
-
Feature('CodeceptJS Demonstration')
|
|
118
|
+
Feature('CodeceptJS Demonstration')
|
|
120
119
|
|
|
121
120
|
Scenario('test some forms', ({ I }) => {
|
|
122
|
-
I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation')
|
|
123
|
-
I.fillField('Email', 'hello@world.com')
|
|
124
|
-
I.fillField('Password', secret('123456'))
|
|
125
|
-
I.checkOption('Active')
|
|
126
|
-
I.checkOption('Male')
|
|
127
|
-
I.click('Create User')
|
|
128
|
-
I.see('User is valid')
|
|
129
|
-
I.dontSeeInCurrentUrl('/documentation')
|
|
130
|
-
})
|
|
121
|
+
I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation')
|
|
122
|
+
I.fillField('Email', 'hello@world.com')
|
|
123
|
+
I.fillField('Password', secret('123456'))
|
|
124
|
+
I.checkOption('Active')
|
|
125
|
+
I.checkOption('Male')
|
|
126
|
+
I.click('Create User')
|
|
127
|
+
I.see('User is valid')
|
|
128
|
+
I.dontSeeInCurrentUrl('/documentation')
|
|
129
|
+
})
|
|
131
130
|
```
|
|
132
131
|
|
|
133
132
|
All actions are performed by `I` object; assertions functions start with `see` function.
|
|
@@ -172,11 +171,11 @@ The same way you can locate element by name, `CSS` or `XPath` locators in tests:
|
|
|
172
171
|
|
|
173
172
|
```js
|
|
174
173
|
// by name
|
|
175
|
-
I.fillField('user_basic[email]', 'hello@world.com')
|
|
174
|
+
I.fillField('user_basic[email]', 'hello@world.com')
|
|
176
175
|
// by CSS
|
|
177
|
-
I.fillField('#user_basic_email', 'hello@world.com')
|
|
176
|
+
I.fillField('#user_basic_email', 'hello@world.com')
|
|
178
177
|
// don't make us guess locator type, specify it
|
|
179
|
-
I.fillField({css: '#user_basic_email'}, 'hello@world.com')
|
|
178
|
+
I.fillField({ css: '#user_basic_email' }, 'hello@world.com')
|
|
180
179
|
```
|
|
181
180
|
|
|
182
181
|
Other methods like `checkOption`, and `click` work in a similar manner. They can take labels or CSS or XPath locators to find elements to interact.
|
|
@@ -187,9 +186,9 @@ Assertions start with `see` or `dontSee` prefix. In our case we are asserting th
|
|
|
187
186
|
However, we can narrow the search to particular element by providing a second parameter:
|
|
188
187
|
|
|
189
188
|
```js
|
|
190
|
-
I.see('User is valid')
|
|
189
|
+
I.see('User is valid')
|
|
191
190
|
// better to specify context:
|
|
192
|
-
I.see('User is valid', '.alert-success')
|
|
191
|
+
I.see('User is valid', '.alert-success')
|
|
193
192
|
```
|
|
194
193
|
|
|
195
194
|
In this case 'User is valid' string will be searched only inside elements located by CSS `.alert-success`.
|
|
@@ -200,13 +199,13 @@ In case you need to return a value from a webpage and use it directly in test, y
|
|
|
200
199
|
They are expected to be used inside `async/await` functions, and their results will be available in test:
|
|
201
200
|
|
|
202
201
|
```js
|
|
203
|
-
Feature('CodeceptJS Demonstration')
|
|
202
|
+
Feature('CodeceptJS Demonstration')
|
|
204
203
|
|
|
205
204
|
Scenario('test page title', async ({ I }) => {
|
|
206
|
-
I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation')
|
|
207
|
-
const title = await I.grabTitle()
|
|
208
|
-
I.expectEqual(title, 'Example application with SimpleForm and Twitter Bootstrap')
|
|
209
|
-
})
|
|
205
|
+
I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation')
|
|
206
|
+
const title = await I.grabTitle()
|
|
207
|
+
I.expectEqual(title, 'Example application with SimpleForm and Twitter Bootstrap') // Avaiable with Expect helper. -> https://codecept.io/helpers/Expect/
|
|
208
|
+
})
|
|
210
209
|
```
|
|
211
210
|
|
|
212
211
|
The same way you can grab text, attributes, or form values and use them in next test steps.
|
|
@@ -216,25 +215,69 @@ The same way you can grab text, attributes, or form values and use them in next
|
|
|
216
215
|
Common preparation steps like opening a web page, logging in a user, can be placed in `Before` or `Background`:
|
|
217
216
|
|
|
218
217
|
```js
|
|
219
|
-
const { I } = inject()
|
|
218
|
+
const { I } = inject()
|
|
220
219
|
|
|
221
|
-
Feature('CodeceptJS Demonstration')
|
|
220
|
+
Feature('CodeceptJS Demonstration')
|
|
222
221
|
|
|
223
|
-
Before(() => {
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
Before(() => {
|
|
223
|
+
// or Background
|
|
224
|
+
I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation')
|
|
225
|
+
})
|
|
226
226
|
|
|
227
227
|
Scenario('test some forms', () => {
|
|
228
|
-
I.click('Create User')
|
|
229
|
-
I.see('User is valid')
|
|
230
|
-
I.dontSeeInCurrentUrl('/documentation')
|
|
231
|
-
})
|
|
228
|
+
I.click('Create User')
|
|
229
|
+
I.see('User is valid')
|
|
230
|
+
I.dontSeeInCurrentUrl('/documentation')
|
|
231
|
+
})
|
|
232
232
|
|
|
233
233
|
Scenario('test title', () => {
|
|
234
|
-
I.seeInTitle('Example application')
|
|
235
|
-
})
|
|
234
|
+
I.seeInTitle('Example application')
|
|
235
|
+
})
|
|
236
236
|
```
|
|
237
237
|
|
|
238
|
+
## HTML Reporter
|
|
239
|
+
|
|
240
|
+
CodeceptJS includes a powerful built-in HTML Reporter that generates comprehensive, interactive test reports with detailed information about your test runs. The HTML reporter is **enabled by default** for all new projects and provides:
|
|
241
|
+
|
|
242
|
+
### Features
|
|
243
|
+
|
|
244
|
+
- **Interactive Dashboard**: Visual statistics, pie charts, and expandable test details
|
|
245
|
+
- **Step-by-Step Execution**: Shows individual test steps with timing and status indicators
|
|
246
|
+
- **BDD/Gherkin Support**: Full support for feature files with proper scenario formatting
|
|
247
|
+
- **System Information**: Comprehensive environment details including browser versions
|
|
248
|
+
- **Advanced Filtering**: Real-time filtering by status, tags, features, and test types
|
|
249
|
+
- **History Tracking**: Multi-run history with trend visualization
|
|
250
|
+
- **Error Details**: Clean formatting of error messages and stack traces
|
|
251
|
+
- **Artifacts Support**: Display screenshots and other test artifacts
|
|
252
|
+
|
|
253
|
+
### Visual Examples
|
|
254
|
+
|
|
255
|
+
#### Interactive Test Dashboard
|
|
256
|
+
|
|
257
|
+
The main dashboard provides a complete overview with interactive statistics and pie charts:
|
|
258
|
+
|
|
259
|
+

|
|
260
|
+
|
|
261
|
+
#### Detailed Test Results
|
|
262
|
+
|
|
263
|
+
Each test shows comprehensive execution details with expandable step information:
|
|
264
|
+
|
|
265
|
+

|
|
266
|
+
|
|
267
|
+
#### Advanced Filtering Capabilities
|
|
268
|
+
|
|
269
|
+
Real-time filtering allows quick navigation through test results:
|
|
270
|
+
|
|
271
|
+

|
|
272
|
+
|
|
273
|
+
#### BDD/Gherkin Support
|
|
274
|
+
|
|
275
|
+
Full support for Gherkin scenarios with proper feature formatting:
|
|
276
|
+
|
|
277
|
+

|
|
278
|
+
|
|
279
|
+
The HTML reporter generates self-contained reports that can be easily shared with your team. Learn more about configuration and features in the [HTML Reporter documentation](https://codecept.io/plugins/#htmlreporter).
|
|
280
|
+
|
|
238
281
|
## PageObjects
|
|
239
282
|
|
|
240
283
|
CodeceptJS provides the most simple way to create and use page objects in your test.
|
|
@@ -248,83 +291,55 @@ It will create a page object file for you and add it to the config.
|
|
|
248
291
|
Let's assume we created one named `docsPage`:
|
|
249
292
|
|
|
250
293
|
```js
|
|
251
|
-
const { I } = inject()
|
|
294
|
+
const { I } = inject()
|
|
252
295
|
|
|
253
296
|
module.exports = {
|
|
254
297
|
fields: {
|
|
255
298
|
email: '#user_basic_email',
|
|
256
|
-
password: '#user_basic_password'
|
|
299
|
+
password: '#user_basic_password',
|
|
257
300
|
},
|
|
258
|
-
submitButton: {css: '#new_user_basic input[type=submit]'},
|
|
301
|
+
submitButton: { css: '#new_user_basic input[type=submit]' },
|
|
259
302
|
|
|
260
303
|
sendForm(email, password) {
|
|
261
|
-
I.fillField(this.fields.email, email)
|
|
262
|
-
I.fillField(this.fields.password, password)
|
|
263
|
-
I.click(this.submitButton)
|
|
264
|
-
}
|
|
304
|
+
I.fillField(this.fields.email, email)
|
|
305
|
+
I.fillField(this.fields.password, password)
|
|
306
|
+
I.click(this.submitButton)
|
|
307
|
+
},
|
|
265
308
|
}
|
|
266
309
|
```
|
|
267
310
|
|
|
268
311
|
You can easily inject it to test by providing its name in test arguments:
|
|
269
312
|
|
|
270
313
|
```js
|
|
271
|
-
Feature('CodeceptJS Demonstration')
|
|
314
|
+
Feature('CodeceptJS Demonstration')
|
|
272
315
|
|
|
273
|
-
Before(({ I }) => {
|
|
274
|
-
|
|
275
|
-
|
|
316
|
+
Before(({ I }) => {
|
|
317
|
+
// or Background
|
|
318
|
+
I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation')
|
|
319
|
+
})
|
|
276
320
|
|
|
277
321
|
Scenario('test some forms', ({ I, docsPage }) => {
|
|
278
|
-
docsPage.sendForm('hello@world.com','123456')
|
|
279
|
-
I.see('User is valid')
|
|
280
|
-
I.dontSeeInCurrentUrl('/documentation')
|
|
281
|
-
})
|
|
322
|
+
docsPage.sendForm('hello@world.com', '123456')
|
|
323
|
+
I.see('User is valid')
|
|
324
|
+
I.dontSeeInCurrentUrl('/documentation')
|
|
325
|
+
})
|
|
282
326
|
```
|
|
283
327
|
|
|
284
328
|
When using Typescript, replace `module.exports` with `export` for autocompletion.
|
|
285
329
|
|
|
286
|
-
|
|
287
330
|
## Contributing
|
|
288
331
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
332
|
+
- ### [Contributing Guide](https://github.com/codeceptjs/CodeceptJS/blob/master/.github/CONTRIBUTING.md)
|
|
333
|
+
- ### [Code of conduct](https://github.com/codeceptjs/CodeceptJS/blob/master/.github/CODE_OF_CONDUCT.md)
|
|
292
334
|
|
|
293
335
|
## Contributors
|
|
294
336
|
|
|
295
|
-
Thanks
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
<a href="https://github.com/reubenmiller"><img src="https://avatars.githubusercontent.com/u/3029781?v=4" title="reubenmiller" width="80" height="80"></a>
|
|
302
|
-
<a href="https://github.com/Arhell"><img src="https://avatars.githubusercontent.com/u/26163841?v=4" title="Arhell" width="80" height="80"></a>
|
|
303
|
-
<a href="https://github.com/APshenkin"><img src="https://avatars.githubusercontent.com/u/14344430?v=4" title="APshenkin" width="80" height="80"></a>
|
|
304
|
-
<a href="https://github.com/fabioel"><img src="https://avatars.githubusercontent.com/u/9824235?v=4" title="fabioel" width="80" height="80"></a>
|
|
305
|
-
<a href="https://github.com/pablopaul"><img src="https://avatars.githubusercontent.com/u/635526?v=4" title="pablopaul" width="80" height="80"></a>
|
|
306
|
-
<a href="https://github.com/mirao"><img src="https://avatars.githubusercontent.com/u/12584138?v=4" title="mirao" width="80" height="80"></a>
|
|
307
|
-
<a href="https://github.com/Georgegriff"><img src="https://avatars.githubusercontent.com/u/9056958?v=4" title="Georgegriff" width="80" height="80"></a>
|
|
308
|
-
<a href="https://github.com/KMKoushik"><img src="https://avatars.githubusercontent.com/u/24666922?v=4" title="KMKoushik" width="80" height="80"></a>
|
|
309
|
-
<a href="https://github.com/nikocanvacom"><img src="https://avatars.githubusercontent.com/u/83254493?v=4" title="nikocanvacom" width="80" height="80"></a>
|
|
310
|
-
<a href="https://github.com/elukoyanov"><img src="https://avatars.githubusercontent.com/u/11647141?v=4" title="elukoyanov" width="80" height="80"></a>
|
|
311
|
-
<a href="https://github.com/gkushang"><img src="https://avatars.githubusercontent.com/u/3663389?v=4" title="gkushang" width="80" height="80"></a>
|
|
312
|
-
<a href="https://github.com/tsuemura"><img src="https://avatars.githubusercontent.com/u/17092259?v=4" title="tsuemura" width="80" height="80"></a>
|
|
313
|
-
<a href="https://github.com/EgorBodnar"><img src="https://avatars.githubusercontent.com/u/63167966?v=4" title="EgorBodnar" width="80" height="80"></a>
|
|
314
|
-
<a href="https://github.com/VikalpP"><img src="https://avatars.githubusercontent.com/u/11846339?v=4" title="VikalpP" width="80" height="80"></a>
|
|
315
|
-
<a href="https://github.com/thomashohn"><img src="https://avatars.githubusercontent.com/u/3414869?v=4" title="thomashohn" width="80" height="80"></a>
|
|
316
|
-
<a href="https://github.com/elaichenkov"><img src="https://avatars.githubusercontent.com/u/29764053?v=4" title="elaichenkov" width="80" height="80"></a>
|
|
317
|
-
<a href="https://github.com/BorisOsipov"><img src="https://avatars.githubusercontent.com/u/6514276?v=4" title="BorisOsipov" width="80" height="80"></a>
|
|
318
|
-
<a href="https://github.com/ngraf"><img src="https://avatars.githubusercontent.com/u/7094389?v=4" title="ngraf" width="80" height="80"></a>
|
|
319
|
-
<a href="https://github.com/nitschSB"><img src="https://avatars.githubusercontent.com/u/39341455?v=4" title="nitschSB" width="80" height="80"></a>
|
|
320
|
-
<a href="https://github.com/hubidu"><img src="https://avatars.githubusercontent.com/u/13134082?v=4" title="hubidu" width="80" height="80"></a>
|
|
321
|
-
<a href="https://github.com/jploskonka"><img src="https://avatars.githubusercontent.com/u/669483?v=4" title="jploskonka" width="80" height="80"></a>
|
|
322
|
-
<a href="https://github.com/maojunxyz"><img src="https://avatars.githubusercontent.com/u/28778042?v=4" title="maojunxyz" width="80" height="80"></a>
|
|
323
|
-
<a href="https://github.com/abhimanyupandian"><img src="https://avatars.githubusercontent.com/u/36107381?v=4" title="abhimanyupandian" width="80" height="80"></a>
|
|
324
|
-
<a href="https://github.com/martomo"><img src="https://avatars.githubusercontent.com/u/1850135?v=4" title="martomo" width="80" height="80"></a>
|
|
325
|
-
<a href="https://github.com/hatufacci"><img src="https://avatars.githubusercontent.com/u/4963181?v=4" title="hatufacci" width="80" height="80"></a>
|
|
326
|
-
|
|
327
|
-
[//]: contributor-faces
|
|
337
|
+
Thanks to our awesome contributors! 🎉
|
|
338
|
+
<a href="https://github.com/codeceptjs/codeceptjs/graphs/contributors">
|
|
339
|
+
<img src="https://contrib.rocks/image?repo=codeceptjs/codeceptjs" />
|
|
340
|
+
</a>
|
|
341
|
+
|
|
342
|
+
Made with [contrib.rocks](https://contrib.rocks).
|
|
328
343
|
|
|
329
344
|
## License
|
|
330
345
|
|
package/bin/codecept.js
CHANGED
|
@@ -32,7 +32,7 @@ const commandFlags = {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const errorHandler =
|
|
35
|
-
|
|
35
|
+
fn =>
|
|
36
36
|
async (...args) => {
|
|
37
37
|
try {
|
|
38
38
|
await fn(...args)
|
|
@@ -58,6 +58,13 @@ program
|
|
|
58
58
|
.description('Creates dummy config in current dir or [path]')
|
|
59
59
|
.action(errorHandler(require('../lib/command/init')))
|
|
60
60
|
|
|
61
|
+
program
|
|
62
|
+
.command('check')
|
|
63
|
+
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
64
|
+
.description('Checks configuration and environment before running tests')
|
|
65
|
+
.option('-t, --timeout [ms]', 'timeout for checks in ms, 50000 by default')
|
|
66
|
+
.action(errorHandler(require('../lib/command/check')))
|
|
67
|
+
|
|
61
68
|
program
|
|
62
69
|
.command('migrate [path]')
|
|
63
70
|
.description('Migrate json config to js config in current dir or [path]')
|
|
@@ -157,6 +164,8 @@ program
|
|
|
157
164
|
.option('--tests', 'run only JS test files and skip features')
|
|
158
165
|
.option('--no-timeouts', 'disable all timeouts')
|
|
159
166
|
.option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
|
|
167
|
+
.option('--shuffle', 'Shuffle the order in which test files run')
|
|
168
|
+
.option('--shard <index/total>', 'run only a fraction of tests (e.g., --shard 1/4)')
|
|
160
169
|
|
|
161
170
|
// mocha options
|
|
162
171
|
.option('--colors', 'force enabling of colors')
|
|
@@ -188,6 +197,7 @@ program
|
|
|
188
197
|
.option('-i, --invert', 'inverts --grep matches')
|
|
189
198
|
.option('-o, --override [value]', 'override current config options')
|
|
190
199
|
.option('--suites', 'parallel execution of suites not single tests')
|
|
200
|
+
.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)')
|
|
191
201
|
.option(commandFlags.debug.flag, commandFlags.debug.description)
|
|
192
202
|
.option(commandFlags.verbose.flag, commandFlags.verbose.description)
|
|
193
203
|
.option('--features', 'run only *.feature files and skip tests')
|
|
@@ -286,7 +296,7 @@ program
|
|
|
286
296
|
|
|
287
297
|
.action(require('../lib/command/run-rerun'))
|
|
288
298
|
|
|
289
|
-
program.on('command:*',
|
|
299
|
+
program.on('command:*', cmd => {
|
|
290
300
|
console.log(`\nUnknown command ${cmd}\n`)
|
|
291
301
|
program.outputHelp()
|
|
292
302
|
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Standalone test server script to replace json-server
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path')
|
|
8
|
+
const TestServer = require('../lib/test-server')
|
|
9
|
+
|
|
10
|
+
// Parse command line arguments
|
|
11
|
+
const args = process.argv.slice(2)
|
|
12
|
+
let dbFile = path.join(__dirname, '../test/data/rest/db.json')
|
|
13
|
+
let port = 8010
|
|
14
|
+
let host = '0.0.0.0'
|
|
15
|
+
|
|
16
|
+
// Simple argument parsing
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
const arg = args[i]
|
|
19
|
+
|
|
20
|
+
if (arg === '-p' || arg === '--port') {
|
|
21
|
+
port = parseInt(args[++i])
|
|
22
|
+
} else if (arg === '--host') {
|
|
23
|
+
host = args[++i]
|
|
24
|
+
} else if (!arg.startsWith('-')) {
|
|
25
|
+
dbFile = path.resolve(arg)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Create and start server
|
|
30
|
+
const server = new TestServer({ port, host, dbFile })
|
|
31
|
+
|
|
32
|
+
console.log(`Starting test server with db file: ${dbFile}`)
|
|
33
|
+
|
|
34
|
+
server
|
|
35
|
+
.start()
|
|
36
|
+
.then(() => {
|
|
37
|
+
console.log(`Test server is ready and listening on http://${host}:${port}`)
|
|
38
|
+
})
|
|
39
|
+
.catch(err => {
|
|
40
|
+
console.error('Failed to start test server:', err)
|
|
41
|
+
process.exit(1)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// Graceful shutdown
|
|
45
|
+
process.on('SIGINT', () => {
|
|
46
|
+
console.log('\nShutting down test server...')
|
|
47
|
+
server.stop().then(() => process.exit(0))
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
process.on('SIGTERM', () => {
|
|
51
|
+
console.log('\nShutting down test server...')
|
|
52
|
+
server.stop().then(() => process.exit(0))
|
|
53
|
+
})
|
|
@@ -3,7 +3,7 @@ if none provided clears all cookies.
|
|
|
3
3
|
|
|
4
4
|
```js
|
|
5
5
|
I.clearCookie();
|
|
6
|
-
I.clearCookie('test');
|
|
6
|
+
I.clearCookie('test');
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
@param {?string} [cookie=null] (optional, `null` by default) cookie name
|