3

I'm writing a test to check our ratequote form on https://militaryvaloan.com/va-rates, I've been mostly successful getting it to work however I'm having trouble keeping the event listeners in order. Each step has some transition before the next steps are visible, so I am using driver.wait to make sure I can click or add text etc.

The problem comes when a step has input fields and a next button like 'Address and Zipcode', I've been unable to get the input fields filled out before the button gets clicked, so sometimes it tries clicking the next button before the fields are finished.

I've tried adding driver.sleep around each step to try and solve this but it still wants to click before the fields are done.

If someone could explain how to improve my code that would be greatly appreciated.

var webdriver = require('selenium-webdriver'),
    By = webdriver.By,
    until = webdriver.until;

var driver = new webdriver.Builder()
    .forBrowser('chrome')
    .build();

var _wait_and_input = function(element_type, descriptor, keys, message) {
  let element = element_type(descriptor);
  driver.wait(until.elementLocated(element)).then(() => {
    driver.wait(until.elementIsVisible(driver.findElement(element)), 20000).then((el) => {
      driver.sleep(1000).then(() => {
        if (message) console.log(message);
        el.sendKeys(keys);
      });
    })
  });
}

var _wait_and_click = function(element_type, descriptor, message) {
  let element = element_type(descriptor);
  driver.wait(until.elementLocated(element)).then(() => {
    driver.wait(until.elementIsVisible(driver.findElement(element)), 20000).then((el) => {
      driver.sleep(1000).then(() => {
        if (message) console.log(message);
        el.click();
      });
    })
  });
}

driver.get('https://militaryvaloan.com/va-rates').then(() => {

  _wait_and_click(By.id, 'va-streamline-btn', 'Loan Type');
  _wait_and_click(By.id, 'single-family-btn', 'Property Type');
  _wait_and_click(By.id, 'prime-res-btn', 'Property Use');

  _wait_and_input(By.name, 'state', 'w' + webdriver.Key.ENTER, 'State');
  _wait_and_click(By.id, 'next-state');

  _wait_and_click(By.id, 'next-mortgage-balance', 'Mortgage Balance');
  _wait_and_click(By.id, 'next-home-value', 'Home Value');
  _wait_and_click(By.id, 'next-interest-rate', 'Rate');
  _wait_and_click(By.id, 'credit-excellent', 'Credit');

  _wait_and_input(By.name, 'address', '123 Street SW', 'Address and Zipcode');
  _wait_and_input(By.name, 'zipcode', '98004');
  _wait_and_click(By.id, 'next-address-zip');

  _wait_and_input(By.name, 'firstname', 'Selenium', 'Name and Email');
  _wait_and_input(By.name, 'lastname', 'Selenium');
  _wait_and_input(By.name, 'email', '[email protected]');
  _wait_and_click(By.id, 'next-name-email');

  _wait_and_input(By.name, 'phone', '425-275-1238', 'Phone Number');
  _wait_and_click(By.id, 'next-phone');

  //driver.quit();

});

enter image description here

3
  • If it was me, I would set a breakpoint early in the test and walk it through the following lines. If you are able to complete the test while doing the steps, could be a timing issue. Should post the console after the execution on your question, helps us so we know if it's making it all the way through the test - Also seems like not all of the code is being shown.
    – DEnumber50
    Oct 11, 2018 at 19:16
  • @DEnumber50, the whole code is there it's just overflowed.
    – Andy H
    Oct 12, 2018 at 18:33
  • 1
    Hi what are you trying to achieve here ? Why haven't you tried protractor
    – PDHide
    Dec 7, 2019 at 8:32

2 Answers 2

1

It would be recommended to use await instead of having sleeps:

var _wait_and_input = async function(element_type, descriptor, keys, message) {
          let element = element_type(descriptor);
          driver.wait(until.elementLocated(element)).then(() => {
            driver.wait(until.elementIsVisible(driver.findElement(element)), 20000).then((el) => {
              driver.sleep(1000).then(() => {
                if (message) console.log(message);
                el.sendKeys(keys);
              });
            })
          });
        }

And in code use the function like

await _wait_and_input (parameters)
-1

Found the answer myself, I was only using wait's and no sleeps. I didn't know the selenium test would run asynchronously, which was why it was not staying in order.

My solution was to add a pause number and counter so I could force each step to run after each other:

let STEP_PAUSE = 500;
let STEP_COUNTER = 1;

function _wait_and_input(element_type, descriptor, keys) {
  driver.sleep(STEP_PAUSE * STEP_COUNTER++).then(() => {
    let element = element_type(descriptor);
    driver.findElement(element).then((input) => {
      input.sendKeys(keys);
    })
  })
}

function _wait_and_click(element_type, descriptor, message) {
  driver.sleep(STEP_PAUSE * STEP_COUNTER++).then(() => {
    let element = element_type(descriptor);
    driver.findElement(element).then((button) => {
      if (message) console.log('Pass: ' + message);
      button.click();
    })
  })
}

Ex:
First step runs after 500ms
Second step runs after 1000ms
Third step runs after 1500ms

and so on...

2
  • That sounds like a workaround rather than a solution the designers of the tools might have intended. Not that workarounds are bad though. In any case - Please mark this answer as accepted, so that others know there is an answer here that satisfied the original asker of the question (you). Thanks!
    – Carolus
    Oct 15, 2019 at 10:17
  • This solution sounds really tricky. What if an action takes longer than 500 ms?, or is much faster, now you might wait unnecessary. Try to use async await. Jan 6, 2020 at 12:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.