Skip to content

Commit

Permalink
Added ability to use element objects from other automation libraries …
Browse files Browse the repository at this point in the history
…in nightwatch tests
  • Loading branch information
beatfactor committed Oct 18, 2020
1 parent 5cfc278 commit 165023a
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 38 deletions.
11 changes: 11 additions & 0 deletions lib/api/_loaders/assertion.js
Expand Up @@ -53,6 +53,9 @@ class AssertionLoader extends BaseCommandLoader {
return function queuedCommandFn({negate, args}) {
const stackTrace = AssertionLoader.getOriginalStackTrace(queuedCommandFn);

const shouldReturnPromise = args[0] && args[0].sessionId && args[0].elementId;
const deferred = Utils.createPromise();

commandQueue.add({
commandName,
commandFn,
Expand All @@ -65,6 +68,14 @@ class AssertionLoader extends BaseCommandLoader {
namespace
});

if (shouldReturnPromise) {
commandQueue.tree.once('asynctree:finished', (err) => {
deferred.resolve();
});

return deferred.promise;
}

return this.api;
}.bind(this);
}
Expand Down
4 changes: 3 additions & 1 deletion lib/api/assertions/_assertionInstance.js
Expand Up @@ -9,7 +9,9 @@ class AssertionInstance {
if (Utils.isFunction(args[args.length-1])) {
this.__doneCallback = args.pop();
} else {
this.__doneCallback = function() {};
this.__doneCallback = function(result) {
return Promise.resolve(result);
};
}

this.__nightwatchInstance = nightwatchInstance;
Expand Down
2 changes: 1 addition & 1 deletion lib/api/element-commands/isVisible.js
Expand Up @@ -60,7 +60,7 @@ class IsVisible extends BaseElementCommand {
browserVersion = parseInt(browserVersion, 10);

// Are we running 12 or newer?
if (browserName.toLowerCase() === 'safari' && (browserVersion >= 12) && this.settings.webdriver.start_process === true) {
if (!isNaN(browserVersion) && browserName.toLowerCase() === 'safari' && (browserVersion >= 12) && this.settings.webdriver.start_process === true) {
return this.executeProtocolAction('getElementProperty', ['hidden']).then(result => ({
value: result.value === false
}));
Expand Down
30 changes: 16 additions & 14 deletions lib/core/session.js
@@ -1,20 +1,13 @@
const EventEmitter = require('events');
const lodashMerge = require('lodash.merge');
const CommandQueue = require('./queue.js');
const {BrowserName, Logger} = require('../utils');
const {BrowserName, Logger, isObject} = require('../utils');

class Session extends EventEmitter {
static get DEFAULT_CAPABILITIES() {
return {
browserName: BrowserName.FIREFOX,
platform: 'ANY'
};
}

constructor(nightwatchInstance) {
super();

this.settings = nightwatchInstance.settings;
this.nightwatchInstance = nightwatchInstance;
this.sessionId = 0;

this.__protocol = nightwatchInstance.transport;
Expand All @@ -23,6 +16,10 @@ class Session extends EventEmitter {
this.createCommandQueue();
}

get settings() {
return this.nightwatchInstance.settings;
}

get commandQueue() {
return this.__commandQueue;
}
Expand Down Expand Up @@ -108,6 +105,7 @@ class Session extends EventEmitter {

useW3CWebdriverProtocol() {
const {browserName} = this.desiredCapabilities;

if (browserName === BrowserName.CHROME) {
const {chromeOptions = {}} = this.desiredCapabilities;

Expand All @@ -118,31 +116,35 @@ class Session extends EventEmitter {
}

setCapabilities() {
this.desiredCapabilities = Object.assign({}, Session.DEFAULT_CAPABILITIES);
Object.assign(this.desiredCapabilities, this.settings.desiredCapabilities);
this.desiredCapabilities = Object.assign({}, this.settings.desiredCapabilities);

if (this.useW3CWebdriverProtocol()) {
this.settings.capabilities = this.settings.capabilities || {};
lodashMerge(this.settings.capabilities, this.desiredCapabilities);
}

const {argv} = this.nightwatchInstance;
this.setHeadlessMode(argv);
}

/**
*
* @return {Promise}
*/
create(argv = {}) {
create(argv = null) {
const startTime = new Date();
const {host, port} = this.settings.webdriver;
const {colors} = Logger;

if (isObject(argv)) {
this.setHeadlessMode(argv);
}

if (this.settings.start_session && this.outputEnabled) {
const ora = require('ora');
this.connectSpinner = ora(colors.cyan(`Connecting to ${host} on port ${port}...\n`)).start();
}

this.setHeadlessMode(argv);

return new Promise((resolve, reject) => {
this.transport.once('transport:session.error', (err) => {
if (this.connectSpinner && this.outputEnabled) {
Expand Down
27 changes: 25 additions & 2 deletions lib/element/command.js
Expand Up @@ -199,6 +199,20 @@ class ElementCommand extends EventEmitter {
};
}

if (this.element.webElement) {
const session = await this.element.webElement.getDriver().getSession();
const elementId = await this.element.webElement.getId();

this.WebdriverElementId = elementId;
this.sessionId = session.getId();

return {
value: elementId,
status: 0,
result: {}
};
}

return await this.elementLocator.findElement({element, commandName});
} catch (err) {
if (err.name === 'ReferenceError' || err.name === 'TypeError') {
Expand All @@ -210,7 +224,9 @@ class ElementCommand extends EventEmitter {
}

executeProtocolAction(actionName, args = []) {
return this.transport.executeProtocolAction(actionName, [this.elementId, ...args]);
const {sessionId, elementId} = this;

return this.transport.executeProtocolAction({actionName, args: [elementId, ...args], sessionId});
}

async complete(err, response) {
Expand Down Expand Up @@ -274,7 +290,7 @@ class ElementCommand extends EventEmitter {
setOptionsFromSelector() {
if (Utils.isObject(this.selector)) {
const {
abortOnFailure, retryInterval, message, timeout, locateStrategy, suppressNotFoundErrors, retryAction, WebdriverElementId
abortOnFailure, retryInterval, message, timeout, locateStrategy, suppressNotFoundErrors, retryAction
} = this.selector;

if (!Utils.isUndefined(abortOnFailure)) {
Expand Down Expand Up @@ -305,8 +321,15 @@ class ElementCommand extends EventEmitter {
this.__retryOnFailure = retryAction;
}

let {WebdriverElementId, elementId, sessionId} = this.selector;
if (WebdriverElementId) {
this.WebdriverElementId = WebdriverElementId;
} else if (elementId && sessionId) {
this.WebdriverElementId = elementId;
this.sessionId = sessionId;
} else if (typeof this.selector.getId == 'function' && typeof this.selector.getDriver == 'function') {
this.elementIdPromise = this.selector.getId;
this.sessionPromise = this.selector.getDriver;
}
}

Expand Down
8 changes: 7 additions & 1 deletion lib/element/index.js
Expand Up @@ -63,7 +63,9 @@ class Element {
}

setProperties(definition, options) {
if (!definition.selector) {
if (definition.driver_ && definition.id_) {
this.webElement = definition;
} else if (!definition.selector) {
throw new Error(`No selector property for ${getDescription(this)}. Instead found properties: ` +
Object
.keys(definition)
Expand Down Expand Up @@ -96,6 +98,10 @@ class Element {
if (!Utils.isUndefined(definition.timeout)) {
this.timeout = definition.timeout;
}

if (definition.sessionId) {
this.sessionId = definition.sessionId;
}
}

toString() {
Expand Down
6 changes: 5 additions & 1 deletion lib/testsuite/hooks/_basehook.js
Expand Up @@ -33,6 +33,10 @@ class BaseHook {
return this.addtOpts.isGlobal || false;
}

get isUnitTest() {
return false;
}

/**
*
* @param {Object} client The nightwatch main instance
Expand Down Expand Up @@ -125,7 +129,7 @@ class BaseHook {
}

resolve();
}, this.key, this.addtOpts.asyncHookTimeout);
}, ((this.isGlobal && !this.isUnitTest) ? 'global ' : '') + this.key, this.addtOpts.asyncHookTimeout);

timedCallback.onTimeoutExpired = timeoutExpired;

Expand Down
6 changes: 5 additions & 1 deletion lib/testsuite/interfaces/describe.js
Expand Up @@ -67,7 +67,7 @@ class DescribeInstance {
}

get desiredCapabilities() {
return this['[attributes]']['@desiredCapabilities'];
return this.client.options.desiredCapabilities;
}
/////////////////////////////////////////////////
// Getters
Expand All @@ -88,6 +88,10 @@ class DescribeInstance {
return this['[instance]'].settings;
}

get argv() {
return this['[instance]'].argv;
}

timeout(value) {
this.globals.waitForConditionTimeout = value;
this.globals.retryAssertionTimeout = value;
Expand Down
6 changes: 5 additions & 1 deletion lib/testsuite/testcase.js
Expand Up @@ -6,6 +6,10 @@ class UnitTest extends BaseHook {
return true;
}

get isUnitTest() {
return true;
}

verifyMethod() {
return this.context.getKey(this.key) || null;
}
Expand All @@ -25,7 +29,7 @@ class TestCase {
}

print() {
if (this.settings.output && this.settings.start_session && this.settings.detailed_output && !this.context.unitTestsMode) {
if (this.settings.output && this.settings.detailed_output && !this.context.unitTestsMode) {
if (this.retriesCount > 0) {
console.log('Retrying (' + this.retriesCount + '/' + this.maxRetries + '): ', Logger.colors.red(this.testName));
} else {
Expand Down
10 changes: 10 additions & 0 deletions lib/transport/transport.js
Expand Up @@ -237,6 +237,16 @@ class Transport extends EventEmitter {
* @return {Promise}
*/
executeProtocolAction(protocolAction, args) {
if (Utils.isObject(protocolAction) && protocolAction.actionName) {
const {actionName, args, sessionId = this.api.sessionId} = protocolAction;

return this.Actions.session[actionName]({
args,
sessionId,
sessionRequired: true
});
}

return this.Actions.session[protocolAction]({
args,
sessionId: this.api.sessionId,
Expand Down
4 changes: 2 additions & 2 deletions test/lib/nightwatch.js
Expand Up @@ -44,7 +44,7 @@ module.exports = new function () {
};
}

this.createClient = function(options = {}, reporter = null) {
this.createClient = function(options = {}, reporter = null, argv = {}) {
let opts = {
selenium : {
port: 10195,
Expand All @@ -66,7 +66,7 @@ module.exports = new function () {

let settings = Settings.parse(opts);

return Nightwatch.client(settings, reporter);
return Nightwatch.client(settings, reporter, argv);
};

this.createClientDefaults = function() {
Expand Down
11 changes: 4 additions & 7 deletions test/src/core/testRequestWithCredentials.js
Expand Up @@ -77,14 +77,13 @@ describe('test Request With Credentials', function () {
headless: true
});

assert.deepStrictEqual(client.settings.desiredCapabilities, {
assert.deepStrictEqual(client.session.desiredCapabilities, {
alwaysMatch: {
'moz:firefoxOptions': {
args: ['-headless']
}
},
browserName: 'firefox',
platform: 'ANY'
browserName: 'firefox'
});
});

Expand Down Expand Up @@ -118,8 +117,7 @@ describe('test Request With Credentials', function () {
chromeOptions: {
args: ['--headless']
},
browserName: 'chrome',
platform: 'ANY'
browserName: 'chrome'
});
});

Expand Down Expand Up @@ -156,8 +154,7 @@ describe('test Request With Credentials', function () {
chromeOptions: {
args: ['--no-sandbox', '--headless']
},
browserName: 'chrome',
platform: 'ANY'
browserName: 'chrome'
});
});
});
7 changes: 2 additions & 5 deletions test/src/index/testNightwatchIndex.js
Expand Up @@ -40,7 +40,6 @@ describe('test NightwatchIndex', function () {
postdata: JSON.stringify({
desiredCapabilities: {
browserName: 'chrome',
platform: 'ANY'
}
}),

Expand Down Expand Up @@ -88,8 +87,7 @@ describe('test NightwatchIndex', function () {

postdata: {
desiredCapabilities: {
browserName: 'chrome',
platform: 'ANY'
browserName: 'chrome'
}
},

Expand Down Expand Up @@ -182,8 +180,7 @@ describe('test NightwatchIndex', function () {
url: '/wd/hub/session',
postdata: JSON.stringify({
desiredCapabilities: {
browserName: 'safari',
platform: 'ANY'
browserName: 'safari'
}
}),
response: '{"value":{"message":"Could not find device : iPhone 6"}}',
Expand Down
2 changes: 0 additions & 2 deletions test/src/runner/testRunnerSessionCreate.js
Expand Up @@ -40,7 +40,6 @@ describe('testRunnerSessionCreate', function() {
},
desiredCapabilities: {
browserName: 'firefox',
platform: 'ANY',
name: 'Async/Test/Sample'
}
}),
Expand All @@ -62,7 +61,6 @@ describe('testRunnerSessionCreate', function() {
},
desiredCapabilities: {
browserName: 'firefox',
platform: 'ANY',
name: 'test-Name'
}
}),
Expand Down

0 comments on commit 165023a

Please sign in to comment.