Skip to content

Commit

Permalink
Merge pull request #94 from angrykoala/dev
Browse files Browse the repository at this point in the history
0.4.6
  • Loading branch information
angrykoala authored Mar 24, 2018
2 parents f824cb6 + 67d6bc2 commit 012667e
Show file tree
Hide file tree
Showing 19 changed files with 455 additions and 104 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
0.4.6 / 2018-03-24
==================

* Browser.assert.cookie
* Cookies submodule
* Remove default assertions errors

0.4.5 / 2018-03-24
==================

Expand Down
79 changes: 68 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ _by @angrykoala_
**Wendigo** is a wrapper of [Puppeteer](https://github.com/GoogleChrome/puppeteer) with the purpose of making automated testing easier and simpler. Install it with `npm install --save-dev wendigo`

Consider the following example of a test using puppeteer:
Consider the following example of a test using Puppeteer:

```javascript
await page.click(".my-btn");
Expand All @@ -35,6 +35,7 @@ await browser.assert.text("#my-modal", "Button Clicked");
* [Wendigo](#wendigo)
* [Browser](#browser)
* [Assert](#assert)
* [Cookies](#cookies)
* [LocalStorage](#localstorage)
* [Errors](#errors)
* [Examples](#examples)
Expand All @@ -48,11 +49,11 @@ await browser.assert.text("#my-modal", "Button Clicked");
Wendigo is the main static class exported by the package. It provides the methods necessary to create browsers and disconnect from chrome, can be imported with `require('wendigo')`:

**static createBrowser(settings)**
Will create and return a [Browser](#Browser) instance. It will automatically launch and connect puppeteer and Chrome if an instance is not running.
Will create and return a [Browser](#Browser) instance. It will automatically launch and connect Puppeteer and Chrome if an instance is not running.

* _settings_ is an optional object with the settings to build the browser
* `log: false`: If true, it will log all the console events of the browser.
* Any settings that can be passed to puppeteer can be passed in createdBrowser, for example:
* Any settings that can be passed to Puppeteer can be passed in createdBrowser, for example:
* `headless: true`: If true, the browser will run on headless mode.
* `slowMo: 0`: Slows the execution of commands by given number of milliseconds

Expand All @@ -76,11 +77,11 @@ const browser=Wendigo.createBrowser({
Will stop and disconnect all the browsers. It should be called after finishing all the tests.

## Browser
The Browser instance is and interface with the `page` class of puppeteer.
The Browser instance is and interface with the `page` class of Puppeteer.

### Attributes
**page**
Puppeteer [page class](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page), allows access to puppeteer API if needed.
Puppeteer [page class](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page), allows access to Puppeteer API if needed.

```js
await browser.page.evaluate(()=>{
Expand Down Expand Up @@ -112,7 +113,7 @@ await browser.close();
```

**evaluate(cb, ...args)**
Evaluates given callback in the browser, passing n arguments. Returns the puppeteer's result of the evaluation.
Evaluates given callback in the browser, passing n arguments. Returns the Puppeteer's result of the evaluation.

```js
const selector = "h1";
Expand Down Expand Up @@ -332,7 +333,7 @@ const options=await browser.options("selector.my-selector"); // ["value1", "valu

> Css, Xpath and Dom selectors supported
**selectedOptions(selector)**
**selectedOptions(selector)**
Returns all the selected options of the first element matching the given selector. If no value is set, the text of the option will be returned.

Will throw if no element is found.
Expand Down Expand Up @@ -487,6 +488,16 @@ browser.assert.global("localStorage");
browser.assert.global("my-val", "dontpanic");
```

> Assertions related to LocalStorage can be found under each section
**cookie(name, expected?, msg?)**
Asserts that the cookie with the given name exists. If the expected parameter is passed, it will check that the cookie has that value.

```js
browser.assert.cookie("username");
browser.assert.cookie("username", "arthur_dent");
```

### 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 Down Expand Up @@ -569,11 +580,57 @@ Assert that the first element with given selector doesn't have the expected opti
**not.global(key, value?, msg?)**
Asserts that the global object (window) doesn't have the given key with the expected value. If not value (or undefined value) is provided, it will assert that the key doesn't exist or it is undefined.

**not.cookie(name, expected?, msg?)**
Asserts that the cookie with given name doesn't have the expected value. If no expected value is passed, it will check that the cookie doesn't exists (is undefined).

```js
browser.assert.not.cookie("not-a-cookie");
browser.assert.not.cookie("username", "not-user");
```

> Assertions related to LocalStorage can be found under each section
## Cookies
The module `browser.cookies` provides a way to easily handle cookies through Puppeteer's api. All methods return Promises.

**all()**
Returns all the cookies in the current page as an object

```js
const cookies = await browser.cookies.all(); // {username: "arthur_dent", email: "[email protected]"}
```

**get(name)**
Returns the value of the cookie with given name. Returns undefined if the cookie doesn't exists

> Assertions related to LocalStorage can be found under LocalStorage section
```js
const cookie = await browser.cookies.get("username"); // "arthur_dent"
```

**set(name, value)**
Sets the value of the cookie with given name. If it already exists it will be replaced.

```js
await browser.cookies.set("username", "marvin");
```

**delete(name)**
Deletes the cookie with given name if exists. Optionally an array can be passed and all the cookies will be removed. Won't do anything if the cookie doesn't exists.

```js
await browser.cookies.delete("username");
await browser.cookies.delete(["username", "email"]);
```

**clear()**
Deletes all the cookies of the current page.

```js
await browser.cookies.clear()
```

## LocalStorage
The module `browser.localStorage` provides a simple wrapper around the browser localStorage. All the methods return promises.
The module `browser.localStorage` provides a simple wrapper around the browser localStorage. All the methods return Promises.

**getItem(key)**
Returns the item with the given key. If no item exists return null.
Expand Down Expand Up @@ -645,7 +702,7 @@ Same as Node.js Assertion Error. It will be throw for any assertion.
Error defining a problem with a DOM query. Generally Thrown as an unexpected result of a query made in an action or assertion.

**FatalError**
Defines a Fatal Error with puppeteer (e.g. a connection error)
Defines a Fatal Error with Puppeteer (e.g. a connection error)

## Examples

Expand Down Expand Up @@ -693,7 +750,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:

```yml
language: node_js
Expand Down
109 changes: 71 additions & 38 deletions lib/assertions/browser_assertions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* global WendigoUtils */
"use strict";

const assert = require('assert');
const BrowserNotAssertions = require('./browser_not_assertions');
const elementsAssertionUtils = require('./utils/assert_elements');
const textUtils = require('./utils/text_utils');
Expand All @@ -18,7 +17,7 @@ module.exports = class BrowserAssertions {
exists(selector, msg) {
if(!msg) msg = `Expected element "${selector}" to exists`;
return this._browser.query(selector).then((element) => {
assert.strictEqual(Boolean(element), true, msg);
if(!element) return assertUtils.rejectAssertion(msg);
});
}

Expand All @@ -28,7 +27,7 @@ module.exports = class BrowserAssertions {
const element = WendigoUtils.queryElement(q);
return WendigoUtils.isVisible(element);
}, selector).then((visible) => {
assert.strictEqual(visible, true, msg);
if(!visible) return assertUtils.rejectAssertion(msg);
});
}

Expand All @@ -45,55 +44,62 @@ module.exports = class BrowserAssertions {
return assertUtils.rejectAssertion(msg, expected, texts);
}
}
return Promise.resolve();
});
}

textContains(selector, expected, msg) {
return this._browser.text(selector).then((texts) => {
for(const text of texts) {
if(text && text.includes(expected)) return Promise.resolve();
}
if(!msg) {
const foundText = texts.length === 0 ? "no text" : `"${texts.join(" ")}"`;
msg = `Expected element "${selector}" to contain text "${expected}", ${foundText} found`;
}
for(const text of texts) {
if(text && text.includes(expected)) return Promise.resolve();
}
assert(false, msg);
return assertUtils.rejectAssertion(msg, expected, texts);
});
}

title(expected, msg) {
return this._browser.title().then((title) => {
const foundTitle = title ? `"${title}"` : "no title";
if(!msg) msg = `Expected page title to be "${expected}", ${foundTitle} found`;
assert(textUtils.matchText(title, expected), msg);
if(!textUtils.matchText(title, expected)) {
if(!msg) msg = `Expected page title to be "${expected}", ${foundTitle} found`;
return assertUtils.rejectAssertion(msg, expected, title);
}
});
}

class(selector, expected, msg) {
return this._browser.class(selector).then((classes) => {
if(!msg) {
const foundClasses = classes.length === 0 ? "no classes" : `"${classes.join(" ")}"`;
msg = `Expected element "${selector}" to contain class "${expected}", ${foundClasses} found.`;
if(!classes.includes(expected)) {
if(!msg) {
const foundClasses = classes.length === 0 ? "no classes" : `"${classes.join(" ")}"`;
msg = `Expected element "${selector}" to contain class "${expected}", ${foundClasses} found.`;
}
return assertUtils.rejectAssertion(msg, expected, classes);
}
assert(classes.includes(expected), msg);
});
}

url(expected, msg) {
return this._browser.url().then((url) => {
if(!msg) msg = `Expected url to be "${expected}", "${url}" found`;
assert.strictEqual(url, expected, msg);
if(url !== expected) {
if(!msg) msg = `Expected url to be "${expected}", "${url}" found`;
return assertUtils.rejectAssertion(msg, expected, url);
}
});
}

value(selector, expected, msg) {
return this._browser.value(selector).then((value) => {
if(!msg) {
if(value === null) msg = `Expected element "${selector}" to have value "${expected}", no value found`;
else msg = `Expected element "${selector}" to have value "${expected}", "${value}" found`;
if(value !== expected) {
if(!msg) {
if(value === null) msg = `Expected element "${selector}" to have value "${expected}", no value found`;
else msg = `Expected element "${selector}" to have value "${expected}", "${value}" found`;
}
return assertUtils.rejectAssertion(msg, expected, value);
}
assert.strictEqual(value, expected, msg);
});
}

Expand All @@ -108,23 +114,25 @@ module.exports = class BrowserAssertions {
}
return this._browser.queryAll(selector).then((elements) => {
const elementsCount = elements.length;
if(!msg) msg = elementsAssertionUtils.getAssertionMessage(selector, assertCountData, elementsCount);
elementsAssertionUtils.makeAssertion(assertCountData, elementsCount, msg);
return elementsAssertionUtils.makeAssertion(selector, assertCountData, elementsCount, msg);
});
}

/* eslint-disable complexity */
attribute(selector, attribute, expectedValue, msg) {
return this._browser.attribute(selector, attribute).then((value) => {
if(expectedValue === undefined) {
if(!msg) msg = `Expected element "${selector}" to have attribute "${attribute}".`;
assert((value !== null), msg);
} else {
if(value === null) {
if(!msg) msg = `Expected element "${selector}" to have attribute "${attribute}".`;
return assertUtils.rejectAssertion(msg);
}
} else if(value !== expectedValue) {
if(!msg) {
msg = `Expected element "${selector}" to have attribute "${attribute}" with value "${expectedValue}"`;
if(value) msg = `${msg}, "${value}" found.`;
else msg = `${msg}.`;
}
assert.strictEqual(value, expectedValue, msg);
return assertUtils.rejectAssertion(msg, expectedValue, value);
}
}).catch(() => {
if(!msg) {
Expand All @@ -135,6 +143,7 @@ module.exports = class BrowserAssertions {
return assertUtils.rejectAssertion(msg, expectedValue, attribute);
});
}
/* eslint-enable complexity */

style(selector, style, expected, msg) {
return this._browser.evaluate((selector, style) => {
Expand All @@ -146,12 +155,14 @@ module.exports = class BrowserAssertions {
const error = ErrorFactory.generateQueryError(`Element "${selector}" not found when trying to assert style.`);
return Promise.reject(error);
}).then((value) => {
if(!msg) {
msg = `Expected element "${selector}" to have style "${style}" with value "${expected}"`;
if(value) msg = `${msg}, "${value}" found.`;
else msg = `${msg}, style not found.`;
if(value !== expected) {
if(!msg) {
msg = `Expected element "${selector}" to have style "${style}" with value "${expected}"`;
if(value) msg = `${msg}, "${value}" found.`;
else msg = `${msg}, style not found.`;
}
return assertUtils.rejectAssertion(msg, expected, value);
}
assert.strictEqual(value, expected, msg);
});
}

Expand Down Expand Up @@ -214,18 +225,40 @@ module.exports = class BrowserAssertions {
return window[k];
}, key).then((value) => {
if(expected === undefined) {
if(!msg) {
msg = `Expected "${key}" to be defined as global variable.`;
if(value === undefined) {
if(!msg) {
msg = `Expected "${key}" to be defined as global variable.`;
}
return assertUtils.rejectAssertion(msg);
}
assert(value !== undefined, msg);
} else{
if(!msg) {
msg = `Expected "${key}" to be defined as global variable with value "${expected}", "${value}" found.`;
if(value !== expected) {
if(!msg) {
msg = `Expected "${key}" to be defined as global variable with value "${expected}", "${value}" found.`;
}
return assertUtils.rejectAssertion(msg, expected, value);
}
assert(value === expected, msg);
}
});
}


cookie(name, expected, msg) {
return this._browser.cookies.get(name).then((value) => {
if(expected === undefined) {
if(value === undefined) {
if(!msg) {
msg = `Expected cookie "${name}" to exist.`;
}
return assertUtils.rejectAssertion(msg);
}
}else{
if(value !== expected) {
if(!msg) {
msg = `Expected cookie "${name}" to have value "${expected}", "${value}" found.`;
}
return assertUtils.rejectAssertion(msg, expected, value);
}
}
});
}
};
Loading

0 comments on commit 012667e

Please sign in to comment.