Skip to content

Commit

Permalink
Make API more fluent and flexible
Browse files Browse the repository at this point in the history
Query objects now only throw exceptions when trying to perform an action it cannot perform, this gives you more flexibility when constructing objects
Default locator is now optional (useful for Appium where you don't really have a default in some cases)
  • Loading branch information
Ardesco committed Oct 31, 2018
1 parent fa90e97 commit 1e97217
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 52 deletions.
84 changes: 53 additions & 31 deletions src/main/java/com/lazerycode/selenium/util/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,58 +13,70 @@
public class Query {

private RemoteWebDriver driver;
private String currentBrowserName;
private boolean isAppium;
private String currentType;
private By defaultLocator;
private HashMap<String, By> customLocators = new HashMap<>();
private boolean isAppiumDriver;

/**
* Set a static driver object that wil be used for all instances of Query
* Specify a default locator that will be used if a more specific locator cannot be detected.
*
* @param driverObject
* @param locator
* @return this
*/
public Query initQueryObject(RemoteWebDriver driverObject) {
driver = driverObject;
if (null != driver) {
currentBrowserName = driver.getCapabilities().getBrowserName();
Object automationName = driver.getCapabilities().getCapability("automationName");
isAppium = (null != automationName) && automationName.toString().toLowerCase().equals("appium");
}
public Query defaultLocator(By locator) {
this.defaultLocator = locator;

return this;
}

private final By defaultLocator;
private HashMap<String, By> customLocators = new HashMap<>();

public Query(By defaultLocator, RemoteWebDriver driver) {
if (null == defaultLocator) throw new NullPointerException("Query locator cannot be null!");
this.defaultLocator = defaultLocator;
initQueryObject(driver);
}

public Query(By defaultLocator) {
if (null == defaultLocator) throw new NullPointerException("Query locator cannot be null!");
this.defaultLocator = defaultLocator;
}

/**
* Specify a alternate locator for a specific browser.
* <p>
* Any actions that use a By object will examine the `browserName` capability of the current driver,
* if it matches what you have specified here this locator will be used instead.
* <p>
* It is Suggested you pass in a org.openqa.selenium.remote.BrowserType field to ensure accuracy, example:
* It is Suggested you pass in a org.openqa.selenium.remote.BrowserType object to ensure accuracy
* (or if you are using Appium a io.appium.java_client.remote.MobileBrowserType, or io.appium.java_client.remoteMobilePlatform),
* examples:
* <p>
* Query query = newQuery(By.id("foo");
* query.addAlternateLocator(BrowserType.GOOGLECHROME, By.id("bar");
* query.addAlternateLocator(MobileBrowserType.BROWSER, By.id("oof");
* query.addAlternateLocator(MobilePlatform.ANDROID, By.id("rab");
* <p>
* This is intentionally a String for future compatibility.
*
* @param browser String value matching a browsername capability
* @param browser String value matching a BrowserType, MobileBrowserType, or MobilePlatform capability
* @param locator A By object used for locating webElements
*/

public void addAlternateLocator(String browser, By locator) {
public Query addAlternateLocator(String browser, By locator) {
customLocators.put(browser, locator);

return this;
}

/**
* Specify the driver object that will be used to find elements
*
* @param driverObject
* @return this
*/
public Query usingDriver(RemoteWebDriver driverObject) {
if (null != driverObject) {
driver = driverObject;
Object automationName = driver.getCapabilities().getCapability("automationName");
isAppiumDriver = (null != automationName) && automationName.toString().toLowerCase().equals("appium");
currentType = driver.getCapabilities().getBrowserName();
if (isAppiumDriver && (null == currentType || currentType.isEmpty())) {
currentType = driver.getCapabilities().getPlatform().toString();
}
} else {
throw new NullPointerException("Driver object is null!");
}

return this;
}

/**
Expand All @@ -82,7 +94,7 @@ public WebElement findWebElement() {
* @return MobileElement
*/
public MobileElement findMobileElement() {
if (isAppium) {
if (isAppiumDriver) {
return (MobileElement) driver.findElement(locator());
}
throw new UnsupportedOperationException("You don't seem to be using Appium!");
Expand All @@ -103,7 +115,7 @@ public List<WebElement> findWebElements() {
* @return List&lt;MobileElement>&gt;
*/
public List<MobileElement> findMobileElements() {
if (isAppium) {
if (isAppiumDriver) {
List<WebElement> elementsFound = driver.findElements(locator());
List<MobileElement> mobileElementsToReturn = new ArrayList<>();
for (WebElement element : elementsFound) {
Expand Down Expand Up @@ -131,7 +143,17 @@ public Select findSelectElement() {
*/
public By locator() {
checkDriverIsSet();
return customLocators.getOrDefault(currentBrowserName, defaultLocator);
By locatorToReturn = customLocators.getOrDefault(currentType, defaultLocator);

return checkLocatorIsNotNull(locatorToReturn);
}

private By checkLocatorIsNotNull(By locator) {
if (null == locator) {
throw new IllegalStateException(String.format("Unable to detect valid locator for '%s' and a default locator has not been set!", currentType));
}

return locator;
}

private void checkDriverIsSet() {
Expand Down
83 changes: 62 additions & 21 deletions src/test/java/com/lazerycode/selenium/util/QueryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobilePlatform;
import org.junit.After;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Capabilities;
Expand Down Expand Up @@ -31,39 +30,39 @@ public class QueryTest {
private static final List<WebElement> MOCKED_MOBILE_ELEMENT_LIST_FOR_DEFAULT = Collections.singletonList(MOCKED_MOBILE_ELEMENT_FOR_DEFAULT);

@Test(expected = NullPointerException.class)
public void thowsErrorIfInstantiatedWithNull() {
new Query(null);
public void throwsErrorIfDriverIsNull() {
new Query().usingDriver(null);
}

@Test(expected = IllegalStateException.class)
public void throwsIllegalStateExceptionWhenCallingLocatorWithNoInit() {
Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
query.locator();
}

@Test(expected = IllegalStateException.class)
public void throwsIllegalStateExceptionWhenCallingFindWebElementWithNoInit() {
Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
query.findWebElement();
}

@Test(expected = IllegalStateException.class)
public void throwsIllegalStateExceptionWhenCallingFindWebElementsWithNoInit() {
Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
query.findWebElements();
}

@Test(expected = IllegalStateException.class)
public void throwsIllegalStateExceptionWhenCallingFindSelectElementWithNoInit() {
Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
query.findSelectElement();
}

@Test
public void returnsAValidSelectElement() {
when(MOCKED_WEB_ELEMENT_FOR_DEFAULT.getTagName()).thenReturn("select");

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObject(query);
Select element = query.findSelectElement();

Expand All @@ -73,7 +72,7 @@ public void returnsAValidSelectElement() {
@Test
public void returnsDefaultLocator() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObject(query);

assertThat(query.locator()).isEqualTo(DEFAULT_LOCATOR);
Expand All @@ -82,7 +81,7 @@ public void returnsDefaultLocator() {
@Test
public void returnsChromeLocatorIfSet() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObject(query);
query.addAlternateLocator(BrowserType.GOOGLECHROME, CHROME_LOCATOR);

Expand All @@ -92,7 +91,7 @@ public void returnsChromeLocatorIfSet() {
@Test
public void returnsDefaultLocatorIfDifferentBrowserIsSet() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObject(query);
query.addAlternateLocator(BrowserType.FIREFOX, FIREFOX_LOCATOR);

Expand All @@ -102,7 +101,7 @@ public void returnsDefaultLocatorIfDifferentBrowserIsSet() {
@Test
public void returnsWebElement() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObject(query);
WebElement element = query.findWebElement();

Expand All @@ -112,7 +111,7 @@ public void returnsWebElement() {
@Test
public void returnsWebElementList() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObject(query);
List<WebElement> element = query.findWebElements();

Expand All @@ -122,7 +121,7 @@ public void returnsWebElementList() {
@Test
public void returnsMobileElement() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObjectWithAppiumAndroid(query);
MobileElement element = query.findMobileElement();

Expand All @@ -132,7 +131,7 @@ public void returnsMobileElement() {
@Test
public void returnsMobileElementList() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObjectWithAppiumAndroid(query);
List<MobileElement> element = query.findMobileElements();

Expand All @@ -142,23 +141,23 @@ public void returnsMobileElementList() {
@Test(expected = UnsupportedOperationException.class)
public void findMobileElementThrowsUnsupportedOperationExceptionIfPlatformIsNotAMobileType() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObject(query);
query.findMobileElement();
}

@Test(expected = UnsupportedOperationException.class)
public void findMobileElementThrowsUnsupportedOperationExceptionIfPlatformIsAGenericName() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryObject(query);
query.findMobileElement();
}

@Test(expected = UnsupportedOperationException.class)
public void findMobileElementsThrowsUnsupportedOperationExceptionIfPlatformIsNotAMobileType() {

Query query = new Query(DEFAULT_LOCATOR);
Query query = new Query().defaultLocator(DEFAULT_LOCATOR);
initQueryWithGenericAutomationNameObject(query);
query.findMobileElements();
}
Expand All @@ -173,7 +172,7 @@ private void initQueryObject(Query queryObject) {
when(mockedWebDriver.findElement(DEFAULT_LOCATOR)).thenReturn(MOCKED_WEB_ELEMENT_FOR_DEFAULT);
when(mockedWebDriver.findElements(DEFAULT_LOCATOR)).thenReturn(MOCKED_WEB_ELEMENT_LIST_FOR_DEFAULT);

queryObject.initQueryObject(mockedWebDriver);
queryObject.usingDriver(mockedWebDriver);
}

private void initQueryObjectWithAppiumAndroid(Query queryObject) {
Expand All @@ -187,7 +186,7 @@ private void initQueryObjectWithAppiumAndroid(Query queryObject) {
when(mockedWebDriver.findElement(DEFAULT_LOCATOR)).thenReturn(MOCKED_MOBILE_ELEMENT_FOR_DEFAULT);
when(mockedWebDriver.findElements(DEFAULT_LOCATOR)).thenReturn(MOCKED_MOBILE_ELEMENT_LIST_FOR_DEFAULT);

queryObject.initQueryObject(mockedWebDriver);
queryObject.usingDriver(mockedWebDriver);
}

private void initQueryWithGenericAutomationNameObject(Query queryObject) {
Expand All @@ -201,6 +200,48 @@ private void initQueryWithGenericAutomationNameObject(Query queryObject) {
when(mockedWebDriver.findElement(DEFAULT_LOCATOR)).thenReturn(MOCKED_WEB_ELEMENT_FOR_DEFAULT);
when(mockedWebDriver.findElements(DEFAULT_LOCATOR)).thenReturn(MOCKED_WEB_ELEMENT_LIST_FOR_DEFAULT);

queryObject.initQueryObject(mockedWebDriver);
queryObject.usingDriver(mockedWebDriver);
}

@Test(expected = IllegalStateException.class)
public void throwsIllegalStateExceptionIfDefaultLocatorIsNull() {
Capabilities mockedCapabilities = mock(Capabilities.class);
when(mockedCapabilities.getBrowserName()).thenReturn(BrowserType.GOOGLECHROME);
when(mockedCapabilities.getPlatform()).thenReturn(Platform.YOSEMITE);
when(mockedCapabilities.getCapability("automationName")).thenReturn("Generic");

RemoteWebDriver mockedWebDriver = mock(RemoteWebDriver.class);
when(mockedWebDriver.getCapabilities()).thenReturn(mockedCapabilities);

Query query = new Query().usingDriver(mockedWebDriver);
query.locator();
}

@Test(expected = IllegalStateException.class)
public void throwsIllegalStateExceptionIfDefaultLocatorIsNullAndCurrentTypeDoesNotMatch() {
Capabilities mockedCapabilities = mock(Capabilities.class);
when(mockedCapabilities.getBrowserName()).thenReturn(BrowserType.GOOGLECHROME);
when(mockedCapabilities.getPlatform()).thenReturn(Platform.YOSEMITE);
when(mockedCapabilities.getCapability("automationName")).thenReturn("Generic");

RemoteWebDriver mockedWebDriver = mock(RemoteWebDriver.class);
when(mockedWebDriver.getCapabilities()).thenReturn(mockedCapabilities);

Query query = new Query().addAlternateLocator(BrowserType.FIREFOX, FIREFOX_LOCATOR).usingDriver(mockedWebDriver);
query.locator();
}

@Test
public void doesNotThrowIllegalStateExceptionIfDefaultLocatorIsNullAndCurrentTypeDoesMatch() {
Capabilities mockedCapabilities = mock(Capabilities.class);
when(mockedCapabilities.getBrowserName()).thenReturn(BrowserType.GOOGLECHROME);
when(mockedCapabilities.getPlatform()).thenReturn(Platform.YOSEMITE);
when(mockedCapabilities.getCapability("automationName")).thenReturn("Generic");

RemoteWebDriver mockedWebDriver = mock(RemoteWebDriver.class);
when(mockedWebDriver.getCapabilities()).thenReturn(mockedCapabilities);

Query query = new Query().addAlternateLocator(BrowserType.GOOGLECHROME, CHROME_LOCATOR).usingDriver(mockedWebDriver);
query.locator();
}
}

0 comments on commit 1e97217

Please sign in to comment.