Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fixed #2489 - api commands throwing TypeError when called inside page…
… section custom commands
  • Loading branch information
beatfactor committed Sep 18, 2020
1 parent 237d61f commit 49ccb2c
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 37 deletions.
2 changes: 1 addition & 1 deletion lib/api/protocol/element.js
Expand Up @@ -56,7 +56,7 @@ module.exports = class Session extends ProtocolAction {
if (using instanceof Element) {
return this.findElements({
element: using,
callback: value,
callback: typeof value == 'function' ? value : callback,
commandName
});
}
Expand Down
2 changes: 1 addition & 1 deletion lib/api/protocol/elements.js
Expand Up @@ -55,7 +55,7 @@ module.exports = class Elements extends ProtocolAction {
if (using instanceof Element) {
return this.findElements({
element: using,
callback: value,
callback: typeof value == 'function' ? value : callback,
commandName
});
}
Expand Down
40 changes: 34 additions & 6 deletions lib/page-object/command-wrapper.js
Expand Up @@ -128,6 +128,27 @@ class Command {
return this.parent.section[sectionName];
}

getSelectorFromArgs(args) {
let selectorArg = args[0];

const isSelector = Command.isPossibleElementSelector(selectorArg, this.commandName);
if (isSelector) {
// check if both strategy and selector are specified as args
const {LocateStrategy} = Utils;
const isStrategySpecified = LocateStrategy.isValid(selectorArg);
if (isStrategySpecified && Utils.isString(args[1])) {
selectorArg = {
selector: args[1],
locateStrategy: args[0]
};
}

return selectorArg;
}

return null;
}

/**
* Identifies element references (@-prefixed selectors) within an argument
* list and converts it into an element object with the appropriate
Expand All @@ -136,19 +157,26 @@ class Command {
* @param {Array} args The argument list to check for an element selector.
*/
parseElementSelector(args) {
// When true, indicates that the selector references a selector within a section rather than an elements definition.
const isSectionSelector = this.isChaiAssertion && this.commandName === 'section';
let selector = this.getSelectorFromArgs(args);

if (!selector) {
return;
}

// currently only support first argument for @-elements
let inputElement = Command.isPossibleElementSelector(args[0], this.commandName) && Element.createFromSelector(args[0]);
let inputElement = Element.createFromSelector(selector);

if (inputElement && inputElement.hasElementSelector()) {
const selector = args[0];
if (inputElement.hasElementSelector()) {
const nameSections = inputElement.selector.substring(1).split(':');
const name = nameSections[0];
const pseudoSelector = nameSections[1] || null;

// When true, indicates that the selector references a selector within a section rather than an elements definition.
// eg: .expect.section('@footer').to.be.visible
const isSectionSelector = this.isChaiAssertion && this.commandName === 'section';

const getter = isSectionSelector ? this.getSection : this.getElement;

const strategy = Utils.isObject(selector) && selector.locateStrategy || null;
const elementOrSection = getter.call(this, name, strategy);
elementOrSection.pseudoSelector = pseudoSelector;
Expand All @@ -162,7 +190,7 @@ class Command {
// if we're calling an element on a section using a css/xpath selector,
// then we need to retrieve the element using recursion
const Section = require('./section.js');
if ((this.parent instanceof Section) && Command.isPossibleElementSelector(args[0], this.commandName)) {
if (this.parent instanceof Section) {
args[0] = Element.createFromSelector({
locateStrategy: 'recursion',
selector: [this.parent, inputElement]
Expand Down
12 changes: 12 additions & 0 deletions test/extra/pageobjects/pages/simplePageObj.js
Expand Up @@ -21,6 +21,18 @@ module.exports = {
sections: {
signUp: {
selector: '#signupSection',
commands: {
sectionElements(cb) {
this.api.elements('css selector', '#helpBtn', function(result) {
cb(result);
});
},
sectionElement(cb) {
this.api.element('css selector', '#helpBtn', function(result) {
cb(result);
});
}
},
sections: {
getStarted: {
selector: '#getStarted',
Expand Down
59 changes: 30 additions & 29 deletions test/extra/pageobjects/pages/simplePageObjWithCommandsObject.js
@@ -1,35 +1,36 @@
const commonCommands = {
dropdownSelect() {
return this;
},

dropdownSelectByText() {
return this;
},

scrollToElement() {
return this;
}
};

const testCommands = {
...commonCommands,

testCommand() {
return this;
}
};

const o = {
module.exports = {
url: 'http://localhost.com',
elements: {
loginAsString: '#weblogin',
loginCss: {selector: '#weblogin'},
loginIndexed: {selector: '#weblogin', index: 1},
loginXpath: {selector: '//weblogin', locateStrategy: 'xpath'},
loginId: {selector: 'weblogin', locateStrategy: 'id'}
loginIndexed: {
selector: '#weblogin',
index: 1
},
loginXpath: {
selector: '//weblogin',
locateStrategy: 'xpath'
},
loginId: {
selector: 'weblogin',
locateStrategy: 'id'
}
},
commands: testCommands
};
commands: {
dropdownSelect() {
return this;
},

module.exports = o;
dropdownSelectByText() {
return this;
},

scrollToElement() {
return this;
},

testCommand() {
return this;
}
}
};
26 changes: 26 additions & 0 deletions test/src/element/testPageObjectElementSelectors.js
Expand Up @@ -113,6 +113,32 @@ describe('test page object element selectors', function() {
Nightwatch.start(done);
});

it('page section custom commands', function(done) {
nocks
.elementsFound('#signupSection')
.elementsId('0', '#helpBtn', [{ELEMENT: "4"}])
.elementId('0', '#helpBtn');

const page = Nightwatch.api().page.simplePageObj();
const section = page.section.signUp;

section.sectionElement(function(result) {
assert.strictEqual(result.status, 0);
assert.strictEqual(result.value, '0');
assert.deepStrictEqual(result.result.value, { ELEMENT: '0' });
assert.strictEqual(result.result.WebdriverElementId, '0');
});

section.sectionElements(function(result) {
assert.strictEqual(result.status, 0);
assert.strictEqual(result.value, '4');
assert.deepStrictEqual(result.result.value, [{ELEMENT: "4"}]);
assert.strictEqual(result.result.WebdriverElementId, '4');
});

Nightwatch.start(done);
});

it('page section protocol .elements()', function(done) {
nocks
.elementsFound('#signupSection')
Expand Down

0 comments on commit 49ccb2c

Please sign in to comment.