Skip to content

Commit

Permalink
Merge pull request #137 from angrykoala/dev
Browse files Browse the repository at this point in the history
wendigo 0.7.4
  • Loading branch information
angrykoala authored Jun 6, 2018
2 parents b166929 + 5bc4501 commit 4de0a3a
Show file tree
Hide file tree
Showing 26 changed files with 775 additions and 470 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ env:
- NO_SANDBOX=true

script:
- npm test
- travis_retry npm test

cache:
directories:
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
0.7.4 / 2018-06-07
==================

* Browser.focus
* Browser.hover
* Assert.focus
* Minor bugs in tests fixed
* Request mock supports objects as response method
* Fixed bug where navigation to a different page breaks some methods

0.7.3 / 2018-06-01
==================

Expand Down
49 changes: 39 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ Waits until the given selector is no longer visible or doesn't exists, with the
await browser.waitUntilNotVisible(".toast");
```

**waitForUrl(url, timeout=500)**
**waitForUrl(url, timeout=500)**
Waits for page url to be the given url.

```js
Expand Down Expand Up @@ -391,7 +391,7 @@ Navigates to next page in history.
**refresh()**
Reloads current page.

**setViewport(viewportConfig)**
**setViewport(viewportConfig)**
Sets the configuration of the page viewport, using the same config as [Puppeteer method](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetviewportviewport).

```js
Expand All @@ -400,6 +400,16 @@ await browser.setViewport({width: 300});

> Unlike Puppeteer setViewport, no parameter is required, as the current values will be used for the new viewport.
**focus(selector)**
Focus the first element matching the given selector.

> Only CSS selectors supported
**hover(selector)**
Hovers over the first element matching the given selector.

> Only CSS selectors supported
## Assert
The submodule `browser.assert` provide some out-of-the-box assertions that can be used to easily write tests that are readable without having to specifically query for elements o perform evaluations. All the assertions have a last optional parameter (msg?) to define a custom assertion message.

Expand Down Expand Up @@ -563,16 +573,27 @@ Asserts that the first element matching the given selector has a checked value s

> Css, Xpath and Dom selectors supported
**disabled(selector, msg?)**
**disabled(selector, msg?)**
Asserts that the first element matching the given selector is disabled (has attribute disabled).

> Css, Xpath and Dom selectors supported
**enabled(selector, msg?)**
**enabled(selector, msg?)**
Asserts that the first element matching the given selector is enabled (doesn't have attribute disabled).

> Css, Xpath and Dom selectors supported
**focus(selector, msg?)**
Asserts that an element matching the given selector is focused.

```js
browser.click(".btn");
browser.assert.focus(".btn");
```

> Css, Xpath and Dom selectors supported

### Negative assertions
Most of the browser assertions have a negative version that can be used with `browser.assert.not`. Most of the "not" assertions are simply the inverse of the positive version.

Expand All @@ -594,7 +615,7 @@ If expected is an array, no element in it should match any element with given se
await browser.assert.not.text("p", "This text doesn't exists");
```

**textContains(selector, expected, msg?)**
**not.textContains(selector, expected, msg?)**
Asserts that no elements matching the given selector contain the expected text.

```js
Expand Down Expand Up @@ -675,16 +696,21 @@ Note that if the element doesn't have a checked value (i.e. is not a checkbox) t

> Css, Xpath and Dom selectors supported
**not.disabled(selector, msg?)**
**not.disabled(selector, msg?)**
Asserts that the first element matching the given selector is not disabled (same as assert.enabled).

> Css, Xpath and Dom selectors supported
**not.enabled(selector, msg?)**
**not.enabled(selector, msg?)**
Asserts that the first element matching the given selector is not enabled (same as assert.disabled).

> Css, Xpath and Dom selectors supported
**not.focus(selector, msg?)**
Asserts that none of the elements matching the given selector is focused.

> Css, Xpath and Dom selectors supported
## Cookies
The module `browser.cookies` provides a way to easily handle cookies through Puppeteer's api. All methods return Promises.

Expand Down Expand Up @@ -809,7 +835,7 @@ Response is an object with the following attributes:
* `status` Response status code, defaults to 200.
* `headers` Optional response headers.
* `contentType` If set, equals to setting Content-Type response header.
* `body` Optional response body. This must be a string
* `body` Optional response body. It can be a string or a json-serializable object

> This object matches the interface with Puppeteer's [respond method](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#requestrespondresponse)
Expand Down Expand Up @@ -1010,7 +1036,7 @@ This error may appear when running wendigo on certain systems and in most CI ser
For example `NO_SANDBOX=true npm test`.

### Running Tests With Travis CI
Running tests using Puppeteer's require disabling the sandbox running mode. This can easily be achieved by passing the environment variable `NO_SANDBOX=true`, this can be done either as part of the test execution command, as a Travis secret env variable or in the `.travis.yml` file itself:
Running tests using Puppeteer's require disabling the sandbox running mode. This can easily be achieved by passing the environment variable `NO_SANDBOX=true`, this can be done either as part of the test execution command, as a Travis secret env variable or in the `.travis.yml` file itself. It is recommended to add `travis_retry` to allow travis to execute the tests multiple times, as browser-based setup may fail frequently on travis workers:

```yml
language: node_js
Expand All @@ -1023,7 +1049,7 @@ env:
- NO_SANDBOX=true

script:
- npm test
- travis_retry npm test

cache:
directories:
Expand Down Expand Up @@ -1053,6 +1079,9 @@ test:
```
_Example of .gitlab-ci.yml_

### Assertion failed messages without error
If you are using node@10 and puppeteer 1.4.0 or less, you may experience messages such as `Assertion failed: No node found for selector`, this is due to a change in how `console.assertion` works in node 10 and how puppeteer uses it, these messages won't affect the tests, if the messages are a big problem for you, consider downgrading your node.js version, upgrading puppeteer if possible or overriding console.assert: `console.assert=()=>{}`.

> Remember to check [Puppeteer Troubleshooting](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md)

## Acknowledgements
Expand Down
5 changes: 4 additions & 1 deletion config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const path = require('path');
module.exports = {
injectionScripts: {
path: path.join(__dirname, "injection_scripts"),
files: ["selector_query.js", "wendigo_utils.js"]
files: {
WendigoQuery: "selector_query.js",
WendigoUtils: "wendigo_utils.js"
}
}
};
151 changes: 76 additions & 75 deletions injection_scripts/selector_query.js
Original file line number Diff line number Diff line change
@@ -1,79 +1,80 @@
"use strict";
if(!window.WendigoQuery) {
window.WendigoQuery = {
selectorTypes: { // Warning: Same as selector type
css: "css",
xpath: "xpath",
domElement: "domElement"
},
query(selector) {
const type = this._parseSelectorType(selector);
switch(type) {
case this.selectorTypes.css:
return this.queryCss(selector);
case this.selectorTypes.xpath:
return this.queryXPath(selector);
case this.selectorTypes.domElement:
return this.queryDomElement(selector);
default:
throw new Error(`Query Error: ${selector} with type ${type}`);
}
},
queryAll(selector) {
const type = this._parseSelectorType(selector);

window.WendigoQuery = {
selectorTypes: { // Warning: Same as selector type
css: "css",
xpath: "xpath",
domElement: "domElement"
},
query(selector) {
const type = this._parseSelectorType(selector);
switch(type) {
case this.selectorTypes.css:
return this.queryCss(selector);
case this.selectorTypes.xpath:
return this.queryXPath(selector);
case this.selectorTypes.domElement:
return this.queryDomElement(selector);
default:
throw new Error(`Query Error: ${selector} with type ${type}`);
}
},
queryAll(selector) {
const type = this._parseSelectorType(selector);
switch(type) {
case this.selectorTypes.css:
return this.queryCssAll(selector);
case this.selectorTypes.xpath:
return this.queryXPathAll(selector);
case this.selectorTypes.domElement:
return this.queryDomElementAll(selector);
default:
throw new Error(`QueryAll Error: ${selector} with type ${type}`);
}
},
queryCss(cssSelector) {
return document.querySelector(cssSelector);
},
queryCssAll(cssSelector) {
return Array.from(document.querySelectorAll(cssSelector));
},
queryDomElement(element) {
if(Array.isArray(element)) return element[0];
else return element;
},
queryDomElementAll(elements) {
if(Array.isArray(elements)) return elements;
else return [elements];
},
queryXPath(xPath) {
const xPathResult = document.evaluate(xPath, document, null, XPathResult.ANY_TYPE, null);
const result = xPathResult.iterateNext();
return result;
},
queryXPathAll(xPath) {
const xPathResult = document.evaluate(xPath, document, null, XPathResult.ANY_TYPE, null);
const result = [];
let r = xPathResult.iterateNext();
while(r !== null) {
result.push(r);
r = xPathResult.iterateNext();
}
return result;
},

switch(type) {
case this.selectorTypes.css:
return this.queryCssAll(selector);
case this.selectorTypes.xpath:
return this.queryXPathAll(selector);
case this.selectorTypes.domElement:
return this.queryDomElementAll(selector);
default:
throw new Error(`QueryAll Error: ${selector} with type ${type}`);
}
},
queryCss(cssSelector) {
return document.querySelector(cssSelector);
},
queryCssAll(cssSelector) {
return Array.from(document.querySelectorAll(cssSelector));
},
queryDomElement(element) {
if(Array.isArray(element)) return element[0];
else return element;
},
queryDomElementAll(elements) {
if(Array.isArray(elements)) return elements;
else return [elements];
},
queryXPath(xPath) {
const xPathResult = document.evaluate(xPath, document, null, XPathResult.ANY_TYPE, null);
const result = xPathResult.iterateNext();
return result;
},
queryXPathAll(xPath) {
const xPathResult = document.evaluate(xPath, document, null, XPathResult.ANY_TYPE, null);
const result = [];
let r = xPathResult.iterateNext();
while(r !== null) {
result.push(r);
r = xPathResult.iterateNext();
}
return result;
},
_parseSelectorType(selector) {
if(typeof(selector) === "string") {
return this._parseStringSelector(selector);
} else if(typeof(selector) === "object") {
return this.selectorTypes.domElement;
} else return null;
},

_parseSelectorType(selector) {
if(typeof(selector) === "string") {
return this._parseStringSelector(selector);
} else if(typeof(selector) === "object") {
return this.selectorTypes.domElement;
} else return null;
},

_parseStringSelector(selector) {
if(selector.length === 0) return null;
if(selector[0] === "/") return this.selectorTypes.xpath;
else return this.selectorTypes.css;
}
};
_parseStringSelector(selector) {
if(selector.length === 0) return null;
if(selector[0] === "/") return this.selectorTypes.xpath;
else return this.selectorTypes.css;
}
};
}
56 changes: 29 additions & 27 deletions injection_scripts/wendigo_utils.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
/* global WendigoQuery */
"use strict";

window.WendigoUtils = {
isVisible(element) {
if(!element) return false;
if (element === document) return true; // Top element, always visible
const style = window.getComputedStyle(element);
if (style.display === 'none') return false;
if (style.visibility === 'hidden') return false;
return this.isVisible(element.parentNode);
},
queryElement(selector) {
return WendigoQuery.query(selector);
},
queryAll(selector) {
return WendigoQuery.queryAll(selector);
},
xPathQuery(xPath) {
return WendigoQuery.queryXPathAll(xPath);
},
getStyles(element) {
const rawStyles = getComputedStyle(element);
const result = {};
for(let i = 0;i < rawStyles.length;i++) {
const name = rawStyles[i];
result[name] = rawStyles.getPropertyValue(name);
if(!window.WendigoUtils) {
window.WendigoUtils = {
isVisible(element) {
if(!element) return false;
if (element === document) return true; // Top element, always visible
const style = window.getComputedStyle(element);
if (style.display === 'none') return false;
if (style.visibility === 'hidden') return false;
return this.isVisible(element.parentNode);
},
queryElement(selector) {
return WendigoQuery.query(selector);
},
queryAll(selector) {
return WendigoQuery.queryAll(selector);
},
xPathQuery(xPath) {
return WendigoQuery.queryXPathAll(xPath);
},
getStyles(element) {
const rawStyles = getComputedStyle(element);
const result = {};
for(let i = 0;i < rawStyles.length;i++) {
const name = rawStyles[i];
result[name] = rawStyles.getPropertyValue(name);
}
return result;
}
return result;
}
};
};
}
Loading

0 comments on commit 4de0a3a

Please sign in to comment.