Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

codeceptjs

Package Overview
Dependencies
Maintainers
1
Versions
235
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

codeceptjs - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

docs/build/Mochawesome.js

2

bin/codecept.js

@@ -18,3 +18,3 @@ #!/usr/bin/env node

.alias('sh')
.description('Interative shell')
.description('Interactive shell')
.option('--verbose', 'output internal logging information')

@@ -21,0 +21,0 @@ .option('--profile [value]', 'configuration profile to be used')

@@ -1,3 +0,24 @@

# CodeceptJS 1.0
## 1.0.1
* Reporters improvements:
* Allows to execute [multiple reporters](http://codecept.io/advanced/#Multi-Reports)
* Added [Mochawesome](http://codecept.io/helpers/Mochawesome/) helper
* `addMochawesomeContext` method to add custom data to mochawesome reports
* Fixed Mochawesome context for failed screenshots.
* [WebDriverIO] improved click on context to match clickable element with a text inside. Fixes [#647](https://github.com/Codeception/CodeceptJS/issues/647)
* [Nightmare] Added `refresh` function by @awhanks
* fixed `Unhandled promise rejection (rejection id: 1): Error: Unknown wait type: pageLoad`
* support for tests with retries in html report
* be sure that change window size and timeouts completes before test
* [Nightmare] Fixed `[Wrapped Error] "codeceptjs is not defined"`; Reinjectiing client scripts to a webpage on changes.
* [Nightmare] Added more detailed error messages for `Wait*` methods
* [Nightmare] Fixed adding screenshots to Mochawesome
* [Nightmare] Fix unique screenshots names in Nightmare
* Fixed CodeceptJS work with hooks in helpers to finish codeceptJS correctly if errors appears in helpers hooks
* Create a new session for next test If selenium grid error received
* Create screenshots for failed hooks from a Feature file
* Fixed `retries` option
## 1.0
CodeceptJS hits first stable release. CodeceptJS provides a unified API for [web testing for Webdriverio](http://codecept.io/acceptance/), [Protractor](http://codecept.io/angular/), and [NightmareJS](http://codecept.io/nightmare/). Since 1.0 you can also **test mobile applications** in the similar manner with Appium.

@@ -19,2 +40,4 @@

---
We also introduced two new helpers for data management.

@@ -41,2 +64,4 @@ Using them you can easily prepare and cleanup data for your tests using public REST API.

---
Next notable feature is **[SmartWait](http://codecept.io/acceptance/#smartwait)** for WebDriverIO, Protractor, SeleniumWebdriver. When `smartwait` option is set, script will wait for extra milliseconds to locate an element before failing. This feature uses implicit waits of Selenium but turns them on only in applicable pieces. For instance, implicit waits are enabled for `seeElement` but disabled for `dontSeeElement`

@@ -46,19 +71,10 @@

#### Changelog
##### Changelog
* Minimal NodeJS version is 6.11.1 LTS
* Use `within` command with generators.
* [Data Driven Tests](http://codecept.io/advanced/#data-driven-tests) introduced.
* Print execution time per step in `--debug` mode. [#591](https://github.com/Codeception/CodeceptJS/pull/591) by @APshenkin
* [WebDriverIO] Fixed `seeNumberOfVisibleElements` by @BorisOsipov [#574](https://github.com/Codeception/CodeceptJS/pull/574)
* [WebDriverIO][Protractor][Nightmare] Added `disableScreenshots` option to disable screenshots on fail by @Apshenkin
* [WebDriverIO][Protractor][Nightmare] Added `uniqueScreenshotNames` option to generate unique names for screenshots on failure by @Apshenkin
* Lots of fixes for promise chain by @APshenkin [#568](https://github.com/Codeception/CodeceptJS/pull/568)
* Fix [#543](https://github.com/Codeception/CodeceptJS/issues/543) - After block not properly executed if Scenario fails
* Expected behavior in promise chains: `_beforeSuite` hooks from helpers -> `BeforeSuite` from test -> `_before` hooks from helpers -> `Before` from test - > Test steps -> `_failed` hooks from helpers (if test failed) -> `After` from test -> `_after` hooks from helpers -> `AfterSuite` from test -> `_afterSuite` hook from helpers.
* if during test we got errors from any hook (in test or in helper) - stop complete this suite and go to another
* if during test we got error from Selenium server - stop complete this suite and go to another
* [WebDriverIO][Protractor] if `restart` option is false - close all tabs expect one in `_after`.
* Complete `_after`, `_afterSuite` hooks even After/AfterSuite from test was failed
* Don't close browser between suites, when `restart` option is false. We should start browser only one time and close it only after all tests.
* Close tabs and clear local storage, if `keepCookies` flag is enabled
* [WebDriverIO][Nightmare] Fixed click on context; `click('text', '#el')` will throw exception if text is not found inside `#el`.

@@ -72,21 +88,31 @@ * [WebDriverIO][Protractor][SeleniumWebdriver] [SmartWait introduced](http://codecept.io/acceptance/#smartwait).

* [WebDriverIO] Methods added by @APshenkin:
* [grabCssPropertyFrom](http://codecept.io/helpers/WebDriverIO/#grabCssPropertyFrom)
* [seeTitleEquals](http://codecept.io/helpers/WebDriverIO/#seeTitleEquals)
* [seeTextEquals](http://codecept.io/helpers/WebDriverIO/#seeTextEquals)
* [seeCssPropertiesOnElements](http://codecept.io/helpers/WebDriverIO/#seeCssPropertiesOnElements)
* [seeAttributesOnElements](http://codecept.io/helpers/WebDriverIO/#seeAttributesOnElements)
* [grabNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#grabNumberOfVisibleElements)
* [waitInUrl](http://codecept.io/helpers/WebDriverIO/#waitInUrl)
* [waitUrlEquals](http://codecept.io/helpers/WebDriverIO/#waitUrlEquals)
* [waitForValue](http://codecept.io/helpers/WebDriverIO/#waitForValue)
* [waitNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#waitNumberOfVisibleElements)
* [switchToNextTab](http://codecept.io/helpers/WebDriverIO/#switchToNextTab)
* [switchToPreviousTab](http://codecept.io/helpers/WebDriverIO/#switchToPreviousTab)
* [closeCurrentTab](http://codecept.io/helpers/WebDriverIO/#closeCurrentTab)
* [openNewTab](http://codecept.io/helpers/WebDriverIO/#openNewTab)
* [refreshPage](http://codecept.io/helpers/WebDriverIO/#refreshPage)
* [scrollPageToBottom](http://codecept.io/helpers/WebDriverIO/#scrollPageToBottom)
* [scrollPageToTop](http://codecept.io/helpers/WebDriverIO/#scrollPageToTop)
* [grabBrowserLogs](http://codecept.io/helpers/WebDriverIO/#grabBrowserLogs)
* [grabCssPropertyFrom](http://codecept.io/helpers/WebDriverIO/#grabcsspropertyfrom)
* [seeTitleEquals](http://codecept.io/helpers/WebDriverIO/#seetitleequals)
* [seeTextEquals](http://codecept.io/helpers/WebDriverIO/#seetextequals)
* [seeCssPropertiesOnElements](http://codecept.io/helpers/WebDriverIO/#seecsspropertiesonelements)
* [seeAttributesOnElements](http://codecept.io/helpers/WebDriverIO/#seeattributesonelements)
* [grabNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#grabnumberofvisibleelements)
* [waitInUrl](http://codecept.io/helpers/WebDriverIO/#waitinurl)
* [waitUrlEquals](http://codecept.io/helpers/WebDriverIO/#waiturlequals)
* [waitForValue](http://codecept.io/helpers/WebDriverIO/#waitforvalue)
* [waitNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#waitnumberofvisibleelements)
* [switchToNextTab](http://codecept.io/helpers/WebDriverIO/#switchtonexttab)
* [switchToPreviousTab](http://codecept.io/helpers/WebDriverIO/#switchtoprevioustab)
* [closeCurrentTab](http://codecept.io/helpers/WebDriverIO/#closecurrenttab)
* [openNewTab](http://codecept.io/helpers/WebDriverIO/#opennewtab)
* [refreshPage](http://codecept.io/helpers/WebDriverIO/#refreshpage)
* [scrollPageToBottom](http://codecept.io/helpers/WebDriverIO/#scrollpagetobottom)
* [scrollPageToTop](http://codecept.io/helpers/WebDriverIO/#scrollpagetotop)
* [grabBrowserLogs](http://codecept.io/helpers/WebDriverIO/#grabbrowserlogs)
* Use mkdirp to create output directory. [#592](https://github.com/Codeception/CodeceptJS/pull/592) by @vkramskikh
* [WebDriverIO] Fixed `seeNumberOfVisibleElements` by @BorisOsipov [#574](https://github.com/Codeception/CodeceptJS/pull/574)
* Lots of fixes for promise chain by @APshenkin [#568](https://github.com/Codeception/CodeceptJS/pull/568)
* Fix [#543](https://github.com/Codeception/CodeceptJS/issues/543) - After block not properly executed if Scenario fails
* Expected behavior in promise chains: `_beforeSuite` hooks from helpers -> `BeforeSuite` from test -> `_before` hooks from helpers -> `Before` from test - > Test steps -> `_failed` hooks from helpers (if test failed) -> `After` from test -> `_after` hooks from helpers -> `AfterSuite` from test -> `_afterSuite` hook from helpers.
* if during test we got errors from any hook (in test or in helper) - stop complete this suite and go to another
* if during test we got error from Selenium server - stop complete this suite and go to another
* [WebDriverIO][Protractor] if `restart` option is false - close all tabs expect one in `_after`.
* Complete `_after`, `_afterSuite` hooks even After/AfterSuite from test was failed
* Don't close browser between suites, when `restart` option is false. We should start browser only one time and close it only after all tests.
* Close tabs and clear local storage, if `keepCookies` flag is enabled
* Fix TypeError when using babel-node or ts-node on node.js 7+ [#586](https://github.com/Codeception/CodeceptJS/pull/586) by @vkramskikh

@@ -493,2 +519,2 @@ * [Nightmare] fixed usage of `_locate`

* Fixed creating output dir when it already exists on init by @alfirin
* Fixed loading of custom helpers
* Fixed loading of custom helpers

@@ -16,3 +16,2 @@ # Acceptance Testing

```js

@@ -204,2 +203,3 @@ I.amOnPage('/login');

```
More wait actions can be found in helper's reference.

@@ -206,0 +206,0 @@

@@ -32,3 +32,3 @@ # Advanced Usage

```
```sh
✓ Test Login | {"login":"davert","password":"123456"}

@@ -58,3 +58,3 @@ ✓ Test Login | {"login":"admin","password":"123456"}

```
```sh
codeceptjs run --grep @slow

@@ -75,3 +75,3 @@ ```

```
```sh
codeceptjs run --debug

@@ -84,3 +84,3 @@ ```

```
```sh
node $NODE_DEBUG_OPTION ./node_modules/.bin/codeceptjs run

@@ -93,3 +93,2 @@ ```

```js

@@ -96,0 +95,0 @@ "multiple": {

@@ -1,6 +0,6 @@

## AngularJS E2E Testing with CodeceptJS
# AngularJS E2E Testing with CodeceptJS
### Introduction
## Introduction
CodeceptJS is an acceptance testing framework. In diversified world of JavaScript testing libraries it aims to create a unified high level API for end-to-end testing, powered by differnet backends.
CodeceptJS is an acceptance testing framework. In diversified world of JavaScript testing libraries it aims to create a unified high level API for end-to-end testing, powered by different backends.
CodeceptJS allows you to write a test and switch in config execution drivers: will it be *wedriverio*, *selenium-webdriver*, or *protractor* depends on you.

@@ -10,3 +10,3 @@ This way you aren't be bound to implementation, and your acceptance tests will work no matter of framework running them.

As you know, [Protractor](http://www.protractortest.org/#/) is an official tool for testing AngularJS applications.
CodeceptJS should not be considerend as alternative to Protractor but a testing framework utilizing this powerful library.
CodeceptJS should not be considered as alternative to Protractor but a testing framework utilizing this powerful library.

@@ -86,3 +86,3 @@ ![](http://codecept.io/images/angular-protractor.png)

You will be asked questions about initial configuration, make sure you select Protractor helper.
If you didn't have Protracotr library it **will be installed**.
If you didn't have Protractor library it **will be installed**.
Please agree to extend steps, and use `http://todomvc.com/examples/angularjs/` as a url for Protractor helper.

@@ -121,3 +121,3 @@

After that you can start writing your first CodeceptJS/Angular tests.
Please look into the reference of [Protractor helper])(http://codecept.io/helpers/Protractor/) for all available actions.
Please look into the reference of [Protractor helper](http://codecept.io/helpers/Protractor/) for all available actions.
You can also run `list` command to see methods of I:

@@ -157,3 +157,3 @@

```
```sh
$ codeceptjs run --steps

@@ -226,3 +226,3 @@

```
```sh
{css: 'button'}

@@ -232,2 +232,3 @@ {repeater: "todo in todos"}

```
When we deal with clicks, CodeceptJS can take a text and search a web page for a valid clickable element with that text.

@@ -258,2 +259,3 @@ So links and buttons can be searched by their text.

```
And that's all, method is available to use as `I.createTodo(title)`:

@@ -260,0 +262,0 @@

@@ -13,3 +13,3 @@ # Codecept

Executes hooks and bootstrap.
If bootstrap is async second parameter is required.
If bootstrap is async, second parameter is required.

@@ -16,0 +16,0 @@ **Parameters**

@@ -32,3 +32,3 @@ # Basics

Tests are written in synchronous way. Test scenarios should be linear, so tests by themseleves should not include promises or callbacks as well.
Tests are written in synchronous way. Test scenarios should be linear, so tests by themselves should not include promises or callbacks as well.
However, behind the scene **all actions are wrapped in promises** inside the `I` object.

@@ -151,3 +151,3 @@ [Global promise](https://github.com/Codeception/CodeceptJS/blob/master/lib/recorder.js) chain is initialized before each test and all `I.*` calls will be appended to it as well as setup and teardown.

```
```sh
codeceptjs def

@@ -218,2 +218,3 @@ ```

```
Every Scenario inside this feature will be rerun 3 times.

@@ -233,2 +234,3 @@ You can make an exception for a specific scenario by passing `retries` option to it:

```
"Really complex" test will be restarted 3 times,

@@ -235,0 +237,0 @@ while "Not that complex" test will be rerun only once.

@@ -19,3 +19,3 @@ 'use strict';

*
* ### Use Case
* ## Use Case
*

@@ -41,3 +41,2 @@ * Acceptance tests interact with a websites using UI and real browser.

*
*
* ### Setup

@@ -47,3 +46,3 @@ *

*
* ```
* ```sh
* npm i rosie faker --save-dev`

@@ -50,0 +49,0 @@ * ```

@@ -24,3 +24,3 @@ 'use strict';

*
* #### Appium Installation
* ## Appium Installation
*

@@ -32,3 +32,3 @@ * Appium is an open source test automation framework for use with native, hybrid and mobile web apps that implements the WebDriver protocol.

*
* ```
* ```sh
* npm install -g appium

@@ -39,8 +39,6 @@ * ```

*
* ### Configuration
* ## Helper configuration
*
* This helper should be configured in codecept.json or codecept.conf.js
*
* #### Appium configuration
*
* * `port`: Appium port

@@ -126,2 +124,4 @@ * * `restart`: restart browser or app between tests (default: true), if set to false cookies will be cleaned but browser window will be kept and for apps nothing will be changed.

this.isRunning = false;
// override defaults with config

@@ -174,26 +174,32 @@ this.options = Object.assign(this.options, config);

}
if (this.options.timeouts && this.isWeb) {
this.defineTimeout(this.options.timeouts);
}
if (this.options.windowSize === 'maximize' && !this.platform) {
this.browser.execute('return [screen.width, screen.height]').then((res) => {
return this.browser.windowHandleSize({
width: res.value[0],
height: res.value[1]
});
});
} else if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0 && !this.platform) {
let dimensions = this.options.windowSize.split('x');
this.browser.windowHandleSize({
width: dimensions[0],
height: dimensions[1]
});
}
return this.browser;
return this.browser.then(() => {
this.isRunning = true;
let promisesList = [];
if (this.options.timeouts && this.isWeb) {
promisesList.push(this.defineTimeout(this.options.timeouts));
}
if (this.options.windowSize === 'maximize' && !this.platform) {
promisesList.push(this.browser.execute('return [screen.width, screen.height]').then((res) => {
return this.browser.windowHandleSize({
width: res.value[0],
height: res.value[1]
});
}));
} else if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0 && !this.platform) {
let dimensions = this.options.windowSize.split('x');
promisesList.push(this.browser.windowHandleSize({
width: dimensions[0],
height: dimensions[1]
}));
}
return Promise.all(promisesList);
});
}
_after() {
if (this.options.restart) return this.browser.end();
if (!this.isRunning) return;
if (this.options.restart) {
this.isRunning = false;
return this.browser.end();
}
if (this.isWeb && !this.platform) {

@@ -200,0 +206,0 @@ return super._after();

@@ -9,2 +9,3 @@ 'use strict';

const truth = require('../assert/truth').truth;
const hashCode = require('../utils').hashCode;
const xpathLocator = require('../utils').xpathLocator;

@@ -32,3 +33,3 @@ const fileExists = require('../utils').fileExists;

*
* ### Configuration
* ## Configuration
*

@@ -39,2 +40,5 @@ * This helper should be configured in codecept.json

* * `restart` (optional, default: true) - restart browser between tests.
* * `disableScreenshots` (optional, default: false) - don't save screenshot on failure
* * `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
* * `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
* * `keepCookies` (optional, default: false) - keep cookies between tests when `restart` set to false.

@@ -62,2 +66,3 @@ * * `waitForAction`: (optional) how long to wait after click, doubleClick or PressKey actions in ms. Default: 500

restart: true,
keepBrowserState: false,
keepCookies: false,

@@ -187,3 +192,3 @@ js_errors: null

if (!this.options.restart && !this.isRunning) {
this.isRunning = true;
this.debugSection('Session', 'Starting singleton browser session');
return this._startBrowser();

@@ -194,5 +199,4 @@ }

_before() {
if (this.options.restart) {
return this._startBrowser();
}
if (this.options.restart) return this._startBrowser();
if (!this.isRunning) return this._startBrowser();
return this.browser;

@@ -202,6 +206,14 @@ }

_after() {
if (!this.isRunning) return;
if (this.options.restart) {
this.isRunning = false;
return this._stopBrowser();
}
if (this.options.keepCookies) return;
if (this.options.keepBrowserState) return;
if (this.options.keepCookies) {
return Promise.all([this.executeScript(function () {
return localStorage.clear();
})]);
}
this.debugSection('Session', 'cleaning cookies and localStorage');
return Promise.all([this.browser.cookies.clearAll(), this.executeScript(function () {

@@ -216,3 +228,3 @@ return localStorage.clear();

_finishTest() {
if (!this.options.restart) {
if (!this.options.restart && this.isRunning) {
this._stopBrowser();

@@ -224,11 +236,16 @@ }

this.browser = this.Nightmare(this.options);
this.browser.on('dom-ready', () => this._injectClientScripts());
this.browser.on('console', (type, message) => {
this.debug(`${type}: ${message}`);
return this.browser.then(() => {
this.isRunning = true;
this.browser.on('dom-ready', () => this._injectClientScripts());
this.browser.on('did-start-loading', () => this._injectClientScripts());
this.browser.on('will-navigate', () => this._injectClientScripts());
this.browser.on('console', (type, message) => {
this.debug(`${type}: ${message}`);
});
if (this.options.windowSize) {
let size = this.options.windowSize.split('x');
return this.browser.viewport(parseInt(size[0]), parseInt(size[1]));
}
});
if (this.options.windowSize) {
let size = this.options.windowSize.split('x');
return this.browser.viewport(parseInt(size[0]), parseInt(size[1]));
}
}

@@ -1139,6 +1156,13 @@

this.browser.options.waitTimeout = sec * 1000 || this.options.waitForTimeout;
sec = this.browser.options.waitForTimeout / 1000;
return this.browser.wait(function (by, locator, text) {
return codeceptjs.findElement(by, locator).innerText.indexOf(text) > -1;
}, lctype(locator), lcval(locator), text);
}, lctype(locator), lcval(locator), text).catch((err) => {
if (err.indexOf(`Cannot read property`) > -1) {
throw new Error(`element (${JSON.stringify(context)}) is not in DOM. Unable to wait text.`);
} else if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
throw new Error(`there is no element(${JSON.stringify(context)}) with text "${text}" after ${sec} sec`);
} else throw err;
});
}

@@ -1159,2 +1183,3 @@

this.browser.options.waitTimeout = sec * 1000 || this.options.waitForTimeout;
sec = this.browser.options.waitForTimeout / 1000;
locator = guessLocator(locator) || { css: locator};

@@ -1166,3 +1191,7 @@

return el.offsetParent !== null;
}, lctype(locator), lcval(locator));
}, lctype(locator), lcval(locator)).catch((err) => {
if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
throw new Error(`element (${JSON.stringify(locator)}) still not visible on page after ${sec} sec`);
} else throw err;
});
}

@@ -1184,2 +1213,3 @@

this.browser.options.waitTimeout = sec * 1000 || this.options.waitForTimeout;
sec = this.browser.options.waitForTimeout / 1000;
locator = guessLocator(locator) || { css: locator};

@@ -1189,6 +1219,17 @@

return codeceptjs.findElement(by, locator) !== null;
}, lctype(locator), lcval(locator));
}, lctype(locator), lcval(locator)).catch((err) => {
if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
throw new Error(`element (${JSON.stringify(locator)}) still not present on page after ${sec} sec`);
} else throw err;
});
}
/**
* Reload the page
*/
refresh() {
return this.browser.refresh();
}
/**
* Saves a screenshot to ouput folder (set in codecept.json).

@@ -1229,6 +1270,8 @@ Filename is relative to output folder.

if (!this.options.disableScreenshots) {
let fileName = clearString(test.title) + '.failed.png';
let fileName = clearString(test.title);
if (test.ctx && test.ctx.test && test.ctx.test.type == 'hook') fileName = clearString(`${test.title}_${test.ctx.test.title}`);
if (this.options.uniqueScreenshotNames) {
fileName = test.title.substring(0, 10).replace(/ /g, '_') + '-' + hashCode(test.title) + '-' + hashCode(test.file) +
'.failed.png';
fileName = `${fileName.substring(0, 10)}-${hashCode(fileName)}-${hashCode(test.file)}.failed.png`;
} else {
fileName = fileName + '.failed.png';
}

@@ -1235,0 +1278,0 @@ promisesList.push(this.saveScreenshot(fileName, true));

@@ -22,4 +22,6 @@ 'use strict';

*
* #### Selenium Installation
* ## Backends
*
* ### Selenium Installation
*
* 1. Download [Selenium Server](http://docs.seleniumhq.org/download/)

@@ -29,3 +31,3 @@ * 2. For Chrome browser install [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/getting-started), for Firefox browser install [GeckoDriver](https://github.com/mozilla/geckodriver).

*
* #### PhantomJS Installation
* ### PhantomJS Installation
*

@@ -38,3 +40,3 @@ * PhantomJS is a headless alternative to Selenium Server that implements the WebDriver protocol.

*
* ### Configuration
* ## Configuration
*

@@ -45,5 +47,8 @@ * This helper should be configured in codecept.json

* * `browser` - browser in which perform testing
* * `driver` - which protrator driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `driver` - which protractor driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `restart` (optional, default: true) - restart browser between tests.
* * `smartWait`: (optional) **enables [SmartWait](http://codecept.io/acceptance/#smartwait)**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000
* * `disableScreenshots` (optional, default: false) - don't save screenshot on failure
* * `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
* * `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
* * `seleniumAddress` - Selenium address to connect (default: http://localhost:4444/wd/hub)

@@ -112,3 +117,3 @@ * * `rootElement` - Root element of AngularJS application (default: body)

this.isProtractor5 = !requireg('protractor').wrapDriver;
this.context = this.options.rootElement;
try {

@@ -121,2 +126,3 @@ // get selenium-webdriver

}
return Promise.resolve(Runner);
}

@@ -145,3 +151,2 @@

this.browser = runner.createBrowser();
global.browser = this.browser;

@@ -153,13 +158,12 @@ global.$ = this.browser.$;

global.ExpectedConditions = EC = this.browser.ExpectedConditions;
let promisesList = [];
if (this.options.windowSize == 'maximize') {
this.resizeWindow(this.options.windowSize);
promisesList.push(this.resizeWindow(this.options.windowSize));
}
if (this.options.windowSize) {
var size = this.options.windowSize.split('x');
this.resizeWindow(parseInt(size[0]), parseInt(size[1]));
promisesList.push(this.resizeWindow(parseInt(size[0]), parseInt(size[1])));
}
return this.browser;
return Promise.all(promisesList).then(() => this.isRunning = true);
}

@@ -169,5 +173,3 @@

super._before();
this.amInsideAngularApp();
this.context = this.options.rootElement;
return this.browser;
return this.amInsideAngularApp();
}

@@ -224,5 +226,2 @@

amInsideAngularApp() {
if (this.browser.driver && this.insideAngular) {
return; // already inside angular
}
this.browser.ignoreSynchronization = false;

@@ -229,0 +228,0 @@ return Promise.resolve(this.insideAngular = true);

@@ -25,4 +25,6 @@ 'use strict';

*
* #### Selenium Installation
* ## Backends
*
* ### Selenium Installation
*
* 1. Download [Selenium Server](http://docs.seleniumhq.org/download/)

@@ -33,3 +35,3 @@ * 2. For Chrome browser install [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/getting-started), for Firefox browser install [GeckoDriver](https://github.com/mozilla/geckodriver).

*
* #### PhantomJS Installation
* ### PhantomJS Installation
*

@@ -42,3 +44,3 @@ * PhantomJS is a headless alternative to Selenium Server that implements [the WebDriver protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol).

*
* ### Configuration
* ## Configuration
*

@@ -49,5 +51,8 @@ * This helper should be configured in codecept.json

* * `browser` - browser in which perform testing
* * `driver` - which protrator driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `driver` - which protractor driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `restart` - restart browser between tests (default: true).
* * `smartWait`: (optional) **enables SmartWait**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000
* * `disableScreenshots` (optional, default: false) - don't save screenshot on failure
* * `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
* * `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
* * `keepCookies` (optional, default: false) - keep cookies between tests when `restart` set to false.*

@@ -95,2 +100,3 @@ * * `seleniumAddress` - Selenium address to connect (default: http://localhost:4444/wd/hub)

restart: true,
keepBrowserState: false,
keepCookies: false,

@@ -131,2 +137,4 @@ disableScreenshots: false,

if (this.options.proxy) this.browserBuilder.setProxy(this.options.proxy);
return Promise.resolve(this.browserBuilder);
}

@@ -151,11 +159,10 @@

this.browser = this.browserBuilder.build();
let promisesList = [];
if (this.options.windowSize == 'maximize') {
this.resizeWindow(this.options.windowSize);
promisesList.push(this.resizeWindow(this.options.windowSize));
} else if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0) {
var size = this.options.windowSize.split('x');
this.resizeWindow(size[0], size[1]);
promisesList.push(this.resizeWindow(size[0], size[1]));
}
return this.browser;
return Promise.all(promisesList).then(() => this.isRunning = true);
}

@@ -166,3 +173,2 @@

this.debugSection('Session', 'Starting singleton browser session');
this.isRunning = true;
return this._startBrowser();

@@ -173,9 +179,13 @@ }

_before() {
if (this.options.restart && !this.options.manualStart) {
return this._startBrowser();
}
if (this.options.restart && !this.options.manualStart) return this._startBrowser();
if (!this.isRunning && !this.options.manualStart) return this._startBrowser();
}
_after() {
if (this.options.restart) return this.browser.quit();
if (!this.isRunning) return;
if (this.options.restart) {
this.isRunning = false;
return this.browser.quit();
}
if (this.options.keepBrowserState) return;
if (this.options.keepCookies) return Promise.all([this.browser.executeScript('localStorage.clear();'), this.closeOtherTabs()]);

@@ -191,3 +201,3 @@ // if browser should not be restarted

_finishTest() {
if (!this.options.restart) return this.browser.quit();
if (!this.options.restart && this.isRunning) return this.browser.quit();
}

@@ -199,9 +209,17 @@

if (!this.options.disableScreenshots) {
let fileName = clearString(test.title) + '.failed.png';
let fileName = clearString(test.title);
if (test.ctx && test.ctx.test && test.ctx.test.type == 'hook') fileName = clearString(`${test.title}_${test.ctx.test.title}`);
if (this.options.uniqueScreenshotNames) {
fileName = clearString(test.title.substring(0, 10)) + '-' + hashCode(test.title) + '-' + hashCode(test.file) + '.failed.png';
fileName = `${fileName.substring(0, 10)}-${hashCode(fileName)}-${hashCode(test.file)}.failed.png`;
} else {
fileName = fileName + '.failed.png';
}
promisesList.push(this.saveScreenshot(fileName, true));
}
return Promise.all(promisesList);
return Promise.all(promisesList).catch((err) => {
if (err && err.type && err.type == "RuntimeError" && err.message && (err.message.indexOf("was terminated due to") > -1 || err.message.indexOf("no such window: target window already closed" > -1))) {
this.isRunning = false;
return;
}
});
}

@@ -208,0 +226,0 @@

@@ -11,3 +11,3 @@ # Commands

```
```sh
codeceptjs run

@@ -18,3 +18,3 @@ ```

```
```sh
codeceptjs run -c test

@@ -25,3 +25,3 @@ ```

```
```sh
codeceptjs run --grep "signin"

@@ -32,3 +32,3 @@ ```

```
```sh
codeceptjs run github_test.js

@@ -39,3 +39,3 @@ ```

```
```sh
codeceptjs run github_test.js --steps

@@ -46,3 +46,3 @@ ```

```
```sh
codeceptjs run github_test.js --debug

@@ -53,3 +53,3 @@ ```

```
```sh
codeceptjs run github_test.js --verbose

@@ -60,3 +60,3 @@ ```

```
```sh
codeceptjs run -c my.codecept.conf.js

@@ -68,3 +68,3 @@ codeceptjs run --config path/to/codecept.json

```
```sh
codeceptjs run --override '{ "helpers": {"WebDriverIO": {"browser": "chrome"}}}'

@@ -75,3 +75,3 @@ ```

```
```sh
codeceptjs run --reporter xunit

@@ -82,3 +82,2 @@ ```

## Run multiple

@@ -88,3 +87,3 @@

```
```sh
codeceptjs run-multiple smoke:chrome regression:firefox

@@ -97,3 +96,3 @@ ```

```
```sh
codeceptjs init

@@ -104,3 +103,3 @@ ```

```
```sh
codecept init test

@@ -113,3 +112,3 @@ ```

```
```sh
codeceptjs shell

@@ -122,3 +121,3 @@ ```

```
```sh
codeceptjs generate test

@@ -129,3 +128,3 @@ ```

```
```sh
codeceptjs generate pageobject

@@ -136,3 +135,3 @@ ```

```
```sh
codeceptjs generate helper

@@ -145,3 +144,3 @@ ```

```
```sh
codeceptjs def

@@ -161,6 +160,6 @@ ```

Prints all avialable methods of `I` to console
Prints all available methods of `I` to console
```
```sh
codeceptjs list
```

@@ -10,3 +10,3 @@ # Configuration

* **tests**: `"./*_test.js"` - pattern to locate tests
* **include**: `{}` - actors and pageobjects to be registered in DI container and included in tests.
* **include**: `{}` - actors and pageobjects to be registered in DI container and i ncluded in tests.
* **timeout**: `10000` - default tests timeout

@@ -16,9 +16,8 @@ * **output**: `"./output"` - where to store failure screenshots, etc

* **mocha**: `{}` - mocha options, [reporters](http://codecept.io/reports/) can be configured here
* **multiple**: `{}` - multiple options, see [#PR439](https://github.com/Codeception/CodeceptJS/pull/439) for more details
* **multiple**: `{}` - multiple options, see [#PR439]( https://github.com/Codeception/CodeceptJS/pull/439) for more details
* **name**: `"tests"` - test suite name (not used)
* **bootstrap**: `"./bootstrap.js"` - an option to run code _before_ tests are run. See [Hooks](#hooks)).
* **teardown**: - an option to run code _after_ tests are run. See [Hooks](#hooks)).
* **translation**: - [locale](http://codecept.io/translation/) to be used to print steps output, as well as used in source code.
* **teardown**: - an option to run code _after_ tests are run. See [Hooks](#hooks).
* **translation**: - [locale](http://codecept.io/translation/) to be used to print s teps output, as well as used in source code.
## Dynamic Configuration

@@ -28,3 +27,3 @@

```
```sh
codeceptjs run -o '{ "helpers": {"WebDriverIO": {"browser": "firefox"}}}'

@@ -63,2 +62,8 @@ ```

If you prefer to store your configuration files in a different location, or with a different name, you can do that with `--config` or `-c:
```sh
codeceptjs run --config=./path/to/my/config.json
```
## Profile

@@ -72,3 +77,3 @@

```
```sh
codeceptjs run --profile firefox

@@ -75,0 +80,0 @@ ```

@@ -8,5 +8,5 @@ # Data Management

1. reset database completely between tests
2. create unique non-intersecting data sets per each test
3. create and delete data for a test
1. reset database completely between tests
2. create unique non-intersecting data sets per each test
3. create and delete data for a test

@@ -85,3 +85,2 @@ The most efficient way would be to allow test to control its data, i.e. the 3rd option.

## Data Generation with Factories

@@ -97,2 +96,3 @@

```
Just define how many items of any kind you need and ApiDataFactory will create them for you.

@@ -138,3 +138,3 @@ However, to make this work some preparations required.

Then, calling `I.have('user')` inside a test will create a new post for you.
Then, calling `I.have('user')` inside a test will create a new user for you.
This is done by sending POST request to `/api/users` URL. Response is returned and can be used in tests.

@@ -149,2 +149,1 @@

### done()

@@ -14,6 +14,5 @@ # Codeceptjs Docker

You can execute CodeceptJS with Nightmare locally with no extra configuration.
```
```sh
docker run --net=host -v $PWD:/tests codeception/codeceptjs

@@ -81,3 +80,3 @@ ```

```sh
$ docker build -t codeception/codeceptjs .
docker build -t codeception/codeceptjs .
```

@@ -63,3 +63,3 @@ # Helpers

```
```sh
codeceptjs def .

@@ -116,3 +116,2 @@ ```

```js

@@ -152,3 +151,3 @@ 'use strict';

does that for you, however you can enable them manually by placing helper to `helpers` section inside config file.
You can also pass additional config options to your helper from a config:
You can also pass additional config options to your helper from a config - **(please note, this example contains comments, while JSON format doesn't support them)**:

@@ -167,3 +166,2 @@ ```js

```
*(please note, this example contains comments, while JSON format doesn't support them)*

@@ -202,36 +200,36 @@ Config values will be stored inside helper in `this.config`. To get `defaultHost` value you can use

1) Failing if JS error occur in WebDriverIO:
1) Failing if JS error occur in WebDriverIO:
```js
class JSFailure extends codecept_helper {
```js
class JSFailure extends codecept_helper {
_before() {
this.err = null;
this.helpers['WebDriverIO'].browser.on('error', (e) => this.err = e);
}
_before() {
this.err = null;
this.helpers['WebDriverIO'].browser.on('error', (e) => this.err = e);
}
_afterStep() {
if (this.err) throw new Error('Browser JS error '+this.err);
}
}
_afterStep() {
if (this.err) throw new Error('Browser JS error '+this.err);
}
}
module.exports = JSFailure;
```
module.exports = JSFailure;
```
2) Wait for Ajax requests to complete after `click`:
2) Wait for Ajax requests to complete after `click`:
```js
class JSWait extends codecept_helper {
```js
class JSWait extends codecept_helper {
_afterStep(step) {
if (step.name == 'click') {
var jqueryActive = () => jQuery.active == 0;
return this.helpers['WebDriverIO'].waitUntil(jqueryActive);
_afterStep(step) {
if (step.name == 'click') {
var jqueryActive = () => jQuery.active == 0;
return this.helpers['WebDriverIO'].waitUntil(jqueryActive);
}
}
}
}
}
module.exports = JSWait;
```
module.exports = JSWait;
```
### done()

@@ -9,3 +9,3 @@ # ApiDataFactory

### Use Case
## Use Case

@@ -35,3 +35,5 @@ Acceptance tests interact with a websites using UI and real browser.

npm i rosie faker --save-dev`
```sh
npm i rosie faker --save-dev`
```

@@ -38,0 +40,0 @@ Create a factory file for a resource.

@@ -7,3 +7,3 @@ # Appium

#### Appium Installation
## Appium Installation

@@ -15,12 +15,12 @@ Appium is an open source test automation framework for use with native, hybrid and mobile web apps that implements the WebDriver protocol.

npm install -g appium
```sh
npm install -g appium
```
Launch the daemon: `appium`
### Configuration
## Helper configuration
This helper should be configured in codecept.json or codecept.conf.js
#### Appium configuration
- `port`: Appium port

@@ -27,0 +27,0 @@ - `restart`: restart browser or app between tests (default: true), if set to false cookies will be cleaned but browser window will be kept and for apps nothing will be changed.

@@ -10,3 +10,3 @@ # Nightmare

### Configuration
## Configuration

@@ -17,2 +17,5 @@ This helper should be configured in codecept.json

- `restart` (optional, default: true) - restart browser between tests.
- `disableScreenshots` (optional, default: false) - don't save screenshot on failure
- `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
- `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
- `keepCookies` (optional, default: false) - keep cookies between tests when `restart` set to false.

@@ -466,2 +469,6 @@ - `waitForAction`: (optional) how long to wait after click, doubleClick or PressKey actions in ms. Default: 500

## refresh
Reload the page
## resizeWindow

@@ -468,0 +475,0 @@

@@ -5,4 +5,6 @@ # Protractor

#### Selenium Installation
## Backends
### Selenium Installation
1. Download [Selenium Server](http://docs.seleniumhq.org/download/)

@@ -12,3 +14,3 @@ 2. For Chrome browser install [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/getting-started), for Firefox browser install [GeckoDriver](https://github.com/mozilla/geckodriver).

#### PhantomJS Installation
### PhantomJS Installation

@@ -21,3 +23,3 @@ PhantomJS is a headless alternative to Selenium Server that implements the WebDriver protocol.

### Configuration
## Configuration

@@ -28,5 +30,8 @@ This helper should be configured in codecept.json

- `browser` - browser in which perform testing
- `driver` - which protrator driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
- `driver` - which protractor driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
- `restart` (optional, default: true) - restart browser between tests.
- `smartWait`: (optional) **enables [SmartWait](http://codecept.io/acceptance/#smartwait)**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000
- `disableScreenshots` (optional, default: false) - don't save screenshot on failure
- `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
- `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
- `seleniumAddress` - Selenium address to connect (default: <http://localhost:4444/wd/hub>)

@@ -33,0 +38,0 @@ - `rootElement` - Root element of AngularJS application (default: body)

@@ -6,4 +6,6 @@ # SeleniumWebdriver

#### Selenium Installation
## Backends
### Selenium Installation
1. Download [Selenium Server](http://docs.seleniumhq.org/download/)

@@ -13,3 +15,3 @@ 2. For Chrome browser install [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/getting-started), for Firefox browser install [GeckoDriver](https://github.com/mozilla/geckodriver).

#### PhantomJS Installation
### PhantomJS Installation

@@ -22,3 +24,3 @@ PhantomJS is a headless alternative to Selenium Server that implements [the WebDriver protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol).

### Configuration
## Configuration

@@ -29,5 +31,8 @@ This helper should be configured in codecept.json

- `browser` - browser in which perform testing
- `driver` - which protrator driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
- `driver` - which protractor driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
- `restart` - restart browser between tests (default: true).
- `smartWait`: (optional) **enables SmartWait**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000
- `disableScreenshots` (optional, default: false) - don't save screenshot on failure
- `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
- `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
- `keepCookies` (optional, default: false) - keep cookies between tests when `restart` set to false.*

@@ -34,0 +39,0 @@ - `seleniumAddress` - Selenium address to connect (default: <http://localhost:4444/wd/hub>)

@@ -6,4 +6,6 @@ # WebDriverIO

#### Selenium Installation
## Backends
### Selenium Installation
1. Download [Selenium Server](http://docs.seleniumhq.org/download/)

@@ -15,3 +17,3 @@ 2. For Chrome browser install [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/getting-started),

#### PhantomJS Installation
### PhantomJS Installation

@@ -32,2 +34,5 @@ PhantomJS is a headless alternative to Selenium Server that implements the WebDriver protocol.

- `smartWait`: (optional) **enables [SmartWait](http://codecept.io/acceptance/#smartwait)**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000
- `disableScreenshots` (optional, default: false) - don't save screenshot on failure
- `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
- `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
- `keepCookies` (optional, default: false) - keep cookies between tests when `restart` set to false.

@@ -34,0 +39,0 @@ - `windowSize`: (optional) default window size. Set to `maximize` or a dimension in the format `640x480`.

@@ -19,3 +19,3 @@ # Hooks

##### Example: Async Bootstrap in a Function
### Example: Async Bootstrap in a Function

@@ -43,3 +43,3 @@ Add to `codecept.json`:

##### Example: Async Teardown in a Function
### Example: Async Teardown in a Function

@@ -62,3 +62,3 @@ Stopping a server from a previous example can be done in a similar manner.

##### Example: Bootstrap & Teardown Inside an Object
### Example: Bootstrap & Teardown Inside an Object

@@ -68,2 +68,3 @@ Examples above can be combined into one file.

Add to config (`codecept.json`):
```js

@@ -89,3 +90,3 @@ "bootstrap": "./server.js"

##### Example: Bootstrap & Teardown Inside Config
### Example: Bootstrap & Teardown Inside Config

@@ -114,3 +115,3 @@ If you are using JavaScript-style config `codecept.conf.js`, bootstrap and teardown functions can be placed inside of it:

## Hooks
## Custom Hooks

@@ -117,0 +118,0 @@ To extend internal CodeceptJS functionality you can use hooks.

# Installation
### Global
## Global
CodeceptJS can be installed via NPM globally
```
```sh
[sudo] npm install -g codeceptjs

@@ -13,3 +13,3 @@ ```

```
```sh
codeceptjs

@@ -20,3 +20,3 @@ ```

```
```sh
[sudo] npm install -g webdriverio

@@ -27,3 +27,3 @@ ```

```
```sh
[sudo] npm install -g protractor

@@ -34,7 +34,6 @@ ```

```
```sh
[sudo] npm install -g nightmare nightmare-upload
```
### Local

@@ -44,3 +43,3 @@

```
```sh
npm install --save-dev codeceptjs

@@ -51,3 +50,3 @@ ```

```
```sh
./node_modules/.bin/codeceptjs

@@ -58,3 +57,3 @@ ```

```
```sh
npm install webdriverio --save-dev

@@ -65,3 +64,3 @@ ```

```
```sh
npm install protractor --save-dev

@@ -72,10 +71,9 @@ ```

```
```sh
npm install nightmare nightmare-upload --save-dev
```
## Meta Packages
By default it doesn't install any backends like Webdriverio, Protracor, or Nightmare, so you need to install corresponding packages manually, or install one of the provided meta-packages:
By default it doesn't install any backends like Webdriverio, Protractor, or Nightmare, so you need to install corresponding packages manually, or install one of the provided meta-packages:

@@ -101,4 +99,4 @@ * [codeceptjs-webdriverio](https://www.npmjs.com/package/codeceptjs-webdriverio) - installs CodeceptJS + WebDriverIO

```
```sh
docker run --net=host selenium/standalone-chrome
```

@@ -21,2 +21,3 @@ # Mobile Testing

```
This test is easy to read and write. Also it will work both on iOS and Android devices.

@@ -31,3 +32,3 @@ Doesn't it sound cool?

```
```sh
npm i -g appium-doctor

@@ -40,3 +41,3 @@ ```

```
```sh
npm i -g appium

@@ -51,3 +52,3 @@ ```

```
```sh
appium

@@ -62,3 +63,3 @@ ```

```
```sh
codeceptjs init

@@ -68,3 +69,4 @@ ```

Select [Appium helper](http://codecept.io/helpers/Appium/) when asked.
```
```sh
? What helpers do you want to use?

@@ -78,5 +80,6 @@ ◯ WebDriverIO

```
You will also be asked for the platform and the application package.
```
```sh
? [Appium] Application package. Path to file or url

@@ -88,3 +91,2 @@ ```

```js

@@ -102,3 +104,3 @@ "helpers": {

```
```sh
codeceptjs gt

@@ -119,3 +121,3 @@ ```

I.hideDeviceKeyboard();
I.click('~input_preferedProgrammingLanguage');
I.click('~input_preferredProgrammingLanguage');
I.click('Javascript');

@@ -256,2 +258,3 @@ I.checkOption('#io.demo.testapp:id/input_adds');

```
Just as you can specify android, and ios-specific locators, you can do so for web:

@@ -258,0 +261,0 @@

@@ -52,3 +52,3 @@ # Blazing Fast Tests with Nightmare

```
```sh
docker run -d -p 4444:4444 selenium/standalone-firefox:2.53.0

@@ -60,3 +60,3 @@ codeceptjs run yahoo_test.js --steps

```
```sh
Yahoo basic test

@@ -75,3 +75,3 @@ > WebDriverIO._before

```
```sh
Yahoo basic test

@@ -101,3 +101,3 @@ > Nightmare._before

```
```sh
codeceptjs init

@@ -127,2 +127,3 @@ ```

```
Turn on the `show` option if you want to follow test progress in a window. This is very useful for debugging.

@@ -169,5 +170,5 @@ All other options can be taken from [NightmareJS API](https://github.com/segmentio/nightmare#api).

```sh
codeceptjs gh
```
codecepjs gh
```

@@ -182,2 +183,3 @@ Learn more about [Helpers](http://codecept.io/helpers/).

```
This way you can call [native Nightmare commands](https://github.com/segmentio/nightmare#interact-with-the-page).

@@ -193,3 +195,2 @@

```js

@@ -196,0 +197,0 @@ // inside a custom helper class

@@ -1,2 +0,2 @@

# PageObjects
# Page Object

@@ -6,11 +6,10 @@ UI of your web application has interaction areas which can be shared across different tests.

## PageObjects
## PageObject
In case an application has different pages (login, admin, etc) you should use a page object.
CodeceptJS can generate a template for it with next command
CodeceptJS can generate a template for it with the command:
```
```sh
codeceptjs gpo
```
*(or generate pageobject)*

@@ -72,2 +71,46 @@ This will create a sample template for a page object and include it into `codecept.json` config.

Also you can use generators inside a PageObject:
```js
'use strict';
let I;
module.exports = {
_init() {
I = actor();
},
// setting locators
container: "//div[@class = 'numbers']",
mainItem: {
number: ".//div[contains(@class, 'numbers__main-number')]",
title: ".//div[contains(@class, 'numbers__main-title-block')]"
},
// introducing methods
openMainArticle: function* () {
I.waitForVisible(this.container)
let _this = this
let title;
yield within(this.container, function*(){
title = yield I.grabTextFrom(_this.mainItem.number);
let subtitle = yield I.grabTextFrom(_this.mainItem.title);
title = title + " " + subtitle.charAt(0).toLowerCase() + subtitle.slice(1);
yield I.click(_this.mainItem.title)
})
return title;
}
}
```
and use them in your tests:
```js
Scenario('login2', (I, loginPage, basePage) => {
let title = yield* mainPage.openMainArticle()
basePage.pageShouldBeOpened(title)
});
```
## Page Fragments

@@ -78,3 +121,3 @@

```
```sh
codeceptjs go --type fragment

@@ -110,6 +153,6 @@ ```

StepObjects represent complex actions which involve usage of multiple web pages. For instance, creating users in backend, chaning permissions, etc.
StepObjects represent complex actions which involve usage of multiple web pages. For instance, creating users in backend, changing permissions, etc.
StepObject can be created similarly to PageObjects or PageFragments:
```
```sh
codeceptjs go --type step

@@ -166,4 +209,5 @@ ```

```
Please notice that instead of `I` you should use `this` in current context.
### done()

@@ -6,8 +6,7 @@ # QuickStart

Install **CodeceptJS** with WebDriverio using `codeceptjs-webdriverio` meta package from NPM.
Install **CodeceptJS** with WebDriverIO using `codeceptjs-webdriverio` meta package from NPM.
You can install it globally:
```
```sh
[sudo] npm install -g codeceptjs-webdriverio

@@ -18,3 +17,3 @@ ```

```
```sh
npm install codeceptjs-webdriverio --save-dev

@@ -31,3 +30,3 @@ ```

```
```sh
codeceptjs init

@@ -45,3 +44,3 @@ ```

```
```sh
? What helpers do you want to use?

@@ -57,3 +56,3 @@ ❯◉ WebDriverIO

```
```sh
? Where should logs, screenshots, and reports to be stored? ./output

@@ -64,3 +63,3 @@ ```

```
```sh
? Would you like to extend I object with custom steps? Yes

@@ -72,3 +71,3 @@ ? Where would you like to place custom steps? ./steps_file.js

```
```sh
? [WebDriverIO] Base url of site to be tested http://localhost

@@ -117,3 +116,3 @@ ? [WebDriverIO] Browser in which testing will be performed (chrome)

```
```sh
[sudo] npm install -g selenium-standalone

@@ -124,3 +123,2 @@ selenium-standalone install

Alternatively [Selenium Server](http://codecept.io/helpers/WebDriverIO/#selenium-installation) with [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/getting-started) can be installed and started manually.

@@ -136,3 +134,3 @@

*steps option will display test execution process in console*
( *steps option will display test execution process in console.* )

@@ -149,4 +147,4 @@ If everything is done right, you will see in console:

## Congrats! Your first test is running.
## Congrats! Your first test is running
Wasn't so hard, right?

@@ -8,3 +8,3 @@ # Reporters

```
```sh
GitHub --

@@ -34,3 +34,3 @@ ✓ search in 2577ms

```
```sh
GitHub --

@@ -64,7 +64,8 @@ search

```
To get additional information about test execution use `--debug` option. This will show execution steps
as well as notices from test runner. To get even more information with more technical details like error stacktraces,
as well as notices from test runner. To get even more information with more technical details like error stack traces,
and global promises, or events use `--verbose` mode.
```
```sh
GitHub --

@@ -94,3 +95,3 @@ register

```
```sh
npm i mocha-junit-reporter

@@ -111,3 +112,3 @@ ```

```
```sh
codeceptjs run --reporter mocha-junit-reporter

@@ -118,6 +119,5 @@ ```

## Html
Best HTML reports could be prodused with [mochawesome](https://www.npmjs.com/package/mochawesome) reporter.
Best HTML reports could be produced with [mochawesome](https://www.npmjs.com/package/mochawesome) reporter.

@@ -128,3 +128,3 @@ ![](http://codecept.io/images/mochawesome.png)

```
```sh
npm i mochawesome

@@ -145,3 +145,3 @@ ```

```
```sh
codeceptjs run --reporter mochawesome

@@ -152,1 +152,85 @@ ```

### Advanced usage
Want to have screenshots for failed tests?
Then add Mochawesome helper to your config:
```json
"helpers": {
"Mochawesome": {
"uniqueScreenshotNames": "true"
}
},
```
Then tests with failure will have screenshots.
### Configuration
This helper should be configured in codecept.json
- `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites. This option should be the same as in common helper.
- `disableScreenshots` (optional, default: false) - don't save screenshot on failure. This option should be the same as in common helper.
Also if you will add Mochawesome helper, then you will able to add custom context in report:
#### addMochawesomeContext
Adds context to executed test in HTML report:
```js
I.addMochawesomeContext('simple string');
I.addMochawesomeContext('http://www.url.com/pathname');
I.addMochawesomeContext('http://www.url.com/screenshot-maybe.jpg');
I.addMochawesomeContext({title: 'expected output',
value: {
a: 1,
b: '2',
c: 'd'
}
});
```
##### Parameters
- `context` string, url, path to screenshot, object. See [this](https://www.npmjs.com/package/mochawesome#adding-test-context)
## Multi Reports
Want to use several reporters in the same time? Try to use [mocha-multi](https://www.npmjs.com/package/mocha-multi) reporter
Install it via NPM:
```sh
npm i mocha-multi
```
Configure mocha-multi with reports that you want:
```json
"mocha": {
"reporterOptions": {
"codeceptjs-cli-reporter": {
"stdout": "-",
"options": {
"verbose": true,
"steps": true,
}
},
"mochawesome": {
"stdout": "./output/console.log",
"options": {
"reportDir": "./output",
"reportFilename": "report"
}
}
}
```
Execute CodeceptJS with mocha-multi reporter:
```sh
codeceptjs run --reporter mocha-multi
```
This will give you cli with steps in console and HTML report in `output` directory.

@@ -12,3 +12,3 @@ # Translation

```
```sh
codeceptjs def

@@ -15,0 +15,0 @@ ```

@@ -73,2 +73,3 @@ 'use strict';

recorder.catchWithoutStop((err) => {
step.status = 'failed';
step.endTime = Date.now();

@@ -75,0 +76,0 @@ event.emit(event.step.failed, step);

@@ -42,3 +42,3 @@ 'use strict';

let result = this.comparator.apply(this.params, arguments);
if (result) return; // should increase global assetion counter
if (result) return; // should increase global assertion counter
throw this.getFailedAssertion();

@@ -54,3 +54,3 @@ }

let result = this.comparator.apply(this.params, arguments);
if (!result) return; // should increase global assetion counter
if (!result) return; // should increase global assertion counter
throw this.getFailedNegation();

@@ -57,0 +57,0 @@ }

@@ -60,3 +60,3 @@ 'use strict';

* Executes hooks and bootstrap.
* If bootstrap is async second parameter is required.
* If bootstrap is async, second parameter is required.
*

@@ -113,3 +113,3 @@ * @param {*} done

}
mocha.run().on('end', () => {
mocha.run(() => {
let done = () => {

@@ -116,0 +116,0 @@ event.emit(event.all.result, this);

@@ -19,3 +19,3 @@ 'use strict';

*
* ### Use Case
* ## Use Case
*

@@ -41,3 +41,2 @@ * Acceptance tests interact with a websites using UI and real browser.

*
*
* ### Setup

@@ -47,3 +46,3 @@ *

*
* ```
* ```sh
* npm i rosie faker --save-dev`

@@ -50,0 +49,0 @@ * ```

@@ -24,3 +24,3 @@ 'use strict';

*
* #### Appium Installation
* ## Appium Installation
*

@@ -32,3 +32,3 @@ * Appium is an open source test automation framework for use with native, hybrid and mobile web apps that implements the WebDriver protocol.

*
* ```
* ```sh
* npm install -g appium

@@ -39,8 +39,6 @@ * ```

*
* ### Configuration
* ## Helper configuration
*
* This helper should be configured in codecept.json or codecept.conf.js
*
* #### Appium configuration
*
* * `port`: Appium port

@@ -126,2 +124,4 @@ * * `restart`: restart browser or app between tests (default: true), if set to false cookies will be cleaned but browser window will be kept and for apps nothing will be changed.

this.isRunning = false;
// override defaults with config

@@ -174,26 +174,32 @@ this.options = Object.assign(this.options, config);

}
if (this.options.timeouts && this.isWeb) {
this.defineTimeout(this.options.timeouts);
}
if (this.options.windowSize === 'maximize' && !this.platform) {
this.browser.execute('return [screen.width, screen.height]').then((res) => {
return this.browser.windowHandleSize({
width: res.value[0],
height: res.value[1]
});
});
} else if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0 && !this.platform) {
let dimensions = this.options.windowSize.split('x');
this.browser.windowHandleSize({
width: dimensions[0],
height: dimensions[1]
});
}
return this.browser;
return this.browser.then(() => {
this.isRunning = true;
let promisesList = [];
if (this.options.timeouts && this.isWeb) {
promisesList.push(this.defineTimeout(this.options.timeouts));
}
if (this.options.windowSize === 'maximize' && !this.platform) {
promisesList.push(this.browser.execute('return [screen.width, screen.height]').then((res) => {
return this.browser.windowHandleSize({
width: res.value[0],
height: res.value[1]
});
}));
} else if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0 && !this.platform) {
let dimensions = this.options.windowSize.split('x');
promisesList.push(this.browser.windowHandleSize({
width: dimensions[0],
height: dimensions[1]
}));
}
return Promise.all(promisesList);
});
}
_after() {
if (this.options.restart) return this.browser.end();
if (!this.isRunning) return;
if (this.options.restart) {
this.isRunning = false;
return this.browser.end();
}
if (this.isWeb && !this.platform) {

@@ -200,0 +206,0 @@ return super._after();

@@ -9,2 +9,3 @@ 'use strict';

const truth = require('../assert/truth').truth;
const hashCode = require('../utils').hashCode;
const xpathLocator = require('../utils').xpathLocator;

@@ -32,3 +33,3 @@ const fileExists = require('../utils').fileExists;

*
* ### Configuration
* ## Configuration
*

@@ -39,2 +40,5 @@ * This helper should be configured in codecept.json

* * `restart` (optional, default: true) - restart browser between tests.
* * `disableScreenshots` (optional, default: false) - don't save screenshot on failure
* * `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
* * `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
* * `keepCookies` (optional, default: false) - keep cookies between tests when `restart` set to false.

@@ -62,2 +66,3 @@ * * `waitForAction`: (optional) how long to wait after click, doubleClick or PressKey actions in ms. Default: 500

restart: true,
keepBrowserState: false,
keepCookies: false,

@@ -187,3 +192,3 @@ js_errors: null

if (!this.options.restart && !this.isRunning) {
this.isRunning = true;
this.debugSection('Session', 'Starting singleton browser session');
return this._startBrowser();

@@ -194,5 +199,4 @@ }

_before() {
if (this.options.restart) {
return this._startBrowser();
}
if (this.options.restart) return this._startBrowser();
if (!this.isRunning) return this._startBrowser();
return this.browser;

@@ -202,6 +206,14 @@ }

_after() {
if (!this.isRunning) return;
if (this.options.restart) {
this.isRunning = false;
return this._stopBrowser();
}
if (this.options.keepCookies) return;
if (this.options.keepBrowserState) return;
if (this.options.keepCookies) {
return Promise.all([this.executeScript(function () {
return localStorage.clear();
})]);
}
this.debugSection('Session', 'cleaning cookies and localStorage');
return Promise.all([this.browser.cookies.clearAll(), this.executeScript(function () {

@@ -216,3 +228,3 @@ return localStorage.clear();

_finishTest() {
if (!this.options.restart) {
if (!this.options.restart && this.isRunning) {
this._stopBrowser();

@@ -224,11 +236,16 @@ }

this.browser = this.Nightmare(this.options);
this.browser.on('dom-ready', () => this._injectClientScripts());
this.browser.on('console', (type, message) => {
this.debug(`${type}: ${message}`);
return this.browser.then(() => {
this.isRunning = true;
this.browser.on('dom-ready', () => this._injectClientScripts());
this.browser.on('did-start-loading', () => this._injectClientScripts());
this.browser.on('will-navigate', () => this._injectClientScripts());
this.browser.on('console', (type, message) => {
this.debug(`${type}: ${message}`);
});
if (this.options.windowSize) {
let size = this.options.windowSize.split('x');
return this.browser.viewport(parseInt(size[0]), parseInt(size[1]));
}
});
if (this.options.windowSize) {
let size = this.options.windowSize.split('x');
return this.browser.viewport(parseInt(size[0]), parseInt(size[1]));
}
}

@@ -817,6 +834,13 @@

this.browser.options.waitTimeout = sec * 1000 || this.options.waitForTimeout;
sec = this.browser.options.waitForTimeout / 1000;
return this.browser.wait(function (by, locator, text) {
return codeceptjs.findElement(by, locator).innerText.indexOf(text) > -1;
}, lctype(locator), lcval(locator), text);
}, lctype(locator), lcval(locator), text).catch((err) => {
if (err.indexOf(`Cannot read property`) > -1) {
throw new Error(`element (${JSON.stringify(context)}) is not in DOM. Unable to wait text.`);
} else if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
throw new Error(`there is no element(${JSON.stringify(context)}) with text "${text}" after ${sec} sec`);
} else throw err;
});
}

@@ -829,2 +853,3 @@

this.browser.options.waitTimeout = sec * 1000 || this.options.waitForTimeout;
sec = this.browser.options.waitForTimeout / 1000;
locator = guessLocator(locator) || { css: locator};

@@ -836,3 +861,7 @@

return el.offsetParent !== null;
}, lctype(locator), lcval(locator));
}, lctype(locator), lcval(locator)).catch((err) => {
if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
throw new Error(`element (${JSON.stringify(locator)}) still not visible on page after ${sec} sec`);
} else throw err;
});
}

@@ -845,2 +874,3 @@

this.browser.options.waitTimeout = sec * 1000 || this.options.waitForTimeout;
sec = this.browser.options.waitForTimeout / 1000;
locator = guessLocator(locator) || { css: locator};

@@ -850,6 +880,17 @@

return codeceptjs.findElement(by, locator) !== null;
}, lctype(locator), lcval(locator));
}, lctype(locator), lcval(locator)).catch((err) => {
if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
throw new Error(`element (${JSON.stringify(locator)}) still not present on page after ${sec} sec`);
} else throw err;
});
}
/**
* Reload the page
*/
refresh() {
return this.browser.refresh();
}
/**
* {{> ../webapi/saveScreenshot }}

@@ -881,6 +922,8 @@ */

if (!this.options.disableScreenshots) {
let fileName = clearString(test.title) + '.failed.png';
let fileName = clearString(test.title);
if (test.ctx && test.ctx.test && test.ctx.test.type == 'hook') fileName = clearString(`${test.title}_${test.ctx.test.title}`);
if (this.options.uniqueScreenshotNames) {
fileName = test.title.substring(0, 10).replace(/ /g, '_') + '-' + hashCode(test.title) + '-' + hashCode(test.file) +
'.failed.png';
fileName = `${fileName.substring(0, 10)}-${hashCode(fileName)}-${hashCode(test.file)}.failed.png`;
} else {
fileName = fileName + '.failed.png';
}

@@ -887,0 +930,0 @@ promisesList.push(this.saveScreenshot(fileName, true));

@@ -22,4 +22,6 @@ 'use strict';

*
* #### Selenium Installation
* ## Backends
*
* ### Selenium Installation
*
* 1. Download [Selenium Server](http://docs.seleniumhq.org/download/)

@@ -29,3 +31,3 @@ * 2. For Chrome browser install [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/getting-started), for Firefox browser install [GeckoDriver](https://github.com/mozilla/geckodriver).

*
* #### PhantomJS Installation
* ### PhantomJS Installation
*

@@ -38,3 +40,3 @@ * PhantomJS is a headless alternative to Selenium Server that implements the WebDriver protocol.

*
* ### Configuration
* ## Configuration
*

@@ -45,5 +47,8 @@ * This helper should be configured in codecept.json

* * `browser` - browser in which perform testing
* * `driver` - which protrator driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `driver` - which protractor driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `restart` (optional, default: true) - restart browser between tests.
* * `smartWait`: (optional) **enables [SmartWait](http://codecept.io/acceptance/#smartwait)**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000
* * `disableScreenshots` (optional, default: false) - don't save screenshot on failure
* * `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
* * `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
* * `seleniumAddress` - Selenium address to connect (default: http://localhost:4444/wd/hub)

@@ -112,3 +117,3 @@ * * `rootElement` - Root element of AngularJS application (default: body)

this.isProtractor5 = !requireg('protractor').wrapDriver;
this.context = this.options.rootElement;
try {

@@ -121,2 +126,3 @@ // get selenium-webdriver

}
return Promise.resolve(Runner);
}

@@ -145,3 +151,2 @@

this.browser = runner.createBrowser();
global.browser = this.browser;

@@ -153,13 +158,12 @@ global.$ = this.browser.$;

global.ExpectedConditions = EC = this.browser.ExpectedConditions;
let promisesList = [];
if (this.options.windowSize == 'maximize') {
this.resizeWindow(this.options.windowSize);
promisesList.push(this.resizeWindow(this.options.windowSize));
}
if (this.options.windowSize) {
var size = this.options.windowSize.split('x');
this.resizeWindow(parseInt(size[0]), parseInt(size[1]));
promisesList.push(this.resizeWindow(parseInt(size[0]), parseInt(size[1])));
}
return this.browser;
return Promise.all(promisesList).then(() => this.isRunning = true);
}

@@ -169,5 +173,3 @@

super._before();
this.amInsideAngularApp();
this.context = this.options.rootElement;
return this.browser;
return this.amInsideAngularApp();
}

@@ -224,5 +226,2 @@

amInsideAngularApp() {
if (this.browser.driver && this.insideAngular) {
return; // already inside angular
}
this.browser.ignoreSynchronization = false;

@@ -229,0 +228,0 @@ return Promise.resolve(this.insideAngular = true);

@@ -25,4 +25,6 @@ 'use strict';

*
* #### Selenium Installation
* ## Backends
*
* ### Selenium Installation
*
* 1. Download [Selenium Server](http://docs.seleniumhq.org/download/)

@@ -33,3 +35,3 @@ * 2. For Chrome browser install [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/getting-started), for Firefox browser install [GeckoDriver](https://github.com/mozilla/geckodriver).

*
* #### PhantomJS Installation
* ### PhantomJS Installation
*

@@ -42,3 +44,3 @@ * PhantomJS is a headless alternative to Selenium Server that implements [the WebDriver protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol).

*
* ### Configuration
* ## Configuration
*

@@ -49,5 +51,8 @@ * This helper should be configured in codecept.json

* * `browser` - browser in which perform testing
* * `driver` - which protrator driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `driver` - which protractor driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `restart` - restart browser between tests (default: true).
* * `smartWait`: (optional) **enables SmartWait**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000
* * `disableScreenshots` (optional, default: false) - don't save screenshot on failure
* * `uniqueScreenshotNames` (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites
* * `keepBrowserState` (optional, default: false) - keep browser state between tests when `restart` set to false.
* * `keepCookies` (optional, default: false) - keep cookies between tests when `restart` set to false.*

@@ -95,2 +100,3 @@ * * `seleniumAddress` - Selenium address to connect (default: http://localhost:4444/wd/hub)

restart: true,
keepBrowserState: false,
keepCookies: false,

@@ -131,2 +137,4 @@ disableScreenshots: false,

if (this.options.proxy) this.browserBuilder.setProxy(this.options.proxy);
return Promise.resolve(this.browserBuilder);
}

@@ -151,11 +159,10 @@

this.browser = this.browserBuilder.build();
let promisesList = [];
if (this.options.windowSize == 'maximize') {
this.resizeWindow(this.options.windowSize);
promisesList.push(this.resizeWindow(this.options.windowSize));
} else if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0) {
var size = this.options.windowSize.split('x');
this.resizeWindow(size[0], size[1]);
promisesList.push(this.resizeWindow(size[0], size[1]));
}
return this.browser;
return Promise.all(promisesList).then(() => this.isRunning = true);
}

@@ -166,3 +173,2 @@

this.debugSection('Session', 'Starting singleton browser session');
this.isRunning = true;
return this._startBrowser();

@@ -173,9 +179,13 @@ }

_before() {
if (this.options.restart && !this.options.manualStart) {
return this._startBrowser();
}
if (this.options.restart && !this.options.manualStart) return this._startBrowser();
if (!this.isRunning && !this.options.manualStart) return this._startBrowser();
}
_after() {
if (this.options.restart) return this.browser.quit();
if (!this.isRunning) return;
if (this.options.restart) {
this.isRunning = false;
return this.browser.quit();
}
if (this.options.keepBrowserState) return;
if (this.options.keepCookies) return Promise.all([this.browser.executeScript('localStorage.clear();'), this.closeOtherTabs()]);

@@ -191,3 +201,3 @@ // if browser should not be restarted

_finishTest() {
if (!this.options.restart) return this.browser.quit();
if (!this.options.restart && this.isRunning) return this.browser.quit();
}

@@ -199,9 +209,17 @@

if (!this.options.disableScreenshots) {
let fileName = clearString(test.title) + '.failed.png';
let fileName = clearString(test.title);
if (test.ctx && test.ctx.test && test.ctx.test.type == 'hook') fileName = clearString(`${test.title}_${test.ctx.test.title}`);
if (this.options.uniqueScreenshotNames) {
fileName = clearString(test.title.substring(0, 10)) + '-' + hashCode(test.title) + '-' + hashCode(test.file) + '.failed.png';
fileName = `${fileName.substring(0, 10)}-${hashCode(fileName)}-${hashCode(test.file)}.failed.png`;
} else {
fileName = fileName + '.failed.png';
}
promisesList.push(this.saveScreenshot(fileName, true));
}
return Promise.all(promisesList);
return Promise.all(promisesList).catch((err) => {
if (err && err.type && err.type == "RuntimeError" && err.message && (err.message.indexOf("was terminated due to") > -1 || err.message.indexOf("no such window: target window already closed" > -1))) {
this.isRunning = false;
return;
}
});
}

@@ -208,0 +226,0 @@

@@ -67,2 +67,3 @@ /**

suite.addTest(scenario.test(test));
if (opts.retries) test.retries(opts.retries);

@@ -72,3 +73,2 @@ if (opts.timeout) test.timeout(opts.timeout);

suite.addTest(scenario.test(test));
return test;

@@ -107,5 +107,6 @@ };

suite.file = file;
suite.fullTitle = () => `${suite.title}: ${suite.file}`;
suites.unshift(suite);
suite.beforeEach('codeceptjs.before', scenario.setup);
afterEachHooks.push(['finialize codeceptjs', scenario.teardown]);
suite.beforeEach('codeceptjs.before', () => scenario.setup(suite));
afterEachHooks.push(['finialize codeceptjs', () => scenario.teardown(suite)]);

@@ -112,0 +113,0 @@ suite.beforeAll('codeceptjs.beforeSuite', () => scenario.suiteSetup(suite));

@@ -17,2 +17,4 @@ 'use strict';

currentTest.steps = [];
if (!('retryNum' in currentTest)) currentTest.retryNum = 0;
else currentTest.retryNum = currentTest.retryNum + 1;
});

@@ -28,5 +30,16 @@

if (!currentTest.steps.length) return;
currentTest.steps.slice(-1)[0].status = 'failed';
let failureIndex = currentTest.steps.findIndex((el) => {
return el.status === 'failed';
});
//To be sure that failed test will be failed in report
currentTest.state = 'failed';
currentTest.steps.length = failureIndex + 1;
});
event.dispatcher.on(event.test.passed, function (test) {
//To be sure that passed test will be passed in report
delete currentTest.err;
currentTest.state = 'passed';
});
event.dispatcher.on(event.step.before, function (step) {

@@ -33,0 +46,0 @@ if (!currentTest || !currentTest.steps) return;

@@ -37,2 +37,8 @@ const Mocha = require('mocha/lib/mocha');

if (reporterOptions["codeceptjs-cli-reporter"]) {
Object.defineProperty(reporterOptions, "codeceptjs/lib/reporter/cli",
Object.getOwnPropertyDescriptor(reporterOptions, "codeceptjs-cli-reporter"));
delete reporterOptions["codeceptjs-cli-reporter"];
}
// custom reporters

@@ -39,0 +45,0 @@ mocha.reporter(opts.reporter, reporterOptions);

@@ -17,2 +17,3 @@ 'use strict';

let level = 0;
opts = opts.reporterOptions || opts;
if (opts.steps) level = 1;

@@ -19,0 +20,0 @@ if (opts.debug) level = 2;

@@ -29,2 +29,15 @@ 'use strict';

var injectHook = function (inject, suite) {
try {
inject();
} catch (err) {
recorder.throw(err);
}
recorder.catch((err) => {
event.emit(event.test.failed, suite, err);
throw err;
});
return recorder.promise();
};
/**

@@ -84,5 +97,13 @@ * Wraps test function, injects support objects from container,

module.exports.injected = function (fn, suite, hookName) {
return function () {
return function (done) {
recorder.errHandler(function (err) {
recorder.session.start('teardown');
event.emit(event.test.failed, suite, err);
if (hookName === 'after') event.emit(event.test.after, suite);
if (hookName === 'afterSuite') event.emit(event.suite.after, suite);
recorder.add(() => done(err));
});
try {
recorder.startUnlessRunning();
this.test.body = fn.toString();
fn.apply(this, getInjectedArguments(fn));

@@ -92,9 +113,4 @@ } catch (err) {

}
recorder.catch((err) => {
event.emit(event.test.failed, suite, err); // emit
if (hookName === 'after') event.emit(event.test.after, suite);
if (hookName === 'afterSuite') event.emit(event.suite.after, suite);
throw err;
});
return recorder.promise();
recorder.add(`finish ${hookName} hook`, () => done());
recorder.catch();
};

@@ -106,20 +122,28 @@ };

*/
module.exports.setup = function () {
recorder.startUnlessRunning();
event.emit(event.test.before);
module.exports.setup = function (suite) {
return injectHook(() => {
recorder.startUnlessRunning();
event.emit(event.test.before);
}, suite);
};
module.exports.teardown = function () {
recorder.startUnlessRunning();
event.emit(event.test.after);
module.exports.teardown = function (suite) {
return injectHook(() => {
recorder.startUnlessRunning();
event.emit(event.test.after);
}, suite);
};
module.exports.suiteSetup = function (suite) {
recorder.startUnlessRunning();
event.emit(event.suite.before, suite);
return injectHook(() => {
recorder.startUnlessRunning();
event.emit(event.suite.before, suite);
}, suite);
};
module.exports.suiteTeardown = function (suite) {
recorder.startUnlessRunning();
event.emit(event.suite.after, suite);
return injectHook(() => {
recorder.startUnlessRunning();
event.emit(event.suite.after, suite);
}, suite);
};

@@ -126,0 +150,0 @@

{
"name": "codeceptjs",
"version": "1.0.0",
"description": "Modern Era Aceptance Testing Framework for NodeJS",
"version": "1.0.1",
"description": "Modern Era Acceptance Testing Framework for NodeJS",
"homepage": "http://codecept.io",

@@ -56,3 +56,3 @@ "repository": "Codeception/codeceptjs",

"gulp-if": "^2.0.2",
"gulp-istanbul": "^0.9.0",
"gulp-istanbul": "^1.1.2",
"gulp-mocha": "^2.0.0",

@@ -65,2 +65,3 @@ "gulp-mustache": "^2.2.0",

"nightmare-upload": "^0.1.1",
"nyc": "^11.1.0",
"protractor": ">4.0.9 <6.0",

@@ -77,2 +78,3 @@ "rosie": "^1.6.0",

"scripts": {
"gulp": "gulp",
"prepublish": "gulp prepublish",

@@ -79,0 +81,0 @@ "test": "gulp",

@@ -29,6 +29,7 @@ # CodeceptJS [![NPM version][npm-image]][npm-url] [![Build Status](https://travis-ci.org/Codeception/CodeceptJS.svg?branch=master)](https://travis-ci.org/Codeception/CodeceptJS) [![Join the chat at https://gitter.im/Codeception/CodeceptJS](https://badges.gitter.im/Codeception/CodeceptJS.svg)](https://gitter.im/Codeception/CodeceptJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

* [**WebDriverIO**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/WebDriverIO.md) - wrapper on top of Selenium bindings library [WebDriverIO](http://webdriver.io/)
* [**Protractor**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Protractor.md) - helper enpowered by [Protractor](http://protractortest.org/) framework for AngularJS testing
* [**Protractor**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Protractor.md) - helper empowered by [Protractor](http://protractortest.org/) framework for AngularJS testing
* [**Nightmare**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Nightmare.md) - helper which for testing web applications indi Electron using NightmareJS.
* [**Appium**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/Appium.md)
* [**SeleniumWebdriver**](https://github.com/Codeception/CodeceptJS/blob/master/docs/helpers/SeleniumWebdriver.md) - helper which for selenium testing using official Selenium Webdriver JS bindings.
And more to come...

@@ -54,7 +55,6 @@

## Install
```sh
$ npm install -g codeceptjs
npm install -g codeceptjs
```

@@ -64,3 +64,3 @@

```
```sh
codeceptjs init

@@ -74,3 +74,3 @@ ```

```
```sh
codeceptjs generate:test

@@ -81,3 +81,3 @@ ```

```
```sh
codeceptjs run

@@ -88,3 +88,3 @@ ```

```
```sh
codeceptjs def .

@@ -104,3 +104,4 @@ ```

Let's see how we can handle basic form testing:
```js
```sh
Feature('CodeceptJS Demonstration');

@@ -125,3 +126,3 @@

```
```sh
codeceptjs run --steps

@@ -132,3 +133,3 @@ ```

```
```sh
CodeceptJS Demonstration --

@@ -153,3 +154,3 @@ test some forms

```
```sh
codeceptjs shell

@@ -233,3 +234,3 @@ ```

```
```sh
codeceptjs generate pageobject

@@ -282,3 +283,2 @@ ```

## License

@@ -288,3 +288,2 @@

[npm-image]: https://badge.fury.io/js/codeceptjs.svg

@@ -291,0 +290,0 @@ [npm-url]: https://npmjs.org/package/codeceptjs

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc