Webdriverio: Change implementation of get* wdio commands

Created on 23 Apr 2017  ·  3Comments  ·  Source: webdriverio/webdriverio

Hello

In our project we override wdio command getText and add new command getTexts:

getText.js

'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);

getTexts.js

'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.

My proposal

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?

Use cases:

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);
...

What can we do about this problem?

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:

  • When the developer first sees the new method, he opens the documentation for wdio and sees an incorrect description
  • We will not have IDE support for overridden methods

It would be much more convenient and clearer to have a similar functional in the core API.

Discussion

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.

All 3 comments

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.

Was this page helpful?
0 / 5 - 0 ratings