In our project we override wdio command getText
and add new command getTexts
:
'use strict';
let assert = require('assert');
/**
* @alias browser.getText
* @param {String} selector
* @returns {String}
*/
let _getText = browser.getText;
browser.addCommand('getText', function (selector) {
let result = _getText.apply(browser, arguments);
if (Array.isArray(result)) {
throw new assert.AssertionError({
message: 'Found several elements, expected one',
expected: 'One item on page',
actual: 'Several elements',
});
}
return result;
}, true);
'use strict';
/**
* @alias browser.getTexts
* @param {String} selector
* @returns {String[]}
*/
let _getText = browser.getText;
browser.addCommand('getTexts', function (selector) {
let result = _getText.apply(browser, arguments);
if (!Array.isArray(result)) {
return [result];
}
return result;
});
This helped us avoid such hacks as this one.
I have a proposal to change all of these methods in a similar way:
getText(s)
getValue(s)
getAttribute(s)
getTagName(s)
getCssProperty(ies)
I want to do this because this expedient looks like a hack and very often occurs in our tests. What do you think about this?
When a developer writes a test, most often he wants to get the text of some particular element on the page (by the selector):
...
const header = browser.getText('h1');
assert.equals(header, 'Hello here!');
...
But now we have to do checks like this in each test:
...
const header = browser.getText('h1');
assert(Array.isArray(header), 'We have more than one `h1` header on the page!');
assert.equals(header, 'Hello here!');
...
On the other hand, when we have on the page, for example, a list of elements and want to get the contents of the elements of this list, we expect to get an array of strings:
...
const emails = browser.getText('.address-book');
assert.equals(emails.length, 1);
...
But in this situation the method getText
behaves strangely and unexpectedly. Now we have to do checks like this in each test:
...
let emails = browser.getText('.address-book');
if (!Array.isArray(emails)) { emails = [emails] }
assert.equals(emails.length, 1);
...
Firstly, we can do such checks in each test. But this is a very unsuitable option.
The second option — is to override getText
and other similar commands in all projects where we use tests. But this method has two important drawbacks:
It would be much more convenient and clearer to have a similar functional in the core API.
Honestly it sounds like your issues stem from brittle locator strategies, not webdriverio...
An alternate option to fixing your locator strategies would be to add the commands yourself in the before hook.
An alternate option to fixing your locator strategies would be to add the commands yourself in the before hook.
It's impossible without https://github.com/webdriverio/wdio-sync/pull/71
This will be fixed in v5 where we introduce element scopes and you can only call these commands on single elements.
Most helpful comment
Honestly it sounds like your issues stem from brittle locator strategies, not webdriverio...
An alternate option to fixing your locator strategies would be to add the commands yourself in the before hook.