bhreinb
bhreinb

Reputation: 181

Awaiting For Elements To Appear Within TestCafe In The Context Of A Page Object Pattern

I use a page object model to store locators and business functions specific to a certain page of the application under test. You can see a sample page object pattern style here

https://github.com/bhreinb/SYSTAC

All the page objects go through a function called pageLoaded() method which can be found in application under test page object. The pageLoaded is used within the base page. Each page object must implement that method or the framework throws an exception to force the user to implement this. The pageLoaded checks attributes of the page belonging to the application under test (for example the page title, a unique element on the page etc) to verify we are on the target page.

I found this works ok in most cases but when a page navigation occurs with multiple re-directs I have to await for elements to exist and be visible as TestCafe prematurely interacts with the application under test. Here is my code sample

pageLoaded() {
    this.userNameLabel = Selector('[data-automation-id="userName"]').with({ visibilityCheck: true });
    this.passWordLabel = Selector('[data-automation-id="password"]').with({ visibilityCheck: true });
    logger.info('Checking Elements That Contain UserName & PassWord Labels For Existence To Confirm We Are On Tenant\'s Target Page');
    const promises = [
      this.userNameLabel.exists,
      this.passWordLabel.exists,
    ];
    return Promise.all(promises).then((elementsExists) => {
      const userNameVisible = elementsExists.pop();
      const passWordVisible = elementsExists.shift();
      if ((userNameVisible) && (passWordVisible)) {
        return true;
      }
      logger.warn(`PageLoaded Method Failure -> Element Containing UserName Is Visible '[${userNameVisible}]'`);
      logger.warn(`PageLoaded Method Failure -> Element Containing PassWord Is Visible '[${passWordVisible}]'`);
      return false;
    });
  }

this will fail but will pass if I change the promises to be like this

const promises = [
      t.expect(this.userNameLabel.exists).ok({ timeout: 20000 }),
      t.expect(this.passWordLabel.exists).ok({ timeout: 20000 }),
    ];

which is not a pattern I particularly like as I don't want assertions logic to be in the page object pattern plus I want the outcome of the promises to return a true or false if that makes sense. Is their anyway I change the expectation to operate on the method for instance

t.expect(pageLoaded()).ok({ timeout: 20000 })

or any other alternative. In addition how can you specify TestCafe to wait for window.onload event to be fired rather than Domcontentloaded in the case where multiple page redirects happen? Thanks in advance as to any help with the above.

Upvotes: 2

Views: 3199

Answers (1)

Alex Skorkin
Alex Skorkin

Reputation: 4274

As @AlexKamaev mentioned in his comment, you can specify the timeout option in the Selector constructor. It'll allow you to avoid using the timeout value as an assertion argument. In addition, have a look at the setPageLoadTimeout method, which will allow you to wait until the page is fully loaded.

Upvotes: 1

Related Questions