diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..77738287 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +dist/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 19651337..a0268058 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ typings/ ncp/ .DS_Store +dist/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b349c7db..6b1efc46 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,6 +12,7 @@ test: stage: test retry: 2 script: - - npm run lint + - npm run eslint + - npm run tslint - npm run markdown-lint - npm test diff --git a/.travis.yml b/.travis.yml index 175402da..16abb6e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,8 @@ env: - NO_SANDBOX=true script: - - npm run lint + - npm run eslint + - npm run tslint - npm run markdown-lint - travis_retry npm test diff --git a/@types/compositer/index.d.ts b/@types/compositer/index.d.ts new file mode 100644 index 00000000..89f0aefc --- /dev/null +++ b/@types/compositer/index.d.ts @@ -0,0 +1 @@ +declare module 'compositer'; diff --git a/@types/is-class/index.d.ts b/@types/is-class/index.d.ts new file mode 100644 index 00000000..a062fb87 --- /dev/null +++ b/@types/is-class/index.d.ts @@ -0,0 +1 @@ +declare module 'is-class'; diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fe5a1a2..174f6504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,35 @@ -1.13.1 / 2018-04-20 +2.0.0 / 2019-05-03 +================== + +* Wendigo refactored into TypeScript +* Browser.query and browser.queryAll now support XPath selectors +* Browser.queryXPath removed +* Removed clearRequestMocks option, mocks are only removed on browser close +* Cookies now support extra cookie parameters +* XPath improvements with axis support and minor fixes +* Added new methods to DomElement class +* More support for XPath and DOMElement selectors +* Complex subqueries with multiple parent elements supported +* Changes in plugin system. Dropped support for not assertions +* Removed deprecated methods assert.cookie, assert.webworker and assert.not.cookie +* Browser.request.all changed into a function to make it consistent with other modules +* WaitForRequest/Response and waitForNextRequest/Response moved to requests module +* Browser.assert.request renamed to browser.assert.requests to keep consistency +* Assertions now always return promises for consistency +* Fixed bug where settings on dialog module where not being updated properly +* Fixed bug where mocks with querystring where not being updated properly +* Removed dependency mixwith +* Dependencies updated +* Puppeteer updated to 1.15 +* Readme updated and several minor fixes in it + +1.13.1 / 2019-04-20 =================== * Some dependencies updated * Deprecation notice in favor of 2.0 -1.13.0 / 2018-03-29 +1.13.0 / 2019-03-29 =================== * Support for an object with assert and not functions for a plugin @@ -15,13 +40,13 @@ * Cookies is now fully implemented as a plugin * ElementFromPoint not returns null if no element is found -1.12.1 / 2018-03-25 +1.12.1 / 2019-03-25 =================== * Minor improvements to dockerfile * Fix of console.warn logs when set the option log: true -1.12.0 / 2018-03-25 +1.12.0 / 2019-03-25 =================== * Browser.assert.tag and browser.assert.not.tag @@ -30,7 +55,7 @@ * Added proxyServer option in create browser * Minor fixes in some error messages -1.11.0 / 2018-03-24 +1.11.0 / 2019-03-24 =================== * Browser.triggerEvent diff --git a/README.md b/README.md index 6fc3903d..cf9e8c32 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,13 @@ _by @angrykoala_ [![Travis (.org)](https://img.shields.io/travis/angrykoala/wendigo/master.svg?label=travis)](https://travis-ci.org/angrykoala/wendigo) [![Gitlab pipeline status](https://img.shields.io/gitlab/pipeline/angrykoala/wendigo/master.svg?label=gitlab-ci)](https://gitlab.com/angrykoala/wendigo/pipelines) -> A proper monster for front-end automated testing +> A proper monster for front-end automated testing. -**Wendigo** (_/wɛndɪɡo/_) is a wrapper of [Puppeteer](https://github.com/GoogleChrome/puppeteer) with the purpose of making automated testing easier. Install it with `npm install --save-dev wendigo`. +**Wendigo** (_/wɛndɪɡo/_) simplify your front-end and end-to-end automated testing using [Puppeteer](https://github.com/GoogleChrome/puppeteer). Install it with `npm install --save-dev wendigo`. -> **DEPRECATION NOTICE:** Wendigo 2.0 is planned for release soon, this documentation refers to Wendigo 1.x Only critical bugs will be released for version 1.x until v2 is ready with new features. Up to date development can be seen [here](https://github.com/angrykoala/wendigo/tree/major-release-2) and beta versions are available at +> **WARNING:** This documentation refers to Wendigo 2, if you are using previous versions of Wendigo, go to [here](https://github.com/angrykoala/wendigo/blob/1.13.1/README.md). -Consider the following example of a test using Puppeteer: +Consider the following example using just Puppeteer: ```javascript await page.click(".my-btn"); @@ -25,7 +25,7 @@ const modalText = await page.evaluate(() => { assert.strictEqual(modalText, "Button Clicked"); ``` -Using Wendigo, the same test could be written like this: +The same test can be written like this with Wendigo: ```javascript await browser.click(".my-btn"); @@ -33,8 +33,6 @@ await browser.waitFor("#my-modal"); await browser.assert.text("#my-modal", "Button Clicked"); ``` -> Recommended Node 10.15.1 LTS or superior - **Contents** * [Getting Started](#getting-started) @@ -66,7 +64,7 @@ await browser.assert.text("#my-modal", "Button Clicked"); ## Getting Started ### Requirements -To start using Wendigo for testing or browser automation. Make sure you've got [NodeJS](https://nodejs.org/en/) 8.0.0 or higher and npm installed in your system. You can check if they are installed and their versions with the following commands: +To start using Wendigo for testing or browser automation. Make sure you've got [NodeJS](https://nodejs.org/en/) 8.16.0 or higher and npm installed in your system. You can check if they are installed and their versions with the following commands: ```bash node -v @@ -89,7 +87,7 @@ You can use it with your favorite test suite or standalone in a JavaScript file ```js const Wendigo = require('wendigo'); -async function getMyPageHeader(){ +async function getMyPageHeader() { const browser = await Wendigo.createBrowser(); await browser.open("http://my-page"); const text = await browser.text("h1"); @@ -102,17 +100,37 @@ getMyPageHeader().then((text)=>{ }); ``` -If you find any problem, please check our [Troubleshooting](#troubleshooting) for solutions to the most common problems, or fill an [issue](https://github.com/angrykoala/wendigo/issues/new) if it appears to be a bug or lacking feature with Wendigo. More information and guides on how to use Wendigo available at the [wiki](https://github.com/angrykoala/wendigo/wiki) +#### Queries With Wendigo +Most methods in Wendigo will receive a _selector_ parameter to query for DOM elements on which execute actions or get data. Unless specified these queries can be performed by passing a CSS selector (e.g. `div`, `.container`), an xPath selector (`//*[text()='my text']`) or passing a [DOM Element](#dom-element). + +For example: + +```js +const myElement = await browser.query(".div"); + +await browser.text(".div"); // My Element Text +await browser.text(myElement); // My Element Text +``` + +#### Using Wendigo With TypesScript + +Wendigo 2.0 and higher contains typings, so importing it in a TyeScript project is enough for types support: + +```typescript +import * as Wendigo from 'wendigo'; +``` + +> If you find any problem, please check our [Troubleshooting](#troubleshooting) for solutions, or fill an [issue](https://github.com/angrykoala/wendigo/issues/new) if it appears to be a bug or lacking feature with Wendigo. More information and guides on how to use Wendigo available at the [wiki](https://github.com/angrykoala/wendigo/wiki) ## Api ### Wendigo Class -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')`: +Wendigo is the only class exported by the package. It provides the methods necessary to create browsers and disconnect from chrome, can be imported with `require('wendigo')`: **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 promise to a [Browser](#Browser) instance. It will automatically launch and connect Puppeteer and Chrome. -* _settings_ is an optional object with the settings to build the browser +* _settings_: an optional object with the configuration for the browser * `log: false`: If true, it will log all the console events of the browser. * `incognito: false`: If true, the browser will open as an incognito browser. * `userAgent`: If defined, the default user agent will be overridden. @@ -121,20 +139,18 @@ Will create and return a [Browser](#Browser) instance. It will automatically lau * `dismissAllDialogs`: This will automatically dismiss any native dialog (`alert`, `prompt`) when appearing. * `bypassCSP: true`: If set to false, puppeteer may fail if Content Security Policy is set in the page. * `proxyServer: null`: If defined, Chromium will run with the option `--proxy-server` set to the given address. - * Any settings that can be passed to Puppeteer can be passed in createBrowser, for example: + * Any settings that can be passed to Puppeteer can be passed to createBrowser, 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 Examples: ```js -const Wendigo = require('wendigo'); -const browser = Wendigo.createBrowser(); // Using default options +const browser = await Wendigo.createBrowser(); // Using default options ``` ```js -const Wendigo = require('wendigo'); -const browser = Wendigo.createBrowser({ +const browser = await Wendigo.createBrowser({ headless: false, slowMo: 500 }); // Using options to see what's happening @@ -183,19 +199,18 @@ await browser.open("http://localhost:8000"); The following options can be passed: -* `clearRequestMocks` (default: true): Clears all previous mocks in the requests module * `viewport`: Viewport config to set when opening the browser, uses the same syntax as `setViewport` * `queryString`: Querystring to be appended to the url, can be a string or object. Avoid using this parameter if a query string is already present in the url **openFile(path, options?)** -Opens the given file from the browser. Same options as `open` can be passed. The file will be passed by appending `file://` to the absolute path. +Opens the given file. Same options as `open` can be passed. The file will be passed by appending `file://` to the absolute path. ```js await browser.open("static/index.html"); ``` **close()** -Close the browser, it should be called after finishing using the browser. Avoid creating a new browser before closing the previous one if possible. Having multiple open browsers will cause performance degradation in your tests. +Close the browser, it should be called after finishing using the browser instance. Avoid creating a new browser before closing the previous one if possible. Having multiple open browsers will cause performance degradation in your tests. ```js await browser.close(); @@ -211,49 +226,31 @@ const elementText = await browser.evaluate((s) => { }, selector); // My Title ``` -This method, unlike `browser.page.evaluate` will automatically parse DOMElements arguments and DOMElements returns: - -```js -const selector = "h1"; -const element = await browser.evaluate((s) => { - return document.querySelector(s); -}, selector); // DOMElement - -const elementText = await browser.evaluate((e)=>{ - return e.textContent; -}, element); // My Title -``` +This method, unlike `browser.page.evaluate` will automatically parse any argument if possible: **query(selector, childSelector?)** -Queries the given css selector and returns a DOM element. If multiple elements are matched, only the first will be returned. Returns null if no element found. +Queries the given selector (css, xpath or DomElement) and returns a [DOMElement](#dom-element). If multiple elements match, only the first will be returned. Returns null if no element found. ```js const element = await browser.query("h1"); ``` -Optionally, query supports 2 parameters, the first being a DOMElement and the selector as the second one. The query will then be performed only on the elements under the parent. - -**queryAll(selector, childSelector?)** -Returns an array with all the DOM elements that match the given css selector. +Optionally, 2 parameters can be passed. A query will be performed only on the nested elements of the first selector: ```js -const elements = await browser.queryAll("h1"); -elements.length; // 2 +const element = await browser.query(".div"); +const children = await browser.query(element, "p"); // First paragraph under element .div ``` -Optionally, queryAll supports 2 parameters, the first being a DOMElement and the selector as the second one. The query will then be performed only on the elements under the parent. - -> All the Dom elements returned by queryElement and queryAll can be used instead of a selector in other methods and assertions. - -**queryXPath(xPathSelector)** -Returns an array with the DOM elements matching the xPath selector. +**queryAll(selector, childSelector?)** +Returns an array with all the [DOMElement](#dom-element) matching the given selector. ```js -const elements = await browser.queryXPath('//p[contains(text(),"My first paragraph")]'); -elements[0].textContent; // "My first paragraph" +const elements = await browser.queryAll("h1"); +elements.length; // 2 ``` -> The DomElement class returned by all query methods provides an interface to Puppeteer's ElementHandle class, it can be accesed with the property `element` +Optionally, queryAll supports 2 parameters. The query will then be performed only on the elements under the first selector. **elementFromPoint(x, y)** Given the coordinates (in pixels) as two numbers, returns the topmost DomElement in that position or `null` if no element is present. @@ -261,22 +258,21 @@ Given the coordinates (in pixels) as two numbers, returns the topmost DomElement ```js const element = await browser.elementFromPoint(500, 150); await browser.text(element); // ["My Title"] - ``` **addScript(scriptPath)** Executes the given script in the browser context. Useful to set helper methods and functions. This method must be called after the page is already loaded, if another page is loaded, the scripts won't be re-executed. If these scripts are required for a plugin to work, remember to execute this method on the `_afterOpen` hook. -It is heavily recommended to only use this to load helper functions, and not execute anything that might cause side effects. Anything loaded as a script may interfere with the behavior of the page or Wendigo. It is recommended to **always** check if the object of function you are loading already exists before loading, remember that `WendigoUtils` and `WendigoQuery` objects in `window` are required for Wendigo to work, so do not override them. +It is heavily recommended to only use this to load helper functions, and not execute anything that might cause side effects. Anything loaded as a script may interfere with the behavior of the page or Wendigo. It is recommended to **always** check if the object of function you are loading already exists before loading, remember that `WendigoUtils`, `WendigoQuery` and `WendigoPathFinder` objects are required for Wendigo to work and overriding them will cause problems. **class(selector)** -Returns and array with the classes of the first element returned from the given css selector. Throws if no element is found. +Returns and array with the classes of the first element found, throws if no element found. ```js const classes = await browser.class("div.container.main"); // Returns ["container", "main", "another-class"] ``` -Using a dom node: +Using a DOMElement: ```js const node = await browser.query("div.container.main"); @@ -284,7 +280,7 @@ const classes = await browser.class(node); // Returns ["container", "main", "ano ``` **value(selector)** -Returns the value of the first element with given selector. Returns _null_ if no element or value found. +Returns the value of the first element with given selector. Throws if no element or value found. ```js const value = await browser.value("input.my-input"); @@ -301,7 +297,7 @@ const hiddentAttr2 = await browser.attribute(".not-hidden-element", "hidden"); / ``` **styles(selector)** -Returns an object with all the computed css styles of the first element matching the given selector. +Returns an object with all the computed css styles of the first element matching the given selector, throws if no element is found. ```js const styles = await browser.styles("h1.my-title"); @@ -309,31 +305,54 @@ styles.color; // 'rgb(255, 0, 0)' ``` **style(selector, style)** -Returns the value of the given style of the first element matching the give nselector. Returns undefined if the style doesn't exists. Throws if the element is not found. +Returns the value of the given style of the first element matching the given selector. Returns undefined if the style doesn't exists. Throws if no element found. ```js const style = await browser.style("h1.my-title", color); // 'rgb(255, 0, 0)' ``` **checked(selector)** -Returns true if the first element matching the given selector (checkbox) is checked. If the value is not a checkbox and doesn't have checked property set, it will return undefined. +Returns true if the first element matching the given selector (checkbox) is checked. If the value is not a checkbox and doesn't have checked property set, it will return undefined. Throws if no element is found. **text(selector)** -Returns an array with all text contents of the elements matching the css selector +Returns an array with the texts of the elements matching the given selector. ```js const texts = await browser.text("p"); // ["My First Paragraph", "My Second Paragraph"] ``` +**innerHtml(selector)** +Returns an array with the innerHtml strings of all the elements matching the given selector + +```js +await browser.innerHtml("p"); // ["my first paragraph"] +``` + +**title()** +Returns the page title. + +**html()** +Returns the page HTML as string. It will return the HTML as it was before performing any actions. + +**frames()** +Returns all the [frames](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#class-frame) attached to the page + +**url()** +Returns the current url of the page. + **click(selector, index?)** -Clicks all the elements with the matching css selector, if the index parameter is set, only the nth element will be clicked. Returns the number of elements clicked. +Clicks all the elements with the matching selector, if the index parameter is set, only the nth element will be clicked. Returns the number of elements clicked. ```js await browser.click("button.btn"); ``` +An array of DOMElements is also supported as selector. + Optionally, if two numbers are passed, position x, y (in pixels) will be clicked. In this case, null with be returned instead of the clicked elements. +> **Warning:** Elements are clicked sequentially, if one of them is a link to an external page, subsequent clicks will fail. + **clickText(selector?, text, index?)** Clicks all the elements matching given text. Returns the number of elements clicked. @@ -350,7 +369,7 @@ await browser.clickText(".container", "Click Me!", 2); // Clicks the second elem ``` **clickTextContaining(selector?, text, index?)** -Same as clickText, but matches with any text containing the given parameter. +Same as clickText, but matches with any text containing the given string. **clickAndWaitForNavigation(selector, timeout=500)** Clicks an element and waits until a navigation event is triggered. Recommended for links to different pages. Keep in mind that not all the clicks will trigger a navigation event. @@ -361,35 +380,35 @@ await browser.clickAndWaitForNavigation(".home-button"); await browser.url(); // my-page/home ``` -> clickAndWaitForNavigation may delay up to 100ms after the given timeout while waiting for the page to load +> clickAndWaitForNavigation may delay up to 100ms after the given timeout while waiting for the page to load. **waitAndClick(selector, timeout=500)** -Waits for an element to exists and be visible before clicking it. Recommended for clicking elements that may have a delay before appearing. +Waits for an element to exists and be visible before clicking it. Useful for clicking elements that may have a delay before appearing. -> Only Css and XPath Selectors supported +> Only Css Selectors supported. **tap(selector, index?)** -Performs a touchscreen tap action, if the index parameter is set, only the nth element will be tapped. Returns the number of elements tapped. The interface is compatible with browser.click +Performs a touchscreen tap action on all the elements matching the given selector, if the index parameter is set, only the nth element will be tapped. Returns the number of elements tapped. The interface is compatible with browser.click. If two numbers are passed, the given coordinates are clicked. **check(selector)** -Checks the first element matching given selector. Setting its checked property to true. +Checks the first element matching given selector. Setting its checked property to true. Throws if no element is found. **uncheck(selector)** -Unchecks the first element matching given selector. Setting its checked property to false. +Unchecks the first element matching given selector. Setting its checked property to false. Throws if no element is found -**title()** -Returns the page title. +**focus(selector)** +Focus the first element matching the given selector. -**html()** -Returns the page html as string. It will return the html as it was before performing any actions. +**blur(selector)** +Unfocus the first element matching the given selector. -**frames()** -Returns all the [frames](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#class-frame) attached to the page +**hover(selector)** +Hovers over the first element matching the given selector. -**url()** -Returns the current url of the page. +**scroll(value, xValue?)** +Vertically scrolls the page to the given value on pixels, an optional xValue can be passed for horizontal scrolling. If value is a selector or DomElement, the page will scroll until that element is at view. **screenshot(options?)** Takes a screenshot of the page. This is just a direct interface to [Puppeteer's screenshot method](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagescreenshotoptions) and will use the same options, please check Puppeteer docs for the updated usage. It will return the image as a string (base64) or Buffer depending on the encoding. If an option path is defined, the image will be created on given path. @@ -412,43 +431,60 @@ const base64Image = await browser.screenshotOfElement("#my-dashboard", { }) ``` -**mockDate(date, options?)** -Mocks the browser's Date object so it returns the expected date instead of current date when using `new Date()` without parameters or `Date.now()`. The first parameter must be a JavaScript Date object. The following options are supported: +**type(selector, text, options?)** +Types given text in the first element matching the selector. If a value is already present, writes the new value at the beginning. Throws if no elements is found. -* `freeze: true`: if set to true, the new Date objects will always return the given date as current date, if false, the expected date will increase normally as time passes. +The following options passed as an object are supported: + +* _delay_: If a delay is given, it will delay the given ms for each key press. ```js -await browser.mockDate(new Date(2010,10,6)); // Mocks to 6-sept 2010 +await browser.type("input.my-input", "My Input"); +``` -await browser.evaluate(() => { - const d = new Date(); // 6-sept 2010 - const d2 = new Date(2011,10,10); // 10-sept 2011 -}) +**keyPress(key, count?)** +Press a keyboard key, the key can be the name of any key supporter by [Puppeteer](https://github.com/GoogleChrome/puppeteer/blob/master/lib/USKeyboardLayout.js) + +If an array is passed, all the keys will be pressed consecutively. If count parameter is passed, all the keys will be pressed that given count times. + +```js +await browser.keyPress("Enter"); // Press Enter once +await browser.keyPress("Escape", 2); // Press Enter twice + +await browser.keyPress(["Enter", "Escape", "Enter"]); ``` +**uploadFile(selector, path)** +Sets the value of an input file element matching given selector. Path can be absolute or relative to the current working directory. + ```js -await browser.mockDate(new Date(2010,10,6), { - freeze: false -}); +await browser.uploadFile("input.my-file-input", "./my/file/path.txt"); +``` -await browser.evaluate(() => { - const d = new Date(); // 6-sept 2010 plus some milliseconds -}); +**select(selector, value)** +Will select the given value in the _select_ tag of the first element matching the given selector, removing all previous selections. Returns an array with the values that could be selected correctly. -await browser.wait(1000); +Value can be a string or an array. If the select is multiple all elements in value will be selected, if not only the first element in the select options will. -await browser.evaluate(() => { - const d = new Date(); // 6-sept 2010 plus one second and some milliseconds -}) +Will throw if no elements were found. + +```js +await browser.select("select.language-select", ["spanish", "english"]); // Returns ["spanish", "english"] ``` -> Keep in mind that using Date as a functions (`Date()`) is not supported by mocked dates. It is recommended to use timestamps to avoid problems with different timezones between the browser and Node. +If the option doesn't have a value, the text should be provided. -**clearDateMock()** -Clears the date mock, if any, returning to the native Date object. +> Only Css Selectors supported + +**clearValue(selector)** +Clears any value that exists in any of the elements matched by the given selector. Setting the value to `""`. + +```js +await browser.clearValue("input.my-input"); +``` **wait(ms=250)** -Waits for the given milliseconds. +Waits the given milliseconds. **waitFor(selector, timeout=500, ...args?)** Waits for given selector to exists and be visible, with the given timeout in milliseconds. @@ -466,7 +502,7 @@ await browser.waitFor((s) => { // Waits for 2 or more elements to be in the page }, 600, ".my-elements"); ``` -> Css and Xpath selectors supported only. +> Css selectors supported only. **waitUntilNotVisible(selector, timeout=500)** Waits until the given selector is no longer visible or doesn't exists, with the given timeout in milliseconds. @@ -475,7 +511,7 @@ Waits until the given selector is no longer visible or doesn't exists, with the await browser.waitUntilNotVisible(".toast"); ``` -> Css and XPath selectors supported only. +> Css selectors supported only. **waitForUrl(url, timeout=500)** Waits for the page to have the given url. The url can be a string or a RegExp. @@ -493,22 +529,6 @@ await browser.waitForText("Click me!"); await browser.clickText("Click me!"); ``` -**waitForRequest(url, timeout=500)** -Waits until a request with given url is done. This will resolve immediately if the requests was already made, to wait without taking in account past requests use `waitForNextRequest`. - -```js -await browser.waitForRequest("my-url"); -``` - -**waitForResponse(url, timeout=500)** -Waits until a response to the given url is done. This will resolve immediately if the response was already received, to wait without taking in account past requests use `waitForNextResponse`. - -**waitForNextRequest(url ,timeout=500)** -Waits until next request with given url is done. If the request was already made, this method will wait until next one. - -**waitForNextResponse(url ,timeout=500)** -Waits until next response with given url is received. If the response was already received, this method will wait until next one. - **waitForNavigation(timeout=500)** Waits until next page is loaded, recommended after following a link to a different page. Keep in mind that a navigation within a SPA won't necessarily trigger a navigation event. @@ -517,6 +537,9 @@ Waits until next page is loaded, recommended after following a link to a differe **waitUntilEnabled(selector, timeout=500)** Waits until the first element matching the given selector has the attribute `disabled` set to null. +**waitForPageLoad()** +Waits until a dom ready event is fired, this method will also wait until Wendigo is ready to perform assertions on the given page. + **findByText(selector?, text)** Returns an array with the elements with text content matching the given text. @@ -538,7 +561,7 @@ elements.length; // 2 Optionally, a selector can be passed as first argument to perform a text search on children of that element only. **findByAttribute(attributeName, attributeValue?)** -Returns an array with all elements having an attribute matching the given name and value. If no value is assigned, it will match all elements with that attribute, regardless of the value. Use empty string as value to match all the elements with an attribute without value (e.g. `