3

So all I want to do is automate a login through WebdriverIO.

This is the LoginPage class where the error occurs, login function - "element not interactable"

class LoginPage {

  get inputUsername() {
    const username = $("#username");
    username.waitForClickable();
    return username;
  }

  get inputPassword() {
    const password = $("#current-password");
    password.waitForClickable();
    return password;
  }

  get btnSubmit() {
    const submitButton = $(".button.button--primary.button--l");
    submitButton.waitForClickable();
    return submitButton;
  }

  async login(username, password) {
    await this.inputUsername.setValue(username); //<--Throws error
    await this.inputPassword.setValue(password); //<--Throws error
    await this.btnSubmit.click(); //<--Not sure if throws error
  }

}

The parameters from the login function come from the call of it on the test file.

describe("login", () => {
  it("should successfully login", async () => {

    await browser.maximizeWindow();

    await LoginPage.open(); //<--Opens the login page on the browser

    await LoginPage.login(
      "emailtest@test.com",
      process.env.PASSWORD
    );

    await expect(browser).toHaveUrl(process.env.CLIENT_AREA_URL);
  }
}

I believe I'm using mocha for the test structure and for the reporters (spec and allure), correct me if I'm wrong in something.

I'm kinda new in Automated Web Testing, can someone help me on this?

NeonSilver
  • 31
  • 5

3 Answers3

1

Try this:

class LoginPage {

  get inputUsername() { return $("#username"); 
  get inputPassword() {return $("#current-password"); 
  get btnSubmit() {return $(".button.button--primary.button--l");

  async login(username, password) {

    await this.inputUsername.waitForClickable();
    await this.inputUsername.setValue(username); 
    await this.password.waitForClickable();
    await this.inputPassword.setValue(password); 
    await this.submitButton.waitForClickable();
    await this.submitButton.click(); 
  }
}

I would recommend to write even a method to fill the input:

async fillLoginName(loginname){

await this.inputUsername.waitForExist();
await this.inputUsername.clearValue();
await this.inputUsername.setValue(loginname);

}

and you called just in your test as:

it("should successfully login", async () => {

  await Loginpage.fillLoginName("emailtest@test.com");

   // do the rest for password field and click login button

)}
Hichow
  • 21
  • 2
0

There are a couple things that could be causing this:

  • The page has a cookie "modal" window that pops up. This modal can block the text input into the login form, which is what the "element not interactable" message comes from. If this is the case, you'll also likely see an additional message saying another element received a click.
  • The login page loads content via JavaScript API calls. WebdriverIO/Selenium is good about waiting for normal page loads, but when you load content via JavaScript, it doesn't know to wait for that. You do have the username.waitForClickable(); calls, but I think they might need to be await username.waitForClickable();to work.
Kevin Lamping
  • 2,292
  • 16
  • 20
  • I didn't put there, but I do have a function that bypasses the cookies popup being called before the: `await LoginPage.login("emailtest@test.com", process.env.PASSWORD);` Which successfully does its job, I'm going to try putting **await** on **username.waitForClickable();** – NeonSilver Oct 12 '21 at 17:45
  • Can't seem to figure out on how can I put async and await on those get methods, it gives me errors and doesn't even open chrome – NeonSilver Oct 12 '21 at 18:10
0

It looks like waitForClickable doesn't work in this case. Could you move it to the async function?

Based on your code:

get inputUsername() {
  return $("#username");
}

async login(username, password) {
  await this.inputUsername.waitForClickable();
  await this.inputUsername.setValue(username);
  ...
}

wait... and set... can be moved to browser.addCommand() in wdio.conf to have a cleaner code.

denbon
  • 51
  • 4