nightwatch
Version:
Easy to use Node.js based end-to-end testing solution for web applications using the W3C WebDriver API.
181 lines (149 loc) • 4.71 kB
JavaScript
const Utils = require('../utils');
const Section = require('./section.js');
const Element = require('../element');
class BaseObject {
static get WrappedProtocolCommands() {
return [
'elements',
'elementIdElement',
'elementIdElements'
];
}
/**
* Returns the properties object passed as an argument (or null if no arguments are passed).
* If the supplied properties argument is a function, it invokes that function with the page as its context.
*
* @param {Object} parent
* @param {Object|Function} val
*/
static createProps(parent, val = {}) {
return Utils.isFunction(val) ? val.call(parent) : val;
}
/**
* Assigns the `elements` property for a page or section object.
* For each object in the passed array, it creates a new element object by instantiating Element with its options
*
* @param {Object} parent
* @param {Object|Array} elements Object or array of objects to become element objects
*/
static createElements(parent, elements = []) {
let elementObjects = {};
if (!Array.isArray(elements)) {
elements = [elements];
}
elements.forEach(els => {
Object.keys(els).forEach(name => {
let definition = Utils.isString(els[name]) ? {
selector: els[name]
} : els[name];
let options = {
name,
parent
};
elementObjects[name] = new Element(definition, options);
});
});
return elementObjects;
}
/**
* Assigns the `section` property for a page or section object.
* For each object in the passed array, it creates a new section object by instantiating Section with its options
*
* @param {Object} parent
* @param {object} sections
*/
static createSections(parent, sections = {}) {
let sectionObjects = {};
Object.keys(sections).forEach(name => {
let definition = sections[name];
let options = {
name,
parent
};
sectionObjects[name] = new Section(definition, options);
});
return sectionObjects;
}
/**
* Mixes in the passed functions to the page or section object.
*
* @param {Page|Section} parent The page object or section instance
* @param {Object} commands Array of commands that will be added to the page or section
*/
static addCommands(parent, commands) {
if (Utils.isFunction(commands) || Utils.isObject(commands) && !Array.isArray(commands)) {
commands = [commands];
}
commands.forEach(m => {
if (Utils.isFunction(m)) {
BaseObject.addCommandsFromClass(parent, m);
} else {
Object.keys(m).forEach(k => {
try {
parent[k] = m[k];
} catch (err) {
const error = new Error(`Trying to overwrite page object/section "${parent.name}" method/property "${k}".`);
error.detailedErr = `Using ${Object.keys(m).join(', ')}.`;
throw error;
}
});
}
});
}
static addCommandsFromClass(parent, CommandClass) {
const instance = BaseObject.createPageCommandInstance(CommandClass, parent);
const methodNames = Utils.getAllClassMethodNames(instance, ['httpRequest']);
methodNames.forEach(method => {
try {
parent[method] = function(...args) {
return instance[method].apply(instance, args);
};
} catch (err) {
const error = new Error(`Trying to overwrite page object/section "${parent.name}" method/property "${method}".`);
error.detailedErr = `Using ${methodNames}.`;
error.displayed = false;
throw error;
}
});
}
static createPageCommandInstance(CommandClass, page) {
const {client} = page;
class CommandInstance extends CommandClass {
get page() {
return page;
}
get section() {
return this.page.section;
}
get api() {
return this.client.api;
}
get browser() {
return this.client.api;
}
get client() {
return client;
}
get transportActions() {
if (this.client && this.client.transport) {
return this.client && this.client.transportActions;
}
return {};
}
get driver() {
if (this.client && this.client.transport && this.client.transport.driver) {
return this.client.transport.driver;
}
return null;
}
httpRequest(requestOptions) {
return this.client.transport.runProtocolAction(requestOptions);
}
toString() {
return CommandClass.toString();
}
}
return new CommandInstance();
}
}
module.exports = BaseObject;