testium-driver-wd
Version:
Testium backend powered by wd
156 lines (137 loc) • 4.62 kB
JavaScript
/*
* Copyright (c) 2015, Groupon, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of GROUPON nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
;
const util = require('util');
const Asserter = require('wd').Asserter;
const Matchers = require('./_matchers');
function propertyAsserter(property, expected) {
const getter = `get${property[0].toUpperCase()}${property.slice(1)}`;
return new Asserter(browser => {
return browser[getter]().then(actual => {
if (!Matchers.string(expected, actual)) {
const err = new Error(
util.format(
'Timed out waiting for %s %s. Last value was: %j',
property,
expected,
actual
)
);
err.retriable = true;
throw err;
}
});
});
}
function urlAsserter(url, query) {
function checkUrl(actualUrl) {
if (!Matchers.url(url, query, actualUrl)) {
const err = new Error(`Url did not match ${actualUrl}`);
err.retriable = true;
throw err;
}
}
function getAndCheckUrl(browser) {
return browser.getUrl().then(checkUrl);
}
return new Asserter(getAndCheckUrl);
}
/**
* Wait for document to be in a certain state
* https://github.com/admc/wd#waiting-for-something
* https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
*
* @param {object} self
* @param {string} state
* @param {number} [timeout] - Timeout for js condition to complete (optional)
*/
function waitForDocumentState(self, state, timeout) {
let expr;
timeout = timeout || 8000;
switch (state) {
case 'interactive':
expr =
"document.readyState === 'interactive' || document.readyState === 'complete'";
break;
case 'complete':
expr = "document.readyState === 'complete'";
break;
default:
throw new Error(
'Document state doesn\'t match "interactive" or "complete"'
);
}
self.setAsyncScriptTimeout(timeout + 250);
return self.waitForConditionInBrowser(expr, timeout);
}
exports.getUrl = function getUrl() {
return this.url();
};
exports.getUrlObj = function getUrl() {
return this.getUrl().then(url => new URL(url));
};
exports.getPath = function getPath() {
return this.getUrlObj().then(
urlObj => `${urlObj.pathname}${urlObj.search}${urlObj.hash}`
);
};
exports.waitForUrl = function waitForUrl(url, query, timeout, pollFreq) {
if (typeof query === 'number') {
timeout = query;
query = {};
}
query = query || {};
return this.waitFor(urlAsserter(url, query), timeout || 5000, pollFreq);
};
exports.waitForPath = function waitForPath(path, timeout, pollFreq) {
return this.waitFor(
propertyAsserter('path', path),
timeout || 5000,
pollFreq
);
};
/**
* Waits until the document ready state has been reached
*
* @param {number} timeout
*/
exports.waitForDocumentReady = function waitForDocumentReady(timeout) {
return waitForDocumentState(this, 'interactive', timeout);
};
/**
* Waits until the document load state has been reached
*
* @param {number} timeout
*/
exports.waitForLoadEvent = function waitForLoadEvent(timeout) {
return waitForDocumentState(this, 'complete', timeout);
};