Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Quality Assurance Intermediate Selenium WebDriver Input Actions Scrolling

Brendan Whiting
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Brendan Whiting
Front End Web Development Techdegree Graduate 84,738 Points

Should we be returning a Promise?

I'm finding that my tests aren't running consistently with the code as is. I refactored to return the Promise from the async methods and it seems to work better. Am I crazy? If something calls an async method that doesn't return anything, and calls await on it, what happens?

Original (pages/scroll.js):

    open() {
        this.driver.get(url);
    }

    async loadContent() {
        var loader = await this.driver.findElement(this.locators.loader);
        await this.driver.executeScript("arguments[0].scrollIntoView();", loader);
        await this.driver.wait(until.elementLocated(By.css('#loader:not(.active)')));
    }

Refactored (pages/scroll.js):

    open() {
        return this.driver.get(url); // now with `return`
    }

    async loadContent() {
        var loader = await this.driver.findElement(this.locators.loader);
        await this.driver.executeScript("arguments[0].scrollIntoView();", loader);
        return this.driver.wait(until.elementLocated(By.css('#loader:not(.active)'))); // now with `return`
    }

Here's the code where these methods get called (test/scroll.js):

        before(async function() {
            driver = await env.builder().build();
            page = new ScrollPage(driver);
            await page.open(); // if page.open() doesn't return anything, what is it awaiting?
        });

        it('adds more boxes', async function() {
            let boxes = await driver.findElements(page.locators.boxes);
            let oldBoxCount = boxes.length;
            await page.loadContent();   // if page.loadContent() doesn't return anything, what is it awaiting?
            boxes = await driver.findElements(page.locators.boxes);
            let newBoxCount = boxes.length;
            assert(newBoxCount > oldBoxCount);
        });

I'm also wondering if the tests are running better now for an unrelated reason, like cacheing.

1 Answer

Steven Parker
Steven Parker
231,275 Points

I'd expect an async function to always return a promise, and if not an explicit one, then one that is resolved (as "undefined") when the function ends.

So I don't see a functional difference between these versions, just that in the original version the final test is awaited inside "loadContent", and in the refactor it is awaited in the caller.

Brendan Whiting
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Brendan Whiting
Front End Web Development Techdegree Graduate 84,738 Points

Okay cool. I did a little experiment. I expected waitForHello2 to behave differently than waitForHello1, but it turns out they resolved at the same time. Which is that implicit resolving with undefined as you were saying after the other 'awaits'.

const sayHello = async () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("hello world")
    }, 2000)
  })
}
const waitForHello1 = async () => {
   const hello1 = await sayHello();
   const hello2 = await sayHello();
   return 1;
}

const waitForHello2 = async () => {
   const hello1 = await sayHello();
   const hello2 = await sayHello();
}

waitForHello1().then(() => console.log("Hello 1 is done"));
waitForHello2().then(() => console.log("Hello 2 is done"));