Skip to content

Commit

Permalink
Merge branch '3.x' of github.com:codeceptjs/CodeceptJS into 3.x
Browse files Browse the repository at this point in the history
  • Loading branch information
DavertMik committed Nov 11, 2021
2 parents 931ea69 + edd7e26 commit b5214d3
Show file tree
Hide file tree
Showing 21 changed files with 167 additions and 32 deletions.
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,53 @@
## 3.2.0

<<<<<<< HEAD
🛩️ Features:

**Timeouts implemented**
* global timeouts (via `timeout` config option).
* _Breaking change:_ timeout option expects **timeout in seconds**, not in miliseconds as it was previously.
* test timeouts (via `Scenario` and `Feature` options)
* _Breaking change:_ `Feature().timeout()` and `Scenario().timeout()` calls has no effect and are deprecated

```js
// set timeout for every test in suite to 10 secs
Feature('tests with timeout', { timeout: 10 });

// set timeout for this test to 20 secs
Scenario('a test with timeout', { timeout: 20 }, ({ I }) => {});
```

* step timeouts (See #3059 by @nikocanvacom)

```js
// set step timeout to 5 secs
I.limitTime(5).click('Link');
```
* `stepTimeout` plugin introduced to automatically add timeouts for each step (#3059 by @nikocanvacom).

[**retryTo**](/plugins/#retryto) plugin introduced to rerun a set of steps on failure:

```js
// editing in text in iframe
// if iframe was not loaded - retry 5 times
await retryTo(() => {
I.switchTo('#editor frame');
I.fillField('textarea', 'value');
}, 5);
```

* [Playwright] added `locale` configuration
* [WebDriver] upgraded to webdriverio v7

🐛 Bugfixes:

* Fixed allure plugin "Unexpected endStep()" error in #3098 by @abhimanyupandian
* [Puppeteer] always close remote browser on test end. See #3054 by @mattonem
* stepbyStepReport Plugin: Disabled screenshots after test has failed. See #3119 by @ioannisChalkias


=======
>>>>>>> timeouts
## 3.1.3

🛩️ Features:
Expand Down
1 change: 1 addition & 0 deletions bin/codecept.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ program.command('run [test]')
.option('-c, --config [file]', 'configuration file to be used')
.option('--features', 'run only *.feature files and skip tests')
.option('--tests', 'run only JS test files and skip features')
.option('--no-timeouts', 'disable all timeouts')
.option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')

// mocha options
Expand Down
50 changes: 50 additions & 0 deletions docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,17 @@ You can use this options for build your own [plugins](https://codecept.io/hooks/
```
### Timeout <Badge text="Updated in 3.2" type="warning"/>
<<<<<<< HEAD
Tests can get stuck due to various reasons such as network connection issues, crashed browser, etc.
This can make tests process hang. To prevent these situations timeouts can be used. Timeouts can be set explicitly for flaky parts of code, or implicitly in a config.
=======
Tests can get stuck due to various reasons such as network connection issues, crashed browser, etc.
This can make tests process hang. To prevent these situations timeouts can be used. Timeouts can be set explicitly for flaky parts of code, or implicitly in a config.
>>>>>>> timeouts
> Previous timeout implementation was disabled as it had no effect when dealing with steps and promises.
### Steps Timeout
Expand Down Expand Up @@ -236,6 +243,49 @@ A timeout for a group of tests can be set on Feature level via options.
Feature('flaky tests', { timeout: 30 })
```
### Sum Up
Let's list all available timeout options.
Timeouts can be set globally in config:
```js
// in codecept.confg.js:
{ // ...
timeout: 30, // limit all tests in all suites to 30 secs

plugins: {
stepTimeout: {
enabled: true,
timeout: 10, // limit all steps except waiters to 10 secs
}
}
}

```
or inside a test file:
```js
// limit all tests in this suite to 10 secs
Feature('tests with timeout', { timeout: 10 });

// limit this test to 20 secs
Scenario('a test with timeout', { timeout: 20 }, ({ I }) => {
// limit step to 5 seconds
I.limitTime(5).click('Link');
});
```
Global timeouts will be overridden by explicit timeouts of a test or steps.
### Disable Timeouts
To execute tests ignoring all timeout settings use `--no-timeouts` option:
```
npx codeceptjs run --no-timeouts
```
## Dynamic Configuration
Expand Down
2 changes: 1 addition & 1 deletion docs/helpers/ApiDataFactory.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,6 @@ I.haveMultiple('post', 3, { author: 'davert' });

[2]: https://www.npmjs.com/package/faker

[3]: https://codecept.io/helpers/REST/
[3]: http://codecept.io/helpers/REST/

[4]: https://github.com/axios/axios#request-config
16 changes: 8 additions & 8 deletions docs/helpers/Appium.md
Original file line number Diff line number Diff line change
Expand Up @@ -1315,7 +1315,7 @@ I.defineTimeout({ implicit: 10000, pageLoad: 10000, script: 5000 });

#### Parameters

- `timeouts` **WebdriverIO.Timeouts** WebDriver timeouts object.
- `timeouts` **any** WebDriver timeouts object.

### amOnPage

Expand Down Expand Up @@ -1884,31 +1884,31 @@ const width = await I.grabElementBoundingRect('h3', 'width');

Returns **([Promise][14]&lt;DOMRect> | [Promise][14]&lt;[number][8]>)** Element bounding rectangle

[1]: https://codecept.io/helpers/WebDriver/
[1]: http://codecept.io/helpers/WebDriver/

[2]: https://appium.io/
[2]: http://appium.io/

[3]: https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md

[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String

[5]: http://v4.webdriver.io/api/mobile/setNetworkConnection.html
[5]: http://webdriver.io/api/mobile/setNetworkConnection.html

[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

[7]: https://developer.android.com/reference/android/view/KeyEvent.html

[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number

[9]: http://v4.webdriver.io/api/mobile/touchAction.html
[9]: http://webdriver.io/api/mobile/touchAction.html

[10]: http://v4.webdriver.io/api/mobile/swipe.html
[10]: http://webdriver.io/api/mobile/swipe.html

[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array

[12]: http://v4.webdriver.io/api/mobile/rotate.html
[12]: http://webdriver.io/api/mobile/rotate.html

[13]: http://v4.webdriver.io/api/mobile/setImmediateValue.html
[13]: http://webdriver.io/api/mobile/setImmediateValue.html

[14]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise

Expand Down
2 changes: 1 addition & 1 deletion docs/helpers/GraphQLDataFactory.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ I.mutateMultiple('createUser', 3, { age: 25 });

[2]: https://www.npmjs.com/package/faker

[3]: https://codecept.io/helpers/GraphQL/
[3]: http://codecept.io/helpers/GraphQL/

[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String

Expand Down
4 changes: 2 additions & 2 deletions docs/helpers/Nightmare.md
Original file line number Diff line number Diff line change
Expand Up @@ -1194,10 +1194,10 @@ I.waitToHide('#popup');
[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[12]: https://electron.atom.io/docs/api/web-contents/#webcontentssendinputeventevent
[12]: http://electron.atom.io/docs/api/web-contents/#webcontentssendinputeventevent
[13]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[14]: https://github.com/segmentio/nightmare/blob/master/Readme.md#cookiessetcookie
[15]: https://electron.atom.io/docs/api/web-contents/#contentssendinputeventevent
[15]: http://electron.atom.io/docs/api/web-contents/#contentssendinputeventevent
2 changes: 1 addition & 1 deletion docs/helpers/Playwright.md
Original file line number Diff line number Diff line change
Expand Up @@ -1961,7 +1961,7 @@ I.waitUrlEquals('http://127.0.0.1:8000/info');

[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

[8]: https://jster.net/category/windows-modals-popups
[8]: http://jster.net/category/windows-modals-popups

[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String

Expand Down
2 changes: 1 addition & 1 deletion docs/helpers/Puppeteer.md
Original file line number Diff line number Diff line change
Expand Up @@ -2024,7 +2024,7 @@ I.waitUrlEquals('http://127.0.0.1:8000/info');
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[7]: https://jster.net/category/windows-modals-popups
[7]: http://jster.net/category/windows-modals-popups
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
Expand Down
18 changes: 9 additions & 9 deletions docs/helpers/WebDriver.md
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ I.defineTimeout({ implicit: 10000, pageLoad: 10000, script: 5000 });

#### Parameters

- `timeouts` **WebdriverIO.Timeouts** WebDriver timeouts object.
- `timeouts` **any** WebDriver timeouts object.

### dontSee

Expand Down Expand Up @@ -2169,23 +2169,23 @@ I.waitUrlEquals('http://127.0.0.1:8000/info');
- `urlPart` **[string][19]** value to check.
- `sec` **[number][22]** (optional, `1` by default) time in seconds to wait
[1]: https://webdriver.io/
[1]: http://webdriver.io/
[2]: https://codecept.io/webdriver/#testing-with-webdriver
[3]: https://codecept.io/acceptance/#smartwait
[3]: http://codecept.io/acceptance/#smartwait
[4]: https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities
[5]: https://webdriver.io/docs/timeouts/
[5]: http://webdriver.io/docs/timeouts.html
[6]: http://v4.webdriver.io/guide/getstarted/configuration.html
[6]: http://webdriver.io/guide/getstarted/configuration.html
[7]: https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/IE/Options.html
[8]: https://aerokube.com/selenoid/latest/
[9]: http://v4.webdriver.io/guide/usage/cloudservices.html
[9]: http://webdriver.io/guide/usage/cloudservices.html
[10]: https://webdriver.io/docs/sauce-service.html
Expand All @@ -2201,13 +2201,13 @@ I.waitUrlEquals('http://127.0.0.1:8000/info');
[16]: https://github.com/PeterNgTr/codeceptjs-applitoolshelper
[17]: http://v4.webdriver.io/guide/usage/multiremote.html
[17]: http://webdriver.io/guide/usage/multiremote.html
[18]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[19]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[20]: https://jster.net/category/windows-modals-popups
[20]: http://jster.net/category/windows-modals-popups
[21]: https://webdriver.io/docs/timeouts.html
Expand All @@ -2219,7 +2219,7 @@ I.waitUrlEquals('http://127.0.0.1:8000/info');
[25]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
[26]: http://v4.webdriver.io/api/protocol/execute.html
[26]: http://webdriver.io/api/protocol/execute.html
[27]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
Expand Down
10 changes: 9 additions & 1 deletion docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,10 @@ Use it in your tests:
```js
// retry these steps 5 times before failing
await retryTo((tryNum) => {
<<<<<<< HEAD
I.switchTo('#editor frame');
=======
>>>>>>> timeouts
I.click('Open');
I.see('Opened')
}, 5);
Expand All @@ -655,6 +659,10 @@ Set polling interval as 3rd argument (200ms by default):
```js
// retry these steps 5 times before failing
await retryTo((tryNum) => {
<<<<<<< HEAD
I.switchTo('#editor frame');
=======
>>>>>>> timeouts
I.click('Open');
I.see('Opened')
}, 5, 100);
Expand Down Expand Up @@ -869,7 +877,7 @@ Possible config options:
- `fullPageScreenshots`: should full page screenshots be used. Default: false.
- `output`: a directory where reports should be stored. Default: `output`.
- `screenshotsForAllureReport`: If Allure plugin is enabled this plugin attaches each saved screenshot to allure report. Default: false.
- `disableScreenshotOnFail` : Disables the capturing of screeshots after the failed step. Default: true.
- \`disableScreenshotOnFail : Disables the capturing of screeshots after the failed step. Default: true.
### Parameters
Expand Down
5 changes: 4 additions & 1 deletion lib/actor.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ class Actor {
* @inner
*/
limitTime(timeout) {
event.dispatcher.once(event.step.before, (step) => {
if (!store.timeouts) return this;

event.dispatcher.prependOnceListener(event.step.before, (step) => {
output.log(`Timeout to ${step}: ${timeout}s`);
step.totalTimeout = timeout * 1000;
});

return this;
}

Expand Down
1 change: 1 addition & 0 deletions lib/codecept.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Codecept {
global.inject = container.support;
global.share = container.share;
global.secret = require('./secret').secret;
global.codecept_debug = output.debug;
global.codeceptjs = require('./index'); // load all objects

// BDD
Expand Down
2 changes: 2 additions & 0 deletions lib/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const MochaFactory = require('./mochaFactory');
const recorder = require('./recorder');
const event = require('./event');
const WorkerStorage = require('./workerStorage');
const store = require('./store');

let container = {
helpers: {},
Expand Down Expand Up @@ -45,6 +46,7 @@ class Container {
container.support = createSupportObjects(config.include || {});
container.plugins = createPlugins(config.plugins || {}, opts);
if (config.gherkin) loadGherkinSteps(config.gherkin.steps || []);
if (opts && typeof opts.timeouts === 'boolean') store.timeouts = opts.timeouts;
}

/**
Expand Down
8 changes: 7 additions & 1 deletion lib/listener/timeout.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@ const event = require('../event');
const output = require('../output');
const recorder = require('../recorder');
const Config = require('../config');
const { timeouts } = require('../store');

module.exports = function () {
let timeout;
let timeoutStack = [];
let currentTest;
let currentTimeout;

if (!timeouts) {
console.log('Timeouts were disabled');
return;
}

event.dispatcher.on(event.suite.before, (suite) => {
timeoutStack = [];
const globalTimeout = Config.get('timeout');
if (globalTimeout) {
if (globalTimeout >= 1000) {
console.log(`Warning: Timeout was set to ${globalTimeout}sec.\nGlobal timeout should be specified in seconds.`);
console.log(`Warning: Timeout was set to ${globalTimeout}secs.\nGlobal timeout should be specified in seconds.`);
}
timeoutStack.push(globalTimeout);
}
Expand Down
6 changes: 3 additions & 3 deletions lib/plugin/allure.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,9 @@ module.exports = (config) => {
function finishMetastep(level) {
const metaStepsToFinish = currentMetaStep.splice(maxLevel - level);
metaStepsToFinish.forEach(() => {
// only if the current step is of type Step, end it.
if (reporter.suites && reporter.suites.length && reporter.suites[0].currentStep && reporter.suites[0].currentStep.constructor.name === 'Step') {
reporter.endStep('passed');
// only if the current step is of type Step, end it.
if (reporter.suites && reporter.suites.length && reporter.suites[0].currentStep && reporter.suites[0].currentStep.constructor.name === 'Step') {
reporter.endStep('passed');
}
});
}
Expand Down

0 comments on commit b5214d3

Please sign in to comment.