codeceptjs 3.5.0 → 3.5.1-2.beta.7
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 +24 -25
- package/lib/actor.js +6 -3
- package/lib/ai.js +12 -3
- package/lib/cli.js +12 -2
- package/lib/codecept.js +4 -0
- package/lib/colorUtils.js +10 -0
- package/lib/command/definitions.js +2 -7
- package/lib/command/dryRun.js +2 -1
- package/lib/command/info.js +24 -0
- package/lib/command/init.js +51 -5
- package/lib/command/run-multiple/collection.js +17 -5
- package/lib/command/run-multiple.js +4 -2
- package/lib/command/run-workers.js +66 -4
- package/lib/command/run.js +7 -0
- package/lib/command/workers/runTests.js +39 -0
- package/lib/data/context.js +14 -6
- package/lib/event.js +4 -0
- package/lib/helper/ApiDataFactory.js +2 -1
- package/lib/helper/Appium.js +73 -24
- package/lib/helper/Expect.js +422 -0
- package/lib/helper/FileSystem.js +1 -1
- package/lib/helper/GraphQL.js +25 -0
- package/lib/helper/Nightmare.js +9 -4
- package/lib/helper/OpenAI.js +14 -10
- package/lib/helper/Playwright.js +1205 -288
- package/lib/helper/Protractor.js +11 -6
- package/lib/helper/Puppeteer.js +173 -61
- package/lib/helper/TestCafe.js +44 -9
- package/lib/helper/WebDriver.js +231 -82
- package/lib/helper/errors/ElementNotFound.js +2 -1
- package/lib/helper/extras/PlaywrightReactVueLocator.js +38 -0
- package/lib/helper/scripts/blurElement.js +17 -0
- package/lib/helper/scripts/focusElement.js +17 -0
- package/lib/helper/scripts/highlightElement.js +2 -2
- package/lib/html.js +3 -3
- package/lib/interfaces/bdd.js +1 -1
- package/lib/interfaces/gherkin.js +37 -3
- package/lib/interfaces/scenarioConfig.js +1 -0
- package/lib/locator.js +17 -4
- package/lib/mochaFactory.js +2 -1
- package/lib/output.js +1 -1
- package/lib/pause.js +12 -9
- package/lib/plugin/autoLogin.js +45 -10
- package/lib/plugin/heal.js +47 -17
- package/lib/plugin/retryFailedStep.js +10 -1
- package/lib/plugin/retryTo.js +2 -4
- package/lib/plugin/selenoid.js +6 -1
- package/lib/plugin/standardActingHelpers.js +0 -2
- package/lib/plugin/stepByStepReport.js +2 -2
- package/lib/plugin/tryTo.js +5 -7
- package/lib/plugin/wdio.js +0 -1
- package/lib/recorder.js +20 -9
- package/lib/session.js +1 -1
- package/lib/step.js +30 -11
- package/lib/ui.js +1 -0
- package/lib/utils.js +18 -1
- package/lib/workers.js +28 -3
- package/package.json +108 -98
- package/translations/de-DE.js +5 -0
- package/translations/fr-FR.js +14 -1
- package/translations/it-IT.js +1 -0
- package/translations/ja-JP.js +5 -0
- package/translations/pl-PL.js +5 -0
- package/translations/pt-BR.js +1 -0
- package/translations/ru-RU.js +1 -0
- package/translations/zh-CN.js +5 -0
- package/translations/zh-TW.js +5 -0
- package/typings/index.d.ts +8 -6
- package/typings/promiseBasedTypes.d.ts +784 -822
- package/typings/types.d.ts +1214 -727
- package/CHANGELOG.md +0 -2492
- package/docs/advanced.md +0 -351
- package/docs/ai.md +0 -246
- package/docs/api.md +0 -323
- package/docs/basics.md +0 -980
- package/docs/bdd.md +0 -535
- package/docs/best.md +0 -237
- package/docs/books.md +0 -37
- package/docs/bootstrap.md +0 -135
- package/docs/build/ApiDataFactory.js +0 -409
- package/docs/build/Appium.js +0 -1978
- package/docs/build/FileSystem.js +0 -228
- package/docs/build/GraphQL.js +0 -204
- package/docs/build/GraphQLDataFactory.js +0 -309
- package/docs/build/JSONResponse.js +0 -338
- package/docs/build/Mochawesome.js +0 -71
- package/docs/build/Nightmare.js +0 -2147
- package/docs/build/OpenAI.js +0 -122
- package/docs/build/Playwright.js +0 -4134
- package/docs/build/Polly.js +0 -42
- package/docs/build/Protractor.js +0 -2701
- package/docs/build/Puppeteer.js +0 -3743
- package/docs/build/REST.js +0 -344
- package/docs/build/SeleniumWebdriver.js +0 -76
- package/docs/build/TestCafe.js +0 -2059
- package/docs/build/WebDriver.js +0 -4042
- package/docs/changelog.md +0 -2501
- package/docs/commands.md +0 -254
- package/docs/community-helpers.md +0 -58
- package/docs/configuration.md +0 -157
- package/docs/continuous-integration.md +0 -22
- package/docs/custom-helpers.md +0 -306
- package/docs/data.md +0 -375
- package/docs/detox.md +0 -235
- package/docs/docker.md +0 -137
- package/docs/email.md +0 -183
- package/docs/examples.md +0 -149
- package/docs/helpers/ApiDataFactory.md +0 -266
- package/docs/helpers/Appium.md +0 -1317
- package/docs/helpers/Detox.md +0 -586
- package/docs/helpers/FileSystem.md +0 -152
- package/docs/helpers/GraphQL.md +0 -130
- package/docs/helpers/GraphQLDataFactory.md +0 -226
- package/docs/helpers/JSONResponse.md +0 -254
- package/docs/helpers/Mochawesome.md +0 -8
- package/docs/helpers/MockRequest.md +0 -377
- package/docs/helpers/Nightmare.md +0 -1258
- package/docs/helpers/OpenAI.md +0 -70
- package/docs/helpers/Playwright.md +0 -2250
- package/docs/helpers/Polly.md +0 -44
- package/docs/helpers/Puppeteer-firefox.md +0 -86
- package/docs/helpers/Puppeteer.md +0 -2147
- package/docs/helpers/REST.md +0 -218
- package/docs/helpers/TestCafe.md +0 -1224
- package/docs/helpers/WebDriver.md +0 -2325
- package/docs/hooks.md +0 -340
- package/docs/index.md +0 -111
- package/docs/installation.md +0 -75
- package/docs/internal-api.md +0 -265
- package/docs/locators.md +0 -331
- package/docs/mobile-react-native-locators.md +0 -67
- package/docs/mobile.md +0 -344
- package/docs/nightmare.md +0 -223
- package/docs/pageobjects.md +0 -291
- package/docs/parallel.md +0 -288
- package/docs/playwright.md +0 -609
- package/docs/plugins.md +0 -1225
- package/docs/puppeteer.md +0 -316
- package/docs/quickstart.md +0 -163
- package/docs/react.md +0 -69
- package/docs/reports.md +0 -392
- package/docs/secrets.md +0 -36
- package/docs/shadow.md +0 -68
- package/docs/shared/keys.mustache +0 -31
- package/docs/shared/react.mustache +0 -1
- package/docs/testcafe.md +0 -174
- package/docs/translation.md +0 -247
- package/docs/tutorial.md +0 -271
- package/docs/typescript.md +0 -180
- package/docs/ui.md +0 -59
- package/docs/videos.md +0 -28
- package/docs/visual.md +0 -202
- package/docs/vue.md +0 -121
- package/docs/webapi/amOnPage.mustache +0 -11
- package/docs/webapi/appendField.mustache +0 -11
- package/docs/webapi/attachFile.mustache +0 -12
- package/docs/webapi/checkOption.mustache +0 -13
- package/docs/webapi/clearCookie.mustache +0 -10
- package/docs/webapi/clearField.mustache +0 -9
- package/docs/webapi/click.mustache +0 -25
- 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/dontSeeCurrentUrlEquals.mustache +0 -10
- package/docs/webapi/dontSeeElement.mustache +0 -8
- package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
- package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
- package/docs/webapi/dontSeeInField.mustache +0 -11
- package/docs/webapi/dontSeeInSource.mustache +0 -8
- package/docs/webapi/dontSeeInTitle.mustache +0 -8
- 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 -16
- 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/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/moveCursorTo.mustache +0 -12
- 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/seeCurrentUrlEquals.mustache +0 -11
- package/docs/webapi/seeElement.mustache +0 -8
- package/docs/webapi/seeElementInDOM.mustache +0 -8
- package/docs/webapi/seeInCurrentUrl.mustache +0 -8
- package/docs/webapi/seeInField.mustache +0 -12
- 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/selectOption.mustache +0 -21
- package/docs/webapi/setCookie.mustache +0 -16
- package/docs/webapi/setGeoLocation.mustache +0 -12
- 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/waitForDetached.mustache +0 -10
- 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/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/webdriver.md +0 -657
- package/docs/wiki/Books-&-Posts.md +0 -27
- package/docs/wiki/Community-Helpers-&-Plugins.md +0 -49
- package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -29
- package/docs/wiki/Examples.md +0 -139
- package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
- package/docs/wiki/Home.md +0 -16
- package/docs/wiki/Release-Process.md +0 -24
- package/docs/wiki/Roadmap.md +0 -23
- package/docs/wiki/Tests.md +0 -1393
- package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
- package/docs/wiki/Videos.md +0 -19
package/README.md
CHANGED
|
@@ -7,10 +7,14 @@
|
|
|
7
7
|
|
|
8
8
|
Build Status:
|
|
9
9
|
|
|
10
|
+
Appium Helper:
|
|
11
|
+
[](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appiumV2_Android.yml)
|
|
12
|
+
[](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appiumV2_iOS.yml)
|
|
13
|
+
|
|
14
|
+
Web Helper:
|
|
10
15
|
[](https://github.com/codeceptjs/CodeceptJS/actions/workflows/playwright.yml)
|
|
11
16
|
[](https://github.com/codeceptjs/CodeceptJS/actions/workflows/puppeteer.yml)
|
|
12
17
|
[](https://github.com/codeceptjs/CodeceptJS/actions/workflows/webdriver.yml)
|
|
13
|
-
[](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appium.yml)
|
|
14
18
|
[](https://github.com/codeceptjs/CodeceptJS/actions/workflows/testcafe.yml)
|
|
15
19
|
|
|
16
20
|
# CodeceptJS [](https://stand-with-ukraine.pp.ua)
|
|
@@ -20,7 +24,7 @@ Reference: [Helpers API](https://github.com/codeceptjs/CodeceptJS/tree/master/do
|
|
|
20
24
|
## Supercharged E2E Testing
|
|
21
25
|
|
|
22
26
|
CodeceptJS is a new testing framework for end-to-end testing with WebDriver (or others).
|
|
23
|
-
It abstracts browser interaction to simple steps that are written from a user perspective.
|
|
27
|
+
It abstracts browser interaction to simple steps that are written from a user's perspective.
|
|
24
28
|
A simple test that verifies the "Welcome" text is present on a main page of a site will look like:
|
|
25
29
|
|
|
26
30
|
```js
|
|
@@ -36,7 +40,7 @@ CodeceptJS tests are:
|
|
|
36
40
|
|
|
37
41
|
* **Synchronous**. You don't need to care about callbacks or promises or test scenarios which are linear. But, your tests should be linear.
|
|
38
42
|
* 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
|
+
* Backend **API agnostic**. We don't know which WebDriver implementation is running this test.
|
|
40
44
|
|
|
41
45
|
CodeceptJS uses **Helper** modules to provide actions to `I` object. Currently, CodeceptJS has these helpers:
|
|
42
46
|
|
|
@@ -44,7 +48,6 @@ CodeceptJS uses **Helper** modules to provide actions to `I` object. Currently,
|
|
|
44
48
|
* [**Puppeteer**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Puppeteer.md) - uses Google Chrome's Puppeteer for fast headless testing.
|
|
45
49
|
* [**WebDriver**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/WebDriver.md) - uses [webdriverio](http://webdriver.io/) to run tests via WebDriver protocol.
|
|
46
50
|
* [**TestCafe**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/TestCafe.md) - cheap and fast cross-browser test automation.
|
|
47
|
-
* [**Nightmare**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Nightmare.md) - uses Electron and NightmareJS to run tests.
|
|
48
51
|
* [**Appium**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Appium.md) - for **mobile testing** with Appium
|
|
49
52
|
* [**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.
|
|
50
53
|
|
|
@@ -54,27 +57,27 @@ And more to come...
|
|
|
54
57
|
|
|
55
58
|
CodeceptJS is a successor of [Codeception](http://codeception.com), a popular full-stack testing framework for PHP.
|
|
56
59
|
With CodeceptJS your scenario-driven functional and acceptance tests will be as simple and clean as they can be.
|
|
57
|
-
You don't need to worry about asynchronous nature of NodeJS or about various APIs of Selenium, Puppeteer,
|
|
60
|
+
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.
|
|
58
61
|
|
|
59
62
|
|
|
60
63
|
## Features
|
|
61
64
|
|
|
62
|
-
* 🪄 **AI-powered** with GPT features to assist and heal failing tests
|
|
63
|
-
* Based on [Mocha](https://mochajs.org/) testing framework.
|
|
64
|
-
* Designed for scenario driven acceptance testing in BDD-style
|
|
65
|
-
* Uses ES6 natively without transpiler.
|
|
65
|
+
* 🪄 **AI-powered** with GPT features to assist and heal failing tests.
|
|
66
|
+
* ☕ Based on [Mocha](https://mochajs.org/) testing framework.
|
|
67
|
+
* 💼 Designed for scenario driven acceptance testing in BDD-style.
|
|
68
|
+
* 💻 Uses ES6 natively without transpiler.
|
|
66
69
|
* Also plays nice with TypeScript.
|
|
67
|
-
* Smart locators: use names, labels, matching text, CSS or XPath to locate elements.
|
|
68
|
-
* Interactive debugging shell: pause test at any point and try different commands in a browser.
|
|
70
|
+
* </> Smart locators: use names, labels, matching text, CSS or XPath to locate elements.
|
|
71
|
+
* 🌐 Interactive debugging shell: pause test at any point and try different commands in a browser.
|
|
69
72
|
* Easily create tests, pageobjects, stepobjects with CLI generators.
|
|
70
73
|
|
|
71
|
-
##
|
|
74
|
+
## Installation
|
|
72
75
|
|
|
73
76
|
```sh
|
|
74
77
|
npm i codeceptjs --save
|
|
75
78
|
```
|
|
76
79
|
|
|
77
|
-
Move to directory where you'd like to have your tests (and
|
|
80
|
+
Move to directory where you'd like to have your tests (and CodeceptJS config) stored, and execute:
|
|
78
81
|
|
|
79
82
|
```sh
|
|
80
83
|
npx codeceptjs init
|
|
@@ -128,8 +131,8 @@ Scenario('test some forms', ({ I }) => {
|
|
|
128
131
|
});
|
|
129
132
|
```
|
|
130
133
|
|
|
131
|
-
All actions are performed by I object; assertions functions start with `see` function.
|
|
132
|
-
In
|
|
134
|
+
All actions are performed by `I` object; assertions functions start with `see` function.
|
|
135
|
+
In these examples all methods of `I` are taken from WebDriver helper, see [reference](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/WebDriver.md) to learn how to use them.
|
|
133
136
|
|
|
134
137
|
Let's execute this test with `run` command. Additional option `--steps` will show us the running process. We recommend use `--steps` or `--debug` during development.
|
|
135
138
|
|
|
@@ -195,17 +198,15 @@ In this case 'User is valid' string will be searched only inside elements locate
|
|
|
195
198
|
### Grabbers
|
|
196
199
|
|
|
197
200
|
In case you need to return a value from a webpage and use it directly in test, you should use methods with `grab` prefix.
|
|
198
|
-
They are expected to be used inside async/await functions, and their results will be available in test:
|
|
201
|
+
They are expected to be used inside `async/await` functions, and their results will be available in test:
|
|
199
202
|
|
|
200
203
|
```js
|
|
201
|
-
const assert = require('assert');
|
|
202
|
-
|
|
203
204
|
Feature('CodeceptJS Demonstration');
|
|
204
205
|
|
|
205
206
|
Scenario('test page title', async ({ I }) => {
|
|
206
207
|
I.amOnPage('http://simple-form-bootstrap.plataformatec.com.br/documentation');
|
|
207
208
|
const title = await I.grabTitle();
|
|
208
|
-
|
|
209
|
+
I.expectEqual(title, 'Example application with SimpleForm and Twitter Bootstrap'); // Avaiable with Expect helper. -> https://codecept.io/helpers/Expect/
|
|
209
210
|
});
|
|
210
211
|
```
|
|
211
212
|
|
|
@@ -303,8 +304,8 @@ Thanks all to those who are and will have contributing to this awesome project!
|
|
|
303
304
|
<a href="https://github.com/APshenkin"><img src="https://avatars.githubusercontent.com/u/14344430?v=4" title="APshenkin" width="80" height="80"></a>
|
|
304
305
|
<a href="https://github.com/fabioel"><img src="https://avatars.githubusercontent.com/u/9824235?v=4" title="fabioel" width="80" height="80"></a>
|
|
305
306
|
<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/Georgegriff"><img src="https://avatars.githubusercontent.com/u/9056958?v=4" title="Georgegriff" width="80" height="80"></a>
|
|
307
307
|
<a href="https://github.com/mirao"><img src="https://avatars.githubusercontent.com/u/12584138?v=4" title="mirao" width="80" height="80"></a>
|
|
308
|
+
<a href="https://github.com/Georgegriff"><img src="https://avatars.githubusercontent.com/u/9056958?v=4" title="Georgegriff" width="80" height="80"></a>
|
|
308
309
|
<a href="https://github.com/KMKoushik"><img src="https://avatars.githubusercontent.com/u/24666922?v=4" title="KMKoushik" width="80" height="80"></a>
|
|
309
310
|
<a href="https://github.com/nikocanvacom"><img src="https://avatars.githubusercontent.com/u/83254493?v=4" title="nikocanvacom" width="80" height="80"></a>
|
|
310
311
|
<a href="https://github.com/elukoyanov"><img src="https://avatars.githubusercontent.com/u/11647141?v=4" title="elukoyanov" width="80" height="80"></a>
|
|
@@ -314,17 +315,15 @@ Thanks all to those who are and will have contributing to this awesome project!
|
|
|
314
315
|
<a href="https://github.com/VikalpP"><img src="https://avatars.githubusercontent.com/u/11846339?v=4" title="VikalpP" width="80" height="80"></a>
|
|
315
316
|
<a href="https://github.com/BorisOsipov"><img src="https://avatars.githubusercontent.com/u/6514276?v=4" title="BorisOsipov" width="80" height="80"></a>
|
|
316
317
|
<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/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4" title="dependabot[bot]" width="80" height="80"></a>
|
|
318
318
|
<a href="https://github.com/nitschSB"><img src="https://avatars.githubusercontent.com/u/39341455?v=4" title="nitschSB" width="80" height="80"></a>
|
|
319
319
|
<a href="https://github.com/hubidu"><img src="https://avatars.githubusercontent.com/u/13134082?v=4" title="hubidu" width="80" height="80"></a>
|
|
320
320
|
<a href="https://github.com/jploskonka"><img src="https://avatars.githubusercontent.com/u/669483?v=4" title="jploskonka" width="80" height="80"></a>
|
|
321
|
+
<a href="https://github.com/ngraf"><img src="https://avatars.githubusercontent.com/u/7094389?v=4" title="ngraf" width="80" height="80"></a>
|
|
321
322
|
<a href="https://github.com/maojunxyz"><img src="https://avatars.githubusercontent.com/u/28778042?v=4" title="maojunxyz" width="80" height="80"></a>
|
|
322
323
|
<a href="https://github.com/abhimanyupandian"><img src="https://avatars.githubusercontent.com/u/36107381?v=4" title="abhimanyupandian" width="80" height="80"></a>
|
|
323
324
|
<a href="https://github.com/martomo"><img src="https://avatars.githubusercontent.com/u/1850135?v=4" title="martomo" width="80" height="80"></a>
|
|
324
|
-
<a href="https://github.com/
|
|
325
|
-
<a href="https://github.com/
|
|
326
|
-
<a href="https://github.com/petehouston"><img src="https://avatars.githubusercontent.com/u/9006720?v=4" title="petehouston" width="80" height="80"></a>
|
|
327
|
-
<a href="https://github.com/jancorvus"><img src="https://avatars.githubusercontent.com/u/67001310?v=4" title="jancorvus" 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
|
+
<a href="https://github.com/johnyb"><img src="https://avatars.githubusercontent.com/u/86358?v=4" title="johnyb" width="80" height="80"></a>
|
|
328
327
|
|
|
329
328
|
[//]: contributor-faces
|
|
330
329
|
|
package/lib/actor.js
CHANGED
|
@@ -13,15 +13,18 @@ const output = require('./output');
|
|
|
13
13
|
*/
|
|
14
14
|
class Actor {
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Print the comment on log. Also, adding a step in the `Test.steps` object
|
|
17
17
|
* @param {string} msg
|
|
18
18
|
* @param {string} color
|
|
19
19
|
* @inner
|
|
20
20
|
*
|
|
21
21
|
* ⚠️ returns a promise which is synchronized internally by recorder
|
|
22
22
|
*/
|
|
23
|
-
say(msg, color = 'cyan') {
|
|
24
|
-
|
|
23
|
+
async say(msg, color = 'cyan') {
|
|
24
|
+
const step = new Step('say', 'say');
|
|
25
|
+
step.status = 'passed';
|
|
26
|
+
return recordStep(step, [msg]).then(() => {
|
|
27
|
+
// this is backward compatibility as this event may be used somewhere
|
|
25
28
|
event.emit(event.step.comment, msg);
|
|
26
29
|
output.say(msg, `${color}`);
|
|
27
30
|
});
|
package/lib/ai.js
CHANGED
|
@@ -16,6 +16,8 @@ const htmlConfig = {
|
|
|
16
16
|
html: {},
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
const aiInstance = null;
|
|
20
|
+
|
|
19
21
|
class AiAssistant {
|
|
20
22
|
constructor() {
|
|
21
23
|
this.config = config.get('ai', defaultConfig);
|
|
@@ -26,7 +28,10 @@ class AiAssistant {
|
|
|
26
28
|
|
|
27
29
|
this.isEnabled = !!process.env.OPENAI_API_KEY;
|
|
28
30
|
|
|
29
|
-
if (!this.isEnabled)
|
|
31
|
+
if (!this.isEnabled) {
|
|
32
|
+
debug('No OpenAI API key provided. AI assistant is disabled.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
30
35
|
|
|
31
36
|
const configuration = new Configuration({
|
|
32
37
|
apiKey: process.env.OPENAI_API_KEY,
|
|
@@ -35,13 +40,17 @@ class AiAssistant {
|
|
|
35
40
|
this.openai = new OpenAIApi(configuration);
|
|
36
41
|
}
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
static getInstance() {
|
|
44
|
+
return aiInstance || new AiAssistant();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async setHtmlContext(html) {
|
|
39
48
|
let processedHTML = html;
|
|
40
49
|
|
|
41
50
|
if (this.htmlConfig.simplify) {
|
|
42
51
|
processedHTML = removeNonInteractiveElements(processedHTML, this.htmlConfig);
|
|
43
52
|
}
|
|
44
|
-
if (this.htmlConfig.minify) processedHTML = minifyHtml(processedHTML);
|
|
53
|
+
if (this.htmlConfig.minify) processedHTML = await minifyHtml(processedHTML);
|
|
45
54
|
if (this.htmlConfig.maxLength) processedHTML = splitByChunks(processedHTML, this.htmlConfig.maxLength)[0];
|
|
46
55
|
|
|
47
56
|
debug(processedHTML);
|
package/lib/cli.js
CHANGED
|
@@ -81,6 +81,11 @@ class Cli extends Base {
|
|
|
81
81
|
if (!codeceptjsEventDispatchersRegistered) {
|
|
82
82
|
codeceptjsEventDispatchersRegistered = true;
|
|
83
83
|
|
|
84
|
+
event.dispatcher.on(event.bddStep.started, (step) => {
|
|
85
|
+
output.stepShift = 2;
|
|
86
|
+
output.step(step);
|
|
87
|
+
});
|
|
88
|
+
|
|
84
89
|
event.dispatcher.on(event.step.started, (step) => {
|
|
85
90
|
let processingStep = step;
|
|
86
91
|
const metaSteps = [];
|
|
@@ -93,12 +98,17 @@ class Cli extends Base {
|
|
|
93
98
|
for (let i = 0; i < Math.max(currentMetaStep.length, metaSteps.length); i++) {
|
|
94
99
|
if (currentMetaStep[i] !== metaSteps[i]) {
|
|
95
100
|
output.stepShift = 3 + 2 * i;
|
|
96
|
-
if (metaSteps[i])
|
|
101
|
+
if (!metaSteps[i]) continue;
|
|
102
|
+
// bdd steps are handled by bddStep.started
|
|
103
|
+
if (metaSteps[i].isBDD()) continue;
|
|
104
|
+
output.step(metaSteps[i]);
|
|
97
105
|
}
|
|
98
106
|
}
|
|
99
107
|
currentMetaStep = metaSteps;
|
|
100
108
|
output.stepShift = 3 + 2 * shift;
|
|
101
|
-
|
|
109
|
+
if (step.helper.constructor.name !== 'ExpectHelper') {
|
|
110
|
+
output.step(step);
|
|
111
|
+
}
|
|
102
112
|
});
|
|
103
113
|
|
|
104
114
|
event.dispatcher.on(event.step.finished, () => {
|
package/lib/codecept.js
CHANGED
|
@@ -89,6 +89,9 @@ class Codecept {
|
|
|
89
89
|
global.When = stepDefinitions.When;
|
|
90
90
|
global.Then = stepDefinitions.Then;
|
|
91
91
|
global.DefineParameterType = stepDefinitions.defineParameterType;
|
|
92
|
+
|
|
93
|
+
// debug mode
|
|
94
|
+
global.debugMode = false;
|
|
92
95
|
}
|
|
93
96
|
}
|
|
94
97
|
|
|
@@ -176,6 +179,7 @@ class Codecept {
|
|
|
176
179
|
* Run a specific test or all loaded tests.
|
|
177
180
|
*
|
|
178
181
|
* @param {string} [test]
|
|
182
|
+
* @returns {Promise<void>}
|
|
179
183
|
*/
|
|
180
184
|
async run(test) {
|
|
181
185
|
return new Promise((resolve, reject) => {
|
package/lib/colorUtils.js
CHANGED
|
@@ -226,15 +226,25 @@ function isColorProperty(prop) {
|
|
|
226
226
|
'color',
|
|
227
227
|
'background',
|
|
228
228
|
'backgroundColor',
|
|
229
|
+
'background-color',
|
|
229
230
|
'borderColor',
|
|
231
|
+
'border-color',
|
|
230
232
|
'borderBottomColor',
|
|
233
|
+
'border-bottom-color',
|
|
231
234
|
'borderLeftColor',
|
|
235
|
+
'border-left-color',
|
|
232
236
|
'borderRightColor',
|
|
233
237
|
'borderTopColor',
|
|
234
238
|
'caretColor',
|
|
235
239
|
'columnRuleColor',
|
|
236
240
|
'outlineColor',
|
|
237
241
|
'textDecorationColor',
|
|
242
|
+
'border-right-color',
|
|
243
|
+
'border-top-color',
|
|
244
|
+
'caret-color',
|
|
245
|
+
'column-rule-color',
|
|
246
|
+
'outline-color',
|
|
247
|
+
'text-decoration-color',
|
|
238
248
|
].indexOf(prop) > -1;
|
|
239
249
|
}
|
|
240
250
|
|
|
@@ -17,7 +17,6 @@ const actingHelpers = [...require('../plugin/standardActingHelpers'), 'REST'];
|
|
|
17
17
|
* @param {Map} params.supportObject
|
|
18
18
|
* @param {Array<string>} params.helperNames
|
|
19
19
|
* @param {Array<string>} params.importPaths
|
|
20
|
-
* @param {Array<string>} params.customHelpers
|
|
21
20
|
* @param params.translations
|
|
22
21
|
*
|
|
23
22
|
* @returns {string}
|
|
@@ -29,15 +28,13 @@ const getDefinitionsFileContent = ({
|
|
|
29
28
|
supportObject,
|
|
30
29
|
importPaths,
|
|
31
30
|
translations,
|
|
32
|
-
customHelpers,
|
|
33
31
|
}) => {
|
|
34
32
|
const getHelperListFragment = ({
|
|
35
33
|
hasCustomHelper,
|
|
36
34
|
hasCustomStepsFile,
|
|
37
|
-
customHelpers,
|
|
38
35
|
}) => {
|
|
39
36
|
if (hasCustomHelper && hasCustomStepsFile) {
|
|
40
|
-
return `${['ReturnType<steps_file>',
|
|
37
|
+
return `${['ReturnType<steps_file>', 'WithTranslation<Methods>'].join(', ')}`;
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
if (hasCustomStepsFile) {
|
|
@@ -50,7 +47,6 @@ const getDefinitionsFileContent = ({
|
|
|
50
47
|
const helpersListFragment = getHelperListFragment({
|
|
51
48
|
hasCustomHelper,
|
|
52
49
|
hasCustomStepsFile,
|
|
53
|
-
customHelpers,
|
|
54
50
|
});
|
|
55
51
|
|
|
56
52
|
const importPathsFragment = importPaths.join('\n');
|
|
@@ -143,7 +139,7 @@ module.exports = function (genPath, options) {
|
|
|
143
139
|
}
|
|
144
140
|
|
|
145
141
|
if (!actingHelpers.includes(name)) {
|
|
146
|
-
customHelpers.push(
|
|
142
|
+
customHelpers.push(name);
|
|
147
143
|
}
|
|
148
144
|
}
|
|
149
145
|
|
|
@@ -186,7 +182,6 @@ module.exports = function (genPath, options) {
|
|
|
186
182
|
translations,
|
|
187
183
|
hasCustomStepsFile,
|
|
188
184
|
hasCustomHelper,
|
|
189
|
-
customHelpers,
|
|
190
185
|
});
|
|
191
186
|
|
|
192
187
|
// add aliases for translations
|
package/lib/command/dryRun.js
CHANGED
|
@@ -20,7 +20,8 @@ module.exports = async function (test, options) {
|
|
|
20
20
|
if (config.plugins) {
|
|
21
21
|
// disable all plugins by default, they can be enabled with -p option
|
|
22
22
|
for (const plugin in config.plugins) {
|
|
23
|
-
|
|
23
|
+
// if `-p all` is passed, then enabling all plugins, otherwise plugins could be enabled by `-p customLocator,commentStep,tryTo`
|
|
24
|
+
config.plugins[plugin].enabled = options.plugins === 'all';
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
package/lib/command/info.js
CHANGED
|
@@ -37,3 +37,27 @@ module.exports = async function (path) {
|
|
|
37
37
|
output.print('Please copy environment info when you report issues on GitHub: https://github.com/Codeception/CodeceptJS/issues');
|
|
38
38
|
output.print('***************************************');
|
|
39
39
|
};
|
|
40
|
+
|
|
41
|
+
module.exports.getMachineInfo = async () => {
|
|
42
|
+
const info = {
|
|
43
|
+
nodeInfo: await envinfo.helpers.getNodeInfo(),
|
|
44
|
+
osInfo: await envinfo.helpers.getOSInfo(),
|
|
45
|
+
cpuInfo: await envinfo.helpers.getCPUInfo(),
|
|
46
|
+
chromeInfo: await envinfo.helpers.getChromeInfo(),
|
|
47
|
+
edgeInfo: await envinfo.helpers.getEdgeInfo(),
|
|
48
|
+
firefoxInfo: await envinfo.helpers.getFirefoxInfo(),
|
|
49
|
+
safariInfo: await envinfo.helpers.getSafariInfo(),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
output.print('***************************************');
|
|
53
|
+
for (const [key, value] of Object.entries(info)) {
|
|
54
|
+
if (Array.isArray(value)) {
|
|
55
|
+
output.print(`${key}: ${value[1]}`);
|
|
56
|
+
} else {
|
|
57
|
+
output.print(`${key}: ${JSON.stringify(value, null, ' ')}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
output.print('If you need more detailed info, just run this: npx codeceptjs info');
|
|
61
|
+
output.print('***************************************');
|
|
62
|
+
return info;
|
|
63
|
+
};
|
package/lib/command/init.js
CHANGED
|
@@ -20,7 +20,7 @@ const defaultConfig = {
|
|
|
20
20
|
include: {},
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium', 'TestCafe'
|
|
23
|
+
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium', 'TestCafe'];
|
|
24
24
|
const translations = Object.keys(require('../../translations'));
|
|
25
25
|
|
|
26
26
|
const noTranslation = 'English (no localization)';
|
|
@@ -201,7 +201,13 @@ module.exports = function (initPath) {
|
|
|
201
201
|
// no extra step file for typescript (as it doesn't match TS conventions)
|
|
202
202
|
const stepFile = `./steps_file.${extension}`;
|
|
203
203
|
fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor);
|
|
204
|
-
|
|
204
|
+
|
|
205
|
+
if (isTypeScript) {
|
|
206
|
+
config.include = _actorTranslation('./steps_file', config.translation);
|
|
207
|
+
} else {
|
|
208
|
+
config.include = _actorTranslation(stepFile, config.translation);
|
|
209
|
+
}
|
|
210
|
+
|
|
205
211
|
print(`Steps file created at ${stepFile}`);
|
|
206
212
|
|
|
207
213
|
let configSource;
|
|
@@ -316,7 +322,17 @@ module.exports = function (initPath) {
|
|
|
316
322
|
};
|
|
317
323
|
|
|
318
324
|
print('Configure helpers...');
|
|
319
|
-
inquirer.prompt(helperConfigs).then((helperResult) => {
|
|
325
|
+
inquirer.prompt(helperConfigs).then(async (helperResult) => {
|
|
326
|
+
if (helperResult.Playwright_browser === 'electron') {
|
|
327
|
+
delete helperResult.Playwright_url;
|
|
328
|
+
delete helperResult.Playwright_show;
|
|
329
|
+
|
|
330
|
+
helperResult.Playwright_electron = {
|
|
331
|
+
executablePath: '// require("electron") or require("electron-forge")',
|
|
332
|
+
args: ['path/to/your/main.js'],
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
320
336
|
Object.keys(helperResult).forEach((key) => {
|
|
321
337
|
const parts = key.split('_');
|
|
322
338
|
const helperName = parts[0];
|
|
@@ -326,12 +342,12 @@ module.exports = function (initPath) {
|
|
|
326
342
|
});
|
|
327
343
|
|
|
328
344
|
print('');
|
|
329
|
-
finish();
|
|
345
|
+
await finish();
|
|
330
346
|
});
|
|
331
347
|
});
|
|
332
348
|
};
|
|
333
349
|
|
|
334
|
-
function install(dependencies
|
|
350
|
+
function install(dependencies) {
|
|
335
351
|
let command;
|
|
336
352
|
let args;
|
|
337
353
|
|
|
@@ -364,9 +380,39 @@ function install(dependencies, verbose) {
|
|
|
364
380
|
].concat(dependencies);
|
|
365
381
|
}
|
|
366
382
|
|
|
383
|
+
if (process.env._INIT_DRY_RUN_INSTALL) {
|
|
384
|
+
args.push('--dry-run');
|
|
385
|
+
}
|
|
386
|
+
|
|
367
387
|
const { status } = spawn.sync(command, args, { stdio: 'inherit' });
|
|
368
388
|
if (status !== 0) {
|
|
369
389
|
throw new Error(`${command} ${args.join(' ')} failed`);
|
|
370
390
|
}
|
|
371
391
|
return true;
|
|
372
392
|
}
|
|
393
|
+
|
|
394
|
+
function _actorTranslation(stepFile, translationSelected) {
|
|
395
|
+
let actor;
|
|
396
|
+
|
|
397
|
+
for (const translationAvailable of translations) {
|
|
398
|
+
if (actor) {
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (translationSelected === translationAvailable) {
|
|
403
|
+
const nameOfActor = require('../../translations')[translationAvailable].I;
|
|
404
|
+
|
|
405
|
+
actor = {
|
|
406
|
+
[nameOfActor]: stepFile,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (!actor) {
|
|
412
|
+
actor = {
|
|
413
|
+
I: stepFile,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return actor;
|
|
418
|
+
}
|
|
@@ -47,14 +47,26 @@ class Collection {
|
|
|
47
47
|
*/
|
|
48
48
|
prepareRuns(selectedRuns, config) {
|
|
49
49
|
selectedRuns.forEach((selectedRun) => {
|
|
50
|
-
const
|
|
51
|
-
const
|
|
50
|
+
const runConfig = [];
|
|
51
|
+
const runName = [];
|
|
52
52
|
|
|
53
|
-
if (
|
|
54
|
-
|
|
53
|
+
if (selectedRun === 'all') {
|
|
54
|
+
Object.keys(config.multiple).forEach(name => {
|
|
55
|
+
runName.push(name);
|
|
56
|
+
runConfig.push(config.multiple[name]);
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
runName.push(selectedRun.split(':')[0]);
|
|
60
|
+
runConfig.push(config.multiple[runName[0]]);
|
|
55
61
|
}
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
for (let i = 0; i < runConfig.length; i++) {
|
|
64
|
+
if (!runConfig[i]) {
|
|
65
|
+
throw new Error(`run ${runName[i]} was not configured in "multiple" section of config`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.addRun(createRun(runName[i], runConfig[i]));
|
|
69
|
+
}
|
|
58
70
|
});
|
|
59
71
|
|
|
60
72
|
return this;
|
|
@@ -28,7 +28,9 @@ let processesDone;
|
|
|
28
28
|
|
|
29
29
|
module.exports = async function (selectedRuns, options) {
|
|
30
30
|
// registering options globally to use in config
|
|
31
|
-
|
|
31
|
+
if (options.profile) {
|
|
32
|
+
process.env.profile = options.profile;
|
|
33
|
+
}
|
|
32
34
|
const configFile = options.config;
|
|
33
35
|
|
|
34
36
|
const testRoot = getTestRoot(configFile);
|
|
@@ -124,7 +126,7 @@ function executeRun(runName, runConfig) {
|
|
|
124
126
|
if (browserConfig.outputName) {
|
|
125
127
|
outputDir += typeof browserConfig.outputName === 'function' ? browserConfig.outputName() : browserConfig.outputName;
|
|
126
128
|
} else {
|
|
127
|
-
const hash = crypto.createHash('
|
|
129
|
+
const hash = crypto.createHash('sha256');
|
|
128
130
|
hash.update(JSON.stringify(browserConfig));
|
|
129
131
|
outputDir += hash.digest('hex');
|
|
130
132
|
}
|
|
@@ -7,6 +7,12 @@ const Workers = require('../workers');
|
|
|
7
7
|
module.exports = async function (workerCount, selectedRuns, options) {
|
|
8
8
|
process.env.profile = options.profile;
|
|
9
9
|
|
|
10
|
+
const suiteArr = [];
|
|
11
|
+
const passedTestArr = [];
|
|
12
|
+
const failedTestArr = [];
|
|
13
|
+
const skippedTestArr = [];
|
|
14
|
+
const stepArr = [];
|
|
15
|
+
|
|
10
16
|
const { config: testConfig, override = '' } = options;
|
|
11
17
|
const overrideConfigs = tryOrDefault(() => JSON.parse(override), {});
|
|
12
18
|
const by = options.suites ? 'suite' : 'test';
|
|
@@ -26,19 +32,75 @@ module.exports = async function (workerCount, selectedRuns, options) {
|
|
|
26
32
|
|
|
27
33
|
const workers = new Workers(numberOfWorkers, config);
|
|
28
34
|
workers.overrideConfig(overrideConfigs);
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
|
|
36
|
+
workers.on(event.suite.before, (suite) => {
|
|
37
|
+
suiteArr.push(suite);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
workers.on(event.step.passed, (step) => {
|
|
41
|
+
stepArr.push(step);
|
|
31
42
|
});
|
|
32
43
|
|
|
33
|
-
workers.on(event.
|
|
34
|
-
|
|
44
|
+
workers.on(event.step.failed, (step) => {
|
|
45
|
+
stepArr.push(step);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
workers.on(event.test.failed, (test) => {
|
|
49
|
+
failedTestArr.push(test);
|
|
50
|
+
output.test.failed(test);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
workers.on(event.test.passed, (test) => {
|
|
54
|
+
passedTestArr.push(test);
|
|
55
|
+
output.test.passed(test);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
workers.on(event.test.skipped, (test) => {
|
|
59
|
+
skippedTestArr.push(test);
|
|
60
|
+
output.test.skipped(test);
|
|
35
61
|
});
|
|
36
62
|
|
|
37
63
|
workers.on(event.all.result, () => {
|
|
64
|
+
// expose test stats after all workers finished their execution
|
|
65
|
+
function addStepsToTest(test, stepArr) {
|
|
66
|
+
stepArr.test.steps.forEach(step => {
|
|
67
|
+
if (test.steps.length === 0) {
|
|
68
|
+
test.steps.push(step);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
stepArr.forEach(step => {
|
|
74
|
+
passedTestArr.forEach(test => {
|
|
75
|
+
if (step.test.title === test.title) {
|
|
76
|
+
addStepsToTest(test, step);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
failedTestArr.forEach(test => {
|
|
81
|
+
if (step.test.title === test.title) {
|
|
82
|
+
addStepsToTest(test, step);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
event.dispatcher.emit(event.workers.result, {
|
|
88
|
+
suites: suiteArr,
|
|
89
|
+
tests: {
|
|
90
|
+
passed: passedTestArr,
|
|
91
|
+
failed: failedTestArr,
|
|
92
|
+
skipped: skippedTestArr,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
38
95
|
workers.printResults();
|
|
39
96
|
});
|
|
40
97
|
|
|
41
98
|
try {
|
|
99
|
+
if (options.verbose) {
|
|
100
|
+
global.debugMode = true;
|
|
101
|
+
const { getMachineInfo } = require('./info');
|
|
102
|
+
await getMachineInfo();
|
|
103
|
+
}
|
|
42
104
|
await workers.bootstrapAll();
|
|
43
105
|
await workers.run();
|
|
44
106
|
} catch (err) {
|
package/lib/command/run.js
CHANGED
|
@@ -28,6 +28,13 @@ module.exports = async function (test, options) {
|
|
|
28
28
|
codecept.init(testRoot);
|
|
29
29
|
await codecept.bootstrap();
|
|
30
30
|
codecept.loadTests(test);
|
|
31
|
+
|
|
32
|
+
if (options.verbose) {
|
|
33
|
+
global.debugMode = true;
|
|
34
|
+
const { getMachineInfo } = require('./info');
|
|
35
|
+
await getMachineInfo();
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
await codecept.run();
|
|
32
39
|
} catch (err) {
|
|
33
40
|
printError(err);
|