Skip to content

Commit

Permalink
Added support for pressing key combinations. #192
Browse files Browse the repository at this point in the history
  • Loading branch information
BugDiver committed Oct 12, 2018
1 parent 551c6e9 commit 489425f
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 46 deletions.
2 changes: 1 addition & 1 deletion lib/api.json

Large diffs are not rendered by default.

97 changes: 52 additions & 45 deletions lib/taiko.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ const connect_to_cri = async (target) => {
await inputHandler.setInput(input);
await domHandler.setDOM(dom);
await targetHandler.setTarget(criTarget, xhrEvent, connect_to_cri, currentHost, currentPort);
await pageHandler.setPage(page, xhrEvent, async function() {
await pageHandler.setPage(page, xhrEvent, async function () {
if (!client) return;
rootId = null;
const { root: { nodeId } } = await dom.getDocument();
rootId = nodeId;
});
if(ignoreSSLErrors) security.setIgnoreCertificateErrors({ignore:true});
if (ignoreSSLErrors) security.setIgnoreCertificateErrors({ ignore: true });
resolve();
});
} catch (e) { setTimeout(() => { connect(resolve); }, 1000).unref(); }
Expand All @@ -62,19 +62,19 @@ const connect_to_cri = async (target) => {
* openBrowser()
* openBrowser({ headless: false })
* openBrowser({args:['--window-size=1440,900']})
* openBrowser({args: [
* openBrowser({args: [
* '--disable-gpu',
* '--disable-dev-shm-usage',
* '--disable-setuid-sandbox',
* '--no-first-run',
* '--no-sandbox',
* '--no-zygote']}) - These are recommended args that has to be passed when running in docker
*
* @param {Object} options {headless: true|false, args:['--window-size=1440,900']}
*
* @param {Object} options {headless: true|false, args:['--window-size=1440,900']}
* @param {boolean} [options.headless=true] - Option to let open browser in headless/headful mode.
* @param {Array} [options.args] - Args to open chromium https://peter.sh/experiments/chromium-command-line-switches/.
* @param {number} [options.port=0] - Remote debugging port if not given connects to any open port.
* @param {boolean} [options.ignoreCertificateErrors=false] - Option to ignore certificate errors.
* @param {boolean} [options.ignoreCertificateErrors=false] - Option to ignore certificate errors.
* @returns {Promise<Object>} - Object with the description of the action performed.
*/
module.exports.openBrowser = async (options = { headless: true }) => {
Expand Down Expand Up @@ -127,25 +127,25 @@ const _closeBrowser = async () => {
if (temporaryUserDataDir) {
try {
await removeFolderAsync(temporaryUserDataDir);
} catch (e) {}
} catch (e) { }
}
});
};

/**
* Gives CRI client object.
*
* @returns {Object}
* @returns {Object}
*/
module.exports.client = () => client;

/**
* Allows to switch between tabs using URL or page title.
*
*
* @example
* switchTo('https://taiko.gauge.org/') - switch using URL
* switchTo('Taiko') - switch using Title
*
*
* @param {string} targetUrl - URL/Page title of the tab to switch.
* @returns {Promise<Object>} - Object with the description of the action performed.
*/
Expand All @@ -159,10 +159,10 @@ module.exports.switchTo = async (targetUrl) => {

/**
* Sets page viewport
*
*
* @example
* setViewPort({width:600,height:800})
*
* setViewPort({width:600,height:800})
*
* @param {Object} options - https://chromedevtools.github.io/devtools-protocol/tot/Emulation#method-setDeviceMetricsOverride
* @returns {Promise<Object>} - Object with the description of the action performed.
*/
Expand Down Expand Up @@ -201,7 +201,7 @@ module.exports.openTab = async (targetUrl, options = { timeout: 30000 }) => {
* @example
* closeTab() - Closes the current tab.
* closeTab('https://gauge.org') - Closes the tab with url 'https://gauge.org'.
*
*
* @param {string} targetUrl - URL/Page title of the tab to switch.
* @returns {Promise<Object>} - Object with the description of the action performed.
*/
Expand Down Expand Up @@ -241,7 +241,7 @@ module.exports.goto = async (url, options = { timeout: 30000 }) => {
xhrEvent.addListener('xhrEvent', func);
if (options.headers) await network.setExtraHTTPHeaders({ headers: options.headers });
const res = await page.navigate({ url: url });
if(res.errorText) throw new Error(`Navigation to url ${url} failed.\n REASON: ${res.errorText}`);
if (res.errorText) throw new Error(`Navigation to url ${url} failed.\n REASON: ${res.errorText}`);
await waitForNavigation(options.timeout, promises).catch(handleTimeout(func, options.timeout));
xhrEvent.removeListener('xhrEvent', func);
return { description: `Navigated to url "${url}"`, url: url };
Expand All @@ -253,8 +253,8 @@ module.exports.goto = async (url, options = { timeout: 30000 }) => {
* @example
* reload('https://google.com')
* reload('https://google.com', { timeout: 10000 })
*
* @param {string} url - URL to reload
*
* @param {string} url - URL to reload
* @returns {Promise<Object>} - Object with the description of the action performed and the final URL.
*/
module.exports.reload = async (url) => {
Expand Down Expand Up @@ -571,7 +571,7 @@ const isPasswordField = async () => {
const result = await runtime.evaluate({
expression: 'document.activeElement.type'
});
return (result.result.value === 'password');
return (result.result.value === 'password');
};

const _getActiveElementTagName = async () => {
Expand All @@ -597,7 +597,7 @@ const _getActiveElementDisabled = async () => {

const _isActiveFieldNotWritable = async () => {
return (['INPUT', 'TEXTAREA', 'SELECT'].indexOf((await _getActiveElementTagName())) <= -1 ||
await _getActiveElementIsContentEditable()) &&
await _getActiveElementIsContentEditable()) &&
await _getActiveElementDisabled();
};

Expand All @@ -623,28 +623,28 @@ const _getDocumentUrl = async () => {
};

/**
* Clears the value of given selector. If no selector is given clears the current active element.
*
* Clears the value of given selector. If no selector is given clears the current active element.
*
* @example
* clear()
* clear(inputField({placeholder:'Email'}))
*
*
* @param {selector} selector - A selector to search for element to clear. If there are multiple elements satisfying the selector, the first will be cleared.
* @param {Object} options - Click options.
* @param {boolean} [options.waitForNavigation=true] - Wait for navigation after clear. Default navigation timeout is 15 seconds, to override pass `{ timeout: 10000 }` in `options` parameter.
* @param {number} [options.waitForStart=500] - wait for navigation to start. Default to 500ms
* @param {number} [options.timeout=5000] - Timeout value in milliseconds for navigation after click.
* @returns {Promise<Object>} - Object with the description of the action performed.
*/
module.exports.clear = async (selector,options={}) => {
let nodeId,desc;
module.exports.clear = async (selector, options = {}) => {
let nodeId, desc;
options = setNavigationOptions(options);
if(!selector) {
if (!selector) {
const result = await runtime.evaluate({ expression: 'document.activeElement' });
const res = await dom.requestNode({ objectId: result.result.objectId });
nodeId = res.nodeId;
desc = { description: 'Cleared element on focus'};
}else {
desc = { description: 'Cleared element on focus' };
} else {
nodeId = await element(selector);
desc = { description: 'Cleared ' + description(selector, true) };
}
Expand All @@ -656,7 +656,7 @@ module.exports.clear = async (selector,options={}) => {
};

const _clear = async (elem) => {
await click(elem,{clickCount:3,waitForNavigation:false});
await click(elem, { clickCount: 3, waitForNavigation: false });
await inputHandler.down('Backspace');
await inputHandler.up('Backspace');
};
Expand Down Expand Up @@ -692,13 +692,14 @@ module.exports.attach = async (filepath, to) => {
};

/**
* Presses the given key.
* Presses the given keys.
*
* @example
* press('Enter')
* press('a')
* press(['Shift', 'ArrowLeft', 'ArrowLeft'])
*
* @param {string} key - Name of key to press, such as ArrowLeft. See [USKeyboardLayout](https://github.com/getgauge/taiko/blob/master/lib/USKeyboardLayout.js) for a list of all key names.
* @param {string | Array<string> } keys - Name of keys to press, such as ArrowLeft. See [USKeyboardLayout](https://github.com/getgauge/taiko/blob/master/lib/USKeyboardLayout.js) for a list of all key names.
* @param {Object} options
* @param {string} [options.text] - If specified, generates an input event with this text.
* @param {number} [options.delay=0] - Time to wait between keydown and keyup in milliseconds.
Expand All @@ -707,16 +708,22 @@ module.exports.attach = async (filepath, to) => {
* @param {number} [options.timeout=5000] - Timeout value in milliseconds for navigation after click.
* @returns {Promise<Object>} - Object with the description of the action performed.
*/
module.exports.press = async (key, options = {}) => {
module.exports.press = async (keys, options = {}) => {
validate();
options = setNavigationOptions(options);
return await _press(new Array().concat(keys), options);
};

async function _press(keys, options) {
await doActionAwaitingNavigation(options, async () => {
await inputHandler.down(key, options);
for (let i = 0; i < keys.length; i++) await inputHandler.down(keys[i], options);
if (options && options.delay) await new Promise(f => setTimeout(f, options.delay).unref());
await inputHandler.up(key);
keys = keys.reverse();
for (let i = 0; i < keys.length; i++) await inputHandler.up(keys[i]);
});
return { description: `Pressed the ${key} key` };
};
return { description: `Pressed the ${keys.reverse().join(' + ')} key` };
}


/**
* Highlights the given element on the page by drawing a red rectangle around it. This is useful for debugging purposes.
Expand Down Expand Up @@ -1452,14 +1459,14 @@ module.exports.beforeunload = (message, callback) => dialog('beforeunload', mess

/**
* Add interceptor for the network call to override request or mock response.
*
*
* @example
* case 1: block url => intercept(url)
* case 2: mockResponse => intercept(url,{mockObject})
* case 3: override request => intercept(url,(request) => {request.continue({overrideObject})})
* case 4: redirect => intercept(url,redirectUrl)
* case 5: mockResponse based on request => intercept(url,(request) => { request.respond({mockResponseObject})} )
*
*
* @param requestUrl request URL to intercept
* @param action action to be done after interception
* @returns {object} Object with the description of the action performed.
Expand All @@ -1471,11 +1478,11 @@ module.exports.intercept = async (requestUrl, action) => {

/**
* Evaluates script on element matching the given selector.
*
*
* @example
* evaluate(link("something"), (element) => element.style.backgroundColor)
* evaluate(()=>{return document.title})
*
*
* @param {selector|string} selector - Web element selector.
* @param {function} callback - callback method to execute on the element.
* @param {Object} options - Click options.
Expand All @@ -1486,10 +1493,10 @@ module.exports.intercept = async (requestUrl, action) => {
*/
module.exports.evaluate = async (selector, callback, options = {}) => {
let result;
if(isFunction(selector)){
if (isFunction(selector)) {
callback = selector;
selector = (await $$xpath('//*'))[0];
}
}
const nodeId = isNaN(selector) ? await element(selector) : selector;
if (headful) await highlightElemOnAction(nodeId);

Expand All @@ -1508,7 +1515,7 @@ module.exports.evaluate = async (selector, callback, options = {}) => {
objectId
});
});
return {description:'Evaluated given script. Result: ' + result.result.value, result: result.result.value};
return { description: 'Evaluated given script. Result: ' + result.result.value, result: result.result.value };
};

/**
Expand Down Expand Up @@ -1615,7 +1622,7 @@ const doActionAwaitingNavigation = async (options, action) => {
await waitForPromises(promises, options.waitForStart);
if (options.awaitNavigation) {
//TODO:Handle frame load without loadEventFired
await waitForNavigation(options.timeout, promises).catch(() => {});
await waitForNavigation(options.timeout, promises).catch(() => { });
}
xhrEvent.removeAllListeners();
};
Expand Down Expand Up @@ -1797,7 +1804,7 @@ const waitUntil = async (condition, intervalTime, timeout) => {
while (true) {
try {
if (await condition()) break;
} catch (e) {}
} catch (e) { }
if ((new Date().getTime() - start) > timeout)
throw new Error(`waiting failed: timeout ${timeout}ms exceeded`);
sleep(intervalTime);
Expand Down Expand Up @@ -1837,7 +1844,7 @@ const getMatchingNode = async (elements, args) => {
}
if (valid) matchingNodes.push({ element: element, dist: dist });
}
matchingNodes.sort(function(a, b) {
matchingNodes.sort(function (a, b) {
return a.dist - b.dist;
});
return matchingNodes;
Expand Down

0 comments on commit 489425f

Please sign in to comment.