Search code examples
javascriptasynchronouswebdriver-io

How to wait after browser.keys() in WebdriverIO async mode?


I'm struggling to do something with async WebdriverIO v7 that in sync mode is quite easy.

Context: I'm using a React masked input component that has a bug (I can't fix that nor change the component), if I type too quickly the keys aren't registered and the cursor goes to the end, so I need to type at a relatively slow speed. When I use await input.setValue('test') the typing is too quick and it only types the first letter and can't type the rest, so I need to type every character separately and wait a little between keystrokes.

Basically I want to do this in async mode:

[...textValue].forEach(char => {
  browser.keys(char);
  browser.pause(100);
});

I tried using waitUntil() but because this is a masked input, if I type 123456, the value in the input will be 123.456.___-_ so I can't directly compare the two strings and wait until they are equal. Also, this seems like a lot of work for something that was so simple, so I'm wondering if there is a better way.

Thanks!

EDIT: I tried comparing the saved input text so far on each browser.key(char) with the actual input.getValue() in the waitUntil() condition an it still doesn't work


Solution

  • Alright I solved the problem. The issue was that the forEach loop can't wait for async operations, so I use a for..of loop now (reference).

    async typeSlowly (input, content) {
        let inputSoFar = '';
    
        for (const char of content) {
            inputSoFar = inputSoFar.concat(char);
    
            await browser.keys(char);
            await browser.waitUntil(
                async () => (await input.getValue()) === inputSoFar,
                {
                    timeout: 500,
                    timeoutMsg: 'expected text to be different after 500ms'
                }
            );
        }
    }
    

    I omitted the masking logic part because that's just a detail, the important bit here is the async waiting inside the loop.