Reputation: 601
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
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
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
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