dce-selenium
Selenium library to simplify integration testing on multiple browsers.
Table of Contents
Writing Tests
-
Create a test/selenium folder for your selenium tests
-
Import dce-selenium at the top of each test:
require('dce-selenium');
...
-
Use standard Mocha testing practices, but use describeS and itS instead of describe and it:
describeS('My App', function () {
itS('Opens', async function (driver) {
await driver.visit('https://www.website.com/');
...
});
});
-
To add a timeout to a test, call itS like this: itS(title, timeout, testFunction). Default timeout is 45s.
describeS('My App', function () {
itS('Logs in', 5000, async function (driver) {
await driver.visit('https://www.website.com/login');
...
});
});
-
To add code that runs before or after each test, add arguments to the describe handler:
describeS('My App', function (beforeEachS, afterEachS) {
beforeEachS(async function (driver) {
});
afterEachS(async function (driver) {
});
});
-
See "Driver Functions" below for a list of actions the driver can perform
Running Tests
To run your tests on all non-headless browsers (Chrome, Firefox, and Safari if on Mac), use:
npm run selenium
To run your tests on specific browser(s), use:
npm run selenium --chrome
npm run selenium --firefox
npm run selenium --safari
npm run selenium --safari-stp
npm run selenium --headless-chrome
npm run selenium --chrome --safari
To run your tests with less printing to the terminal, use the --silent parameter. Example:
npm run selenium --chrome --silent
Snapshots
When you run your tests, a test/snapshots folder will be created. Check it out!
Environment Config
Add config parameters to your test/selenium/config.json file to customize how dce-selenium works.
| defaultHost | a default hostname to use when driver.visit is passed a path, not a full url | none |
| dontUseHTTPS | if true, when driver.visit is passed a path. not a full url, we will visit the host using HTTP instead of HTTPS | false |
| noSnapshots | if true, no snapshots are taken | false |
Setting up a New Project
To add dce-selenium to your NPM project, use our initializer:
npm init dce-selenium
Notes:
- Your npm project must already be initialized with
npm init or npm init caccl
- This initializer automatically installs dependencies, creates a
/test folder, and adds the npm run selenium script to package.json
Driver Functions
This is the list of built-in functions the driver can perform. Every function is asynchronous, so you must use the await command to wait for it to complete.
To call any driver function, just call driver.functionName (driver is a global variable):
await driver.visit('https://www.my-website.com');
await driver.click('#login-button');
await driver.typeInto('#username-field', 'divardo');
await driver.typeInto('#password-field', '142509');
Custom functions: to create your own functions, see the info at the end of this section.
Logging
log(object) - print to the log
Arguments:
object - a string or any object to print to the terminal
Note: use this function instead of console.log for better log formatting.
Example:
driver.log(`The current status is ${status}`);
Navigation
visit(location, [locationToWaitFor]) – visit a webpage and wait for it to load
Arguments:
location – either full url or just path. If location is a path, defaultHost and dontUseHTTPS are used to determine the host and protocol for the url.
locationToWaitFor – optional: the location or list of locations to wait for before resolving. If the location we're visiting redirects the user elsewhere, we need to wait for that location instead. Put that final location as this locationToWaitFor. If there are more than one possible final locations, include an array. Defaults to same value as location.
Example:
await driver.visit('/about');
Example with redirect:
await driver.visit('/contact', '/email');
Example with nondeterministic redirect:
await driver.visit('/contact', ['/email', '/phone']);
post(location, body, [finalLocation]) – visit a webpage and wait for it to load
Arguments:
location – either full url or just path. If location is a path, defaultHost and dontUseHTTPS are used to determine the host and protocol for the url.
body – the POST request body to send.
locationToWaitFor – optional: the location or list of locations to wait for before resolving. If the location we're visiting redirects the user elsewhere, we need to wait for that location instead. Put that final location as this locationToWaitFor. If there are more than one possible final locations, include an array. Defaults to same value as location.
Example:
await driver.post('/login', {
user: 'admin',
password: 'Pa$$w0rD',
});
Interactions
click(cssSelectorOrElem) – click an item on the page
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the item to click
Example:
await driver.click('#support-button');
openAnchorInSameTab(cssSelectorOrElem, [locationToWaitFor]) - open an anchor tab in the current tab even if it was made to open in another tab
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the anchor tag
locationToWaitFor – optional: the location or list of locations to wait for before resolving. If the location we're visiting redirects the user elsewhere, we need to wait for that location instead. Put that final location as this locationToWaitFor. If there are more than one possible final locations, include an array. Defaults to same value as location.
Example:
await driver.openAnchorInSameTab('#contact-button');
Example where button leads to /contact which redirects to /email:
await driver.openAnchorInSameTab('#contact-button', '/email');
Example where button leads to /contact which either redirects to /email or /phone:
await driver.openAnchorInSameTab('#contact-button', ['/email', '/phone']);
clickByContents(contents, [cssSelector]) – click an item (find using its contents)
Find an item containing contents in its body and click it.
Arguments:
contents – the text contents of the item to click (may be a substring)
cssSelector – the css selector that further limits the items in question
Example:
await driver.clickByContents('Log In');
typeInto(cssSelectorOrElem, text) – type in an html element
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the item to type into
text – the text to type
Example:
await driver.typeInto('#username', 'admin');
await driver.typeInto('#password', 'Pa$$w0rD');
await driver.clickByContents('Log In');
Note: to type a backspace, use the driver.BACKSPACE character.
Example:
await driver.typeInto('#search', 'dogs');
await driver.typeInto('#search', driver.BACKSPACE);
simulateKeystrokesIntoDocument(text, [finishWithEnter]) – simulate keystroke into the page document
Arguments:
text – the text to type
finishWithEnter – if true, the enter key is pressed after the text is typed
Example:
await driver.simulateKeystrokesIntoDocument('test', true);
scrollTo(cssSelectorOrElem) – scroll to an element
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the item to scroll to
Example:
await driver.scrollTo('#footer');
chooseSelectItem(cssSelectorOrElem, item) – select an item from a select-based dropdown based on its human-visible text
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the select item to interact with
item – the human-readable text of the option to choose
Example:
await driver.chooseSelectValue('#card-types', 'MasterCard Debit');
chooseSelectValue(cssSelectorOrElem, value) – select an item from a select-based dropdown based on the item's value attribute
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the select item to interact with
value – the value attribute of the option to select
Example:
await driver.chooseSelectValue('#card-types', 'mc-debit');
chooseFile(cssSelectorOrElem, filePath) – choose a file for a file input field
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the file chooser element
filePath – the path of the file with respect to the project directory (the directory from which you started the selenium tests)
Example:
const path = require('path');
...
await driver.chooseFile('#file-upload', '/test/resources/images/profile.png');
await driver.click('#upload');
Data
getTitle() – gets the title of the page
Returns the title of the current page.
Example:
assert.equal(await driver.getTitle(), 'Divard\'s Profile', 'Page title is wrong');
getSource() – gets the source of the page
Returns the source of the current page.
Example:
const body = await driver.getSource();
assert(body.includes('src="https://code.jquery.com'), 'No jQuery embed');
getJSON() – gets the JSON of the page
Returns the JSON object of the current page (only valid if the current url points to a JSON object).
Example:
await driver.visit('/api/user/profile');
const profile = await driver.getJSON();
driver.log(`The current user's name is: ${profile.name}`);
getBody() - gets the html body of the page
Return the html body of the page.
Example:
const body = await driver.getBody();
const numAtSymbols = (body.split('@').length - 1);
assert(numAtSymbols >= 3, `Not enough "@" symbols: only found ${numAtSymbols}.`);
getURL() - gets the url of the page
Return the url of the page.
Example:
const url = await driver.getURL();
assert(url.endsWith('/about'), 'URL does not end with /about');
getQuery() - gets the query parameters of the page
Return the query parameters of the page in the form { name: value }.
Example:
const queryParams = await driver.getQuery();
const { name, email } = queryParams;
Elements
elementExists(cssSelector) - checks if an element exists
Returns true if the element exists.
Arguments:
cssSelector – the css selector identifying the item
Example:
assert(await driver.elementExists('#search-box'), 'No search box');
elementAbsent(cssSelector) - checks if an element does not exist
Returns true if the element does not exist.
Arguments:
cssSelector – the css selector identifying the item
Example:
assert(await driver.elementAbsent('#warning-message'), 'Warning message found');
elementWithContentsExists(contents, [cssSelector]) – check if an element with specific contents exists
Return true if the element exists.
Arguments:
contents – the text contents of the element we're looking for
cssSelector – the css selector that further limits the search
Example:
const submitVisible = await driver.elementWithContentsExists('Submit');
if (submitVisible) {
await driver.clickByContents('Submit');
}
elementWithContentsAbsent(contents, [cssSelector]) – check if an element with specific contents does not exist
Returns true if the element does not exist.
Arguments:
contents – the text contents of the element we're looking for
cssSelector – the css selector that further limits the search
Example:
const needToExpand = elementWithContentsAbsent('This is part of the body of the description');
if (needToExpand) {
await driver.click('#expand-description');
}
getElement(cssSelector) - find an element by css selector
Arguments:
cssSelector - the css selector
Example:
const searchButtonElement = await driver.getElement('table#cities');
getElements(cssSelector) - find all elements that match a css selector
Arguments:
cssSelector - the css selector
Example:
const images = await driver.getElements('img');
assert.equal(
images.length,
3,
'The wrong number of images were found in the page'
);
getElementByContents(contents, [cssSelector]) – find an element by its contents
Arguments:
contents – the text contents of the element we're looking for
cssSelector – the css selector that further limits the search
Example:
const searchButtonElement = await driver.getElementByContents('Search');
parentOf(cssSelectorOrElem) – given a selector or an element, finds the parent of the element
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the child element
Example:
const nameElement = await driver.getElementByContents('Sarah');
const profileElement = await driver.parentOf(nameElement);
await driver.click(profileElement);
descendantOf(element, cssSelector) - given an element and a cssSelector, finds the first descendant of the element that matches the css selector
Arguments:
element - the parent element
cssSelector - the css selector that identifies the desired descendant
Example:
const elem = await driver.getElement('div#main');
const button = await driver.descendantOf(elem, 'button');
listSelectItems(cssSelectorOrElem) - lists the human-readable text for the items in a select-based dropdown
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the select element
Example:
const cards = await listSelectItems('#card-types');
> ['MasterCard Credit', 'MasterCard Debit', 'Visa', 'Discover']
listSelectValues(cssSelectorOrElem) - lists the values for the items in a select-based dropdown
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the select element
Example:
const cards = await listSelectValues('#card-types');
> ['mc-credit', 'mc-debit', 'visa', 'discover']
getElementInnerHTML(cssSelectorOrElement) - gets the innerHTML of an element
Arguments:
cssSelectorOrElem – the css selector or the WebElement that identifies the item to get contents of
Example:
const html = await getElementInnerHTML('#message');
getEmbeddedMetadata() - Searches the page for a #embedded-metadata element and parses the stringified json content inside it
Example:
const metadata = await driver.getEmbeddedMetadata();
Session
reset() – reset the browser session
Example:
await driver.reset();
Waiting
pause() – wait for the user to press enter in the terminal
Example:
await driver.pause();
wait(ms) – wait for a specific number of milliseconds
Arguments:
ms – number of milliseconds to wait
Example:
await driver.wait(2000);
waitForElementVisible(cssSelector, timeout) – wait for an element to be visible
Arguments:
cssSelector – the css selector of the element to wait for
[timeout=10000] – number of ms to wait before timing out
Example:
await driver.waitForElementVisible('#title-bar');
waitForElementWithContentsVisible([see below]) – wait for an element with contents to be visible
Either use separated arguments:
contents – the text contents to search for
[cssSelector] – an optional css selector to further limit the search
[timeout=10000] – the timeout of the wait in ms
Example:
await waitForElementWithContentsVisible('About Me', 'h3');
...or use a single-argument options object:
options.contents – the text contents to search for
[options.cssSelector] – an optional css selector to further limit the search
[options.timeout=10000] – the timeout of the wait in ms
Example:
await waitForElementWithContentsVisible({
contents: 'About Me',
timeout: 7000,
});
waitForLocation(location) – wait for a location to load
Note: location waiting happens automatically after visit(...). There is no need to call this function right after calling visit(...).
Arguments:
location – either full url or just path. If location is a path, defaultHost and dontUseHTTPS are used to determine the host and protocol for the url. The query part of the path is not included in the match. If you want to check the query, use getQuery() (see above)
waitForLocations(locations) – wait for any location in a list to load
Note: location waiting happens automatically after visit(...). There is no need to call this function right after calling visit(...).
Arguments:
locations – either an array of or a single url/path to wait for. If a location is a path, defaultHost and dontUseHTTPS are used to determine the host and protocol for the url. The query part of the path is not included in the match. If you want to check the query, use getQuery() (see above)
Custom Functions
To create your own functions, add a file test/selenium/commands.js and export your custom commands:
module.exports = {
async visitGoogle() {
await this.visit('https://www.google.com');
},
async searchYoutube(query) {
await this.visit(`https://www.youtube.com/results?search_query=${query}`);
},
};
The context of the function is the driver. Thus, this.visit calls driver.visit. To directly access the Selenium webdriver, use this.webdriver.
Examples
Visit google and type into the search box
require('dce-selenium');
const assert = require('assert');
describeS('Google', function () {
itS('Displays Search Results', async function (driver) {
await driver.visit('https://www.google.com');
await driver.typeInto('.gLFyf', 'Puppy');
await driver.clickByContents('Google Search', 'input');
await driver.waitForElementVisible('#resultStats');
const wikiExists = await driver.elementWithContentsExists('Puppy - Wikipedia');
assert(wikiExists, 'Could not find expected result: Wikipedia');
});
});