snikt
snikt

Reputation: 601

How to get webdriver to switch between using css, xpath, tag, link or element id

Currently all my step definitions are only accepting element ids in order to take action on the webpage.

driver.findElement(By.id("id"));

But what if I wanted to pass in a css selector, tag, link or xpath? I don't want to have to re-write all my step definitions for all these scenarios (or create multiple and identical step def), not knowing which one will be passed.

driver.findElement(By.cssSelector("css"));
driver.findElement(By.link("link"));
driver.findElement(By.tagName("tag"));
driver.findElement(By.xpath("xpath"));

Is there a switch statement I can use, that will determine what kind of locator it is being passed, and then go on to perform the action accordingly?

Upvotes: 0

Views: 267

Answers (3)

Pieter A
Pieter A

Reputation: 166

Are you are trying to pass element ID's from the feature files through the step definitions similar to the example that the user 'yong' posted?

If this is the case than I would strongly recommend reconsidering this approach. The whole purpose of using Gherkin as layer on top regular code is to make the tests readable to humans that have no knowledge of the technical implementation.

I would rather use one step definition per input field, so if you need to access that field in multiple tests you don't have to specify the ID or cssSelector every time. If the ID's of the fields in the HTML would change, you don't need to update the feature files, but only the step definition.

If it happens often that you use the same elements in multiple step definitions, take a look at the Page Object Model pattern where you only define elements once per page so you can re-use them in multiple step definitions.

Upvotes: 1

yong
yong

Reputation: 13712

You can create a helper class to return By according to different locator string.

// feature file
Secnario Outline: Test user login
  Given ...
  And user input username: <value> into <element>
  And user input password: <value> into <element>

  Examples:
    | value | element |
    | user1 | id:username |
    | pwd1  | css:input.pwd |

// helper class to build Locator
public class Locator {

  public static By build(locator) {
    String[] parts = locator.split(":");
    String use = parts[0].trim().lowerCase();
    String value = parts[1].trim();

    if(use.equals("id")) {
      return By.id(value);
    }
    else if(use.equals("css")){
      return By.css(value);
    }
    .....
  }
}

// step definition
Then("^user input username: (.+) into (.+)$", 
      (String inputValue, String locatoExp) -> {

    driver.findElement(Locator.build(locatoExp)).sendKeys(inputValue);
});

Upvotes: 1

siegi
siegi

Reputation: 5996

I don't know if I understand you correctly, but each of the static methods in the By class return a By object. So if you want to create a method that works with ID, CSS selector, XPath… you can simply use By as the parameter type.

So instead of passing a ID as String like this…

public void foo(String id) {
    // ...
    driver.findElement(By.id(id));
    // ...
}

… you can do…

public void foo(By by) {
    // ...
    driver.findElement(by);
    // ...
}

… and so a caller of foo can pass any By it likes.

Upvotes: 0

Related Questions