Racing condition when refetching elements #1739

Open
christian-bromann opened this Issue Nov 30, 2016 · 1 comment

Projects

None yet

2 participants

@christian-bromann
Member

The problem

Following scripts creates a racing condition. Probably because the refetch mechanism fetches multiple elements and tries to execute a click command on it.

Environment

  • WebdriverIO version: latest
  • Node.js version: 5.10.3
  • Standalone mode or wdio testrunner: wdio
  • if wdio testrunner, running synchronous or asynchronous tests: sync
  • Additional wdio packages used (if applicable): mocha frameowkr

Link to Selenium/WebdriverIO logs

https://gist.github.com/christian-bromann/f7f1c7d1599f0603e9ca554372dadd0e

Code To Reproduce Issue [ Good To Have ]

describe('MyTickets results', function(){
    it('should click on ticket', function(){
        browser.url('https://test.lttldemo.com?userId=3');
        browser.frame(0);

        const menu = $('.navigation-component a[href="/tickets');
        menu.click();


        const ticket = $('.ticket-list-item-component');
        ticket.waitForExist(5000);
        ticket.click();
    });
});
@christian-bromann christian-bromann added this to the Upcoming milestone Nov 30, 2016
@mzvonar
mzvonar commented Nov 30, 2016

I'm still a bit lost in the source code, but I've found out that elements() fetches again if called without selector:

if (!selector) {
    let newSelector = Object.assign({}, lastPromise.value)
    /**
     * if last result was an element result transform result into an array
     */
    newSelector.value = Array.isArray(newSelector.value)
        ? newSelector.value : newSelector.value !== null
        ? [newSelector.value] : []

    /**
     * Only return new selector if existing otherwise fetch again for selector.
     * This is important in cases you do a waitForExist and use the same element
     * variable again after the element has appeared.
     */
    if (newSelector.value.length === 0) {
        this.lastResult = null
        return elements.call(this, newSelector.selector)
    }

    return newSelector
}

But element never fetches again so if called after waitForExist it returns old NoSuchElement error:

if (!selector) {
    return lastPromise.value
}

If I modify element() function like this it works:

if (!selector) {
    const newSelector = Object.assign({}, lastPromise.value);

    if(!newSelector.value) {
        this.lastResult = null
        return element.call(this, newSelector.selector)
    }

    return newSelector;
}

But I'm not sure if that breaks anything

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment