diff --git a/.hound.yml b/.hound.yml
new file mode 100644
index 000000000..6728a4cba
--- /dev/null
+++ b/.hound.yml
@@ -0,0 +1,3 @@
+eslint:
+ enabled: true
+ config_file: .eslintrc.json
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2df8f4f57..ee0d84913 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,19 +6,40 @@
```js
// retry action once on failure
I.retry().see('Hello');
+
// retry action 3 times on failure
I.retry(3).see('Hello');
+
// retry action 3 times waiting for 0.1 second before next try
I.retry({ retries: 3, minTimeout: 100 }).see('Hello');
+
// retry action 3 times waiting no more than 3 seconds for last retry
I.retry({ retries: 3, maxTimeout: 3000 }).see('Hello');
-//
+
+// retry 2 times if error with message 'Node not visible' happens
I.retry({
retries: 2,
when: err => err.message === 'Node not visible'
}).seeElement('#user');
```
+* `Scenario().injectDependencies` added to dynamically add objects into DI container by @Apshenkin. See [Dependency Injection section in PageObjects](https://codecept.io/pageobjects/#dependency-injection).
+* Fixed using async/await functions inside `within`
+* [WebDriverIO][Protractor][Puppeteer][Nightmare] **`waitUntilExists` deprecated** in favor of `waitForElement`
+* [WebDriverIO][Protractor] **`waitForStalenessOf` deprecated** in favor of `waitForDetached`
+* [WebDriverIO][Protractor][Puppeteer][Nightmare] `waitForDetached` added
+* [Nightmare] Added `I.seeNumberOfElements()` by @pmoncadaisla
+* [Nightmare] Load blank page when starting nightmare so that the .evaluate function will work if _failed/saveScreenshot is triggered by @reubenmiller
+* Fixed using plain arrays for data driven tests by @reubenmiller
+* [Puppeteer] Use default tab instead of opening a new tab when starting the browser by @reubenmiller
+* [Puppeteer] Added `grabNumberOfTabs` function by @reubenmiller
+* [Puppeteer] Add ability to set user-agent by @abidhahmed
+* [Puppeteer] Add keepCookies and keepBrowserState @abidhahmed
+* [Puppeteer] Clear value attribute instead of innerhtml for TEXTAREA by @reubenmiller
+* [REST] fixed sending string payload by @Spartans2017
+* Fixed unhandled rejection in async/await tests by @APshenkin
+
+
## 1.1.4
* Removed `yarn` call in package.json
diff --git a/docs/helpers/Nightmare.md b/docs/helpers/Nightmare.md
index b10223379..f5b859a7c 100644
--- a/docs/helpers/Nightmare.md
+++ b/docs/helpers/Nightmare.md
@@ -66,7 +66,7 @@ I.amOnPage('/login'); // opens a login page
**Parameters**
- `url` url path or global urlIn a second argument a list of request headers can be passed:```js
- I.amOnPage('/auth', [{'x-my-custom-header': 'some value'}])
+ I.amOnPage('/auth', { 'x-my-custom-header': 'some value' })
```
- `headers` (optional, default `null`)
@@ -659,6 +659,20 @@ Checks that title contains text.
- `text`
+## seeNumberOfElements
+
+asserts that an element appears a given number of times in the DOM
+Element is located by label or name or CSS or XPath.
+
+```js
+I.seeNumberOfElements('#submitBtn', 1);
+```
+
+**Parameters**
+
+- `selector`
+- `num`
+
## selectOption
Selects an option in a drop-down select.
@@ -725,6 +739,18 @@ I.wait(2); // wait 2 secs
- `sec`
+## waitForDetached
+
+Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
+Element can be located by CSS or XPath.
+
+ I.waitForDetached('#popup');
+
+**Parameters**
+
+- `locator` element located by CSS|XPath|strict locator
+- `sec` time seconds to wait, 1 by default
+
## waitForElement
Waits for element to be present on page (by default waits for 1sec).
@@ -780,18 +806,3 @@ Element can be located by CSS or XPath.
- `locator` element located by CSS|XPath|strict locator
- `sec` time seconds to wait, 1 by default
-
-## waitUntilExists
-
-Waits for element not to be present on page (by default waits for 1sec).
-Element can be located by CSS or XPath.
-
-```js
-I.waitUntilExists('.btn.continue');
-I.waitUntilExists('.btn.continue', 5); // wait for 5 secs
-```
-
-**Parameters**
-
-- `locator` element located by CSS|XPath|strict locator
-- `sec` time seconds to wait, 1 by default
diff --git a/docs/helpers/Protractor.md b/docs/helpers/Protractor.md
index 7335af361..f5a61b3e7 100644
--- a/docs/helpers/Protractor.md
+++ b/docs/helpers/Protractor.md
@@ -474,17 +474,22 @@ assert(cookie.value, '123456');
- `name` Returns cookie in JSON [format](https://code.google.com/p/selenium/wiki/JsonWireProtocol#Cookie_JSON_Object).
-## grabSource
+## grabNumberOfOpenTabs
-Checks that the current page contains the given string in its raw source code.
+Grab number of open tabs
```js
-I.seeInSource('
Green eggs & ham
');
+I.grabNumberOfOpenTabs();
```
-**Parameters**
+## grabSource
-- `text`
+Retrieves page source and returns it to test.
+Resumes test execution, so should be used inside an async function.
+
+```js
+let pageSource = await I.grabSource();
+```
## grabTextFrom
@@ -571,7 +576,7 @@ I.openNewTab();
## pressKey
Presses a key on a focused element.
-Speical keys like 'Enter', 'Control', [etc](https://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value)
+Special keys like 'Enter', 'Control', [etc](https://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value)
will be replaced with corresponding unicode.
If modifier key is used (Control, Command, Alt, Shift) in array, it will be released afterwards.
@@ -874,44 +879,48 @@ I.wait(2); // wait 2 secs
Waits for element to become clickable for number of seconds.
+```js
+I.waitForClickable('#link');
+```
+
**Parameters**
- `locator`
- `sec` (optional, default `null`)
-## waitForElement
+## waitForDetached
-Waits for element to be present on page (by default waits for 1sec).
+Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
Element can be located by CSS or XPath.
-```js
-I.waitForElement('.btn.continue');
-I.waitForElement('.btn.continue', 5); // wait for 5 secs
-```
+ I.waitForDetached('#popup');
**Parameters**
- `locator` element located by CSS|XPath|strict locator
- `sec` time seconds to wait, 1 by default
-## waitForInvisible
+## waitForElement
-Waits for an element to become invisible on a page (by default waits for 1sec).
+Waits for element to be present on page (by default waits for 1sec).
Element can be located by CSS or XPath.
- I.waitForInvisible('#popup');
+```js
+I.waitForElement('.btn.continue');
+I.waitForElement('.btn.continue', 5); // wait for 5 secs
+```
**Parameters**
- `locator` element located by CSS|XPath|strict locator
- `sec` time seconds to wait, 1 by default
-## waitForStalenessOf
+## waitForInvisible
-Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
+Waits for an element to become invisible on a page (by default waits for 1sec).
Element can be located by CSS or XPath.
- I.waitForStalenessOf('#popup');
+ I.waitForInvisible('#popup');
**Parameters**
@@ -946,18 +955,3 @@ Element can be located by CSS or XPath.
- `locator` element located by CSS|XPath|strict locator
- `sec` time seconds to wait, 1 by default
-
-## waitUntilExists
-
-Waits for element not to be present on page (by default waits for 1sec).
-Element can be located by CSS or XPath.
-
-```js
-I.waitUntilExists('.btn.continue');
-I.waitUntilExists('.btn.continue', 5); // wait for 5 secs
-```
-
-**Parameters**
-
-- `locator` element located by CSS|XPath|strict locator
-- `sec` time seconds to wait, 1 by default
diff --git a/docs/helpers/Puppeteer.md b/docs/helpers/Puppeteer.md
index 9bfc09e6b..54d43bcc1 100644
--- a/docs/helpers/Puppeteer.md
+++ b/docs/helpers/Puppeteer.md
@@ -10,13 +10,18 @@ Requires `puppeteer` package to be installed.
This helper should be configured in codecept.json
-- `url` - base url of website to be tested
-- `show` (optional, default: false) - show Google Chrome window for debug.
-- `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.
+- `url`: base url of website to be tested
+- `show`: (optional, default: false) - show Google Chrome window for debug.
+- `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` is set to false.
+- `keepCookies`: (optional, default: false) - keep cookies between tests when `restart` is set to false.
- `waitForAction`: (optional) how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
- `waitForTimeout`: (optional) default wait* timeout in ms. Default: 1000.
- `windowSize`: (optional) default window size. Set a dimension like `640x480`.
+- `userAgent`: (optional) user-agent string.
+- `manualStart`: (optional, default: false) - do not start browser before a test, start it manually inside a helper with `this.helpers["Puppeteer"]._startBrowser()`.
- `chrome`: (optional) pass additional [Puppeteer run options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions). Example
```js
@@ -479,7 +484,7 @@ let hint = yield I.grabAttributeFrom('#tooltip', 'title');
Get JS log from browser.
```js
-let logs = yield I.grabBrowserLogs();
+let logs = await I.grabBrowserLogs();
console.log(JSON.stringify(logs))
```
@@ -524,6 +529,14 @@ let postHTML = yield I.grabHTMLFrom('#post');
- `locator`
+## grabNumberOfOpenTabs
+
+Grab number of open tabs
+
+```js
+I.grabNumberOfOpenTabs();
+```
+
## grabNumberOfVisibleElements
Grab number of visible elements by locator
@@ -546,16 +559,13 @@ await I.grabPopupText();
## grabSource
-Checks that the current page contains the given string in its raw source code.
+Retrieves page source and returns it to test.
+Resumes test execution, so should be used inside an async function.
```js
-I.seeInSource('Green eggs & ham
');
+let pageSource = await I.grabSource();
```
-**Parameters**
-
-- `text`
-
## grabTextFrom
Retrieves a text from an element located by CSS or XPath and returns it to test.
@@ -632,7 +642,7 @@ I.openNewTab();
## pressKey
Presses a key on a focused element.
-Speical keys like 'Enter', 'Control', [etc](https://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value)
+Special keys like 'Enter', 'Control', [etc](https://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value)
will be replaced with corresponding unicode.
If modifier key is used (Control, Command, Alt, Shift) in array, it will be released afterwards.
@@ -1026,6 +1036,18 @@ I.wait(2); // wait 2 secs
- `sec`
+## waitForDetached
+
+Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
+Element can be located by CSS or XPath.
+
+ I.waitForDetached('#popup');
+
+**Parameters**
+
+- `locator` element located by CSS|XPath|strict locator
+- `sec` time seconds to wait, 1 by default
+
## waitForElement
Waits for element to be present on page (by default waits for 1sec).
@@ -1122,21 +1144,6 @@ I.waitUntil(() => window.requests == 0, 5);
- `fn`
- `sec` time seconds to wait, 1 by default
-## waitUntilExists
-
-Waits for element not to be present on page (by default waits for 1sec).
-Element can be located by CSS or XPath.
-
-```js
-I.waitUntilExists('.btn.continue');
-I.waitUntilExists('.btn.continue', 5); // wait for 5 secs
-```
-
-**Parameters**
-
-- `locator` element located by CSS|XPath|strict locator
-- `sec` time seconds to wait, 1 by default
-
## waitUrlEquals
Waits for the entire URL to match the expected
diff --git a/docs/helpers/WebDriverIO.md b/docs/helpers/WebDriverIO.md
index 8f1c8d7b6..c38cc1c46 100644
--- a/docs/helpers/WebDriverIO.md
+++ b/docs/helpers/WebDriverIO.md
@@ -9,20 +9,20 @@ WebDriverIO requires [Selenium Server and ChromeDriver/GeckoDriver to be install
This helper should be configured in codecept.json
-- `url` - base url of website to be tested
-- `browser` - browser in which perform testing
-- `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.
-- `keepCookies` (optional, default: false) - keep cookies between tests when `restart` set to false.
+- `url`: base url of website to be tested.
+- `browser`: browser in which to perform testing.
+- `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 screenshots 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` is set to false.
+- `keepCookies`: (optional, default: false) - keep cookies between tests when `restart` set to false.
- `windowSize`: (optional) default window size. Set to `maximize` or a dimension in the format `640x480`.
-- `waitForTimeout`: (option) sets default wait time in _ms_ for all `wait*` functions. 1000 by default;
+- `waitForTimeout`: (option) sets default wait time in _ms_ for all `wait*` functions. 1000 by default.
- `desiredCapabilities`: Selenium's [desired
- capabilities](https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities)
-- `manualStart` (optional, default: false) - do not start browser before a test, start it manually inside a helper
- with `this.helpers["WebDriverIO"]._startBrowser()`
+ capabilities](https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities).
+- `manualStart`: (optional, default: false) - do not start browser before a test, start it manually inside a helper
+ with `this.helpers["WebDriverIO"]._startBrowser()`.
- `timeouts`: [WebDriverIO timeouts](http://webdriver.io/guide/testrunner/timeouts.html) defined as hash.
Example:
@@ -679,6 +679,14 @@ let postHTML = yield I.grabHTMLFrom('#post');
- `locator`
+## grabNumberOfOpenTabs
+
+Grab number of open tabs
+
+```js
+I.grabNumberOfOpenTabs();
+```
+
## grabNumberOfVisibleElements
Grab number of visible elements by locator
@@ -701,15 +709,14 @@ await I.grabPopupText();
## grabSource
-Checks that the current page contains the given string in its raw source code.
+Retrieves page source and returns it to test.
+Resumes test execution, so should be used inside an async function.
```js
-I.seeInSource('Green eggs & ham
');
+let pageSource = await I.grabSource();
```
-**Parameters**
-
-- `text` Appium: support
+Appium: support
## grabTextFrom
@@ -779,7 +786,7 @@ I.openNewTab();
## pressKey
Presses a key on a focused element.
-Speical keys like 'Enter', 'Control', [etc](https://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value)
+Special keys like 'Enter', 'Control', [etc](https://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value)
will be replaced with corresponding unicode.
If modifier key is used (Control, Command, Alt, Shift) in array, it will be released afterwards.
@@ -1231,6 +1238,18 @@ I.wait(2); // wait 2 secs
- `sec` Appium: support
+## waitForDetached
+
+Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
+Element can be located by CSS or XPath.
+
+ I.waitForDetached('#popup');
+
+**Parameters**
+
+- `locator` element located by CSS|XPath|strict locator
+- `sec` time seconds to wait, 1 by defaultAppium: support
+
## waitForElement
Waits for element to be present on page (by default waits for 1sec).
@@ -1270,18 +1289,6 @@ Element can be located by CSS or XPath.
- `locator` element located by CSS|XPath|strict locator
- `sec` time seconds to wait, 1 by defaultAppium: support
-## waitForStalenessOf
-
-Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
-Element can be located by CSS or XPath.
-
- I.waitForStalenessOf('#popup');
-
-**Parameters**
-
-- `locator` element located by CSS|XPath|strict locator
-- `sec` time seconds to wait, 1 by defaultAppium: support
-
## waitForText
Waits for a text to appear (by default waits for 1sec).
@@ -1383,21 +1390,6 @@ I.waitUntil(() => window.requests == 0, 5);
- `sec` time seconds to wait, 1 by defaultAppium: support
- `timeoutMsg` (optional, default `null`)
-## waitUntilExists
-
-Waits for element not to be present on page (by default waits for 1sec).
-Element can be located by CSS or XPath.
-
-```js
-I.waitUntilExists('.btn.continue');
-I.waitUntilExists('.btn.continue', 5); // wait for 5 secs
-```
-
-**Parameters**
-
-- `locator` element located by CSS|XPath|strict locator
-- `sec` time seconds to wait, 1 by defaultAppium: support
-
## waitUrlEquals
Waits for the entire URL to match the expected
diff --git a/docs/hooks.md b/docs/hooks.md
index f4d5ce804..b79e05c43 100644
--- a/docs/hooks.md
+++ b/docs/hooks.md
@@ -252,37 +252,6 @@ module.exports = function() {
Whenever you execute tests with `--verbose` option you will see registered events and promises executed by a recorder.
-### Conditional Retries with Recorder
-
-It is possible to execute global conditional retries to handle unforseen errors.
-Lost connections and network issues are good candidates to be retried whenever they appear.
-
-This can be done inside a [helper](https://codecept.io/helpers/) using `recorder`:
-
-Example: Retrying rendering errors in Puppeteer.
-
-```js
-_before() {
- const recorder = require('codeceptjs').recorder;
- recorder.retry({
- retries: 2,
- when: err => err.message.indexOf('Cannot find context with specified id') > -1,
- });
-}
-```
-
-`recorder.retry` acts similarly to `I.retry()` and accepts the same parameters. It expects the `when` parameter to be set so it would handle only specific errors and not to retry for every failed step.
-
-Retry rules are available in array `recorder.retries`. The last retry rule can be disabled by running `recorder.retries.pop()`;
-
-```js
-// inside a helper
-disableLastRetryRule() {
- const recorder = require('codeceptjs').recorder;
- recorder.retries.pop();
-}
-```
-
### Output
Output module provides 4 verbosity levels. Depending on the mode you can have different information printed using corresponding functions.
diff --git a/docs/webapi/waitUntilExists.mustache b/docs/webapi/waitUntilExists.mustache
deleted file mode 100644
index 4f36c7e92..000000000
--- a/docs/webapi/waitUntilExists.mustache
+++ /dev/null
@@ -1,10 +0,0 @@
-Waits for element to be present on page (by default waits for 1sec).
-Element can be located by CSS or XPath.
-
-```js
-I.waitUntilExists('.btn.continue');
-I.waitUntilExists('.btn.continue', 5); // wait for 5 secs
-```
-
-@param locator element located by CSS|XPath|strict locator
-@param sec time seconds to wait, 1 by default
diff --git a/lib/helper/Nightmare.js b/lib/helper/Nightmare.js
index f81e3d4ee..d69d8921a 100644
--- a/lib/helper/Nightmare.js
+++ b/lib/helper/Nightmare.js
@@ -883,10 +883,17 @@ class Nightmare extends Helper {
});
}
+ async waitUntilExists(locator, sec) {
+ console.log(`waitUntilExists deprecated:
+ * use 'waitForElement' to wait for element to be attached
+ * use 'waitForDetached to wait for element to be removed'`);
+ return this.waitForDetached(locator, sec);
+ }
+
/**
- * {{> ../webapi/waitUntilExists }}
+ * {{> ../webapi/waitForDetached }}
*/
- async waitUntilExists(locator, sec) {
+ async waitForDetached(locator, sec) {
this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
sec = this.browser.options.waitForTimeout / 1000;
locator = new Locator(locator, 'css');
diff --git a/lib/helper/Puppeteer.js b/lib/helper/Puppeteer.js
index fe3bbb86b..f53e93037 100644
--- a/lib/helper/Puppeteer.js
+++ b/lib/helper/Puppeteer.js
@@ -1466,10 +1466,17 @@ class Puppeteer extends Helper {
return context.waitForFunction(fn, { timeout: waitTimeout });
}
+ async waitUntilExists(locator, sec) {
+ console.log(`waitUntilExists deprecated:
+ * use 'waitForElement' to wait for element to be attached
+ * use 'waitForDetached to wait for element to be removed'`);
+ return this.waitForDetached(locator, sec);
+ }
+
/**
- * {{> ../webapi/waitUntilExists }}
+ * {{> ../webapi/waitForDetached }}
*/
- async waitUntilExists(locator, sec) {
+ async waitForDetached(locator, sec) {
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
locator = new Locator(locator, 'css');
diff --git a/lib/helper/WebDriverIO.js b/lib/helper/WebDriverIO.js
index 10d496246..e1a8b6c4c 100644
--- a/lib/helper/WebDriverIO.js
+++ b/lib/helper/WebDriverIO.js
@@ -1420,15 +1420,10 @@ class WebDriverIO extends Helper {
}
async waitUntilExists(locator, sec = null) {
-<<<<<<< HEAD
- const aSec = sec || this.options.waitForTimeout;
- return this.browser.waitForExist(withStrictLocator.call(this, locator), aSec * 1000);
-=======
console.log(`waitUntilExists deprecated:
* use 'waitForElement' to wait for element to be attached
* use 'waitForDetached to wait for element to be removed'`);
return this.waitForStalenessOf(locator, sec);
->>>>>>> ab24a51a7bb977452cdff9f26cf772fa6de7ed77
}
@@ -1606,19 +1601,7 @@ class WebDriverIO extends Helper {
* {{> ../webapi/waitForDetached }}
* Appium: support
*/
-<<<<<<< HEAD
- async waitForStalenessOf(locator, sec = null) {
- return this.waitUntilNotExists(locator, sec);
- }
-
- /**
- * {{> ../webapi/waitForStalenessOf }}
- * Appium: support
- */
- async waitUntilNotExists(locator, sec = null) {
-=======
async waitForDetached(locator, sec = null) {
->>>>>>> ab24a51a7bb977452cdff9f26cf772fa6de7ed77
const aSec = sec || this.options.waitForTimeout;
return this.browser.waitUntil(async () => {
const res = await this.browser.elements(withStrictLocator.call(this, locator));
diff --git a/package.json b/package.json
index 68a258333..87d5d725d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "codeceptjs",
- "version": "1.1.4",
+ "version": "1.1.5",
"description": "Modern Era Acceptance Testing Framework for NodeJS",
"keywords": [
"acceptance",
@@ -52,7 +52,7 @@
"@types/node": "^8.9.3",
"chai": "^3.4.1",
"chai-as-promised": "^5.2.0",
- "co-mocha": "^1.2.1",
+ "co-mocha": "^1.2. left-pad --save1",
"documentation": "^4.0.0-beta1",
"eslint": "^4.17.0",
"eslint-config-airbnb-base": "^12.1.0",