Skip to content

Commit

Permalink
Added SPI for easy extension of action annotations. Additionally acti…
Browse files Browse the repository at this point in the history
…ons now support By locators. This further reduces complexity of code
  • Loading branch information
tobiasstamann committed Nov 7, 2024
1 parent d400756 commit 8a09139
Show file tree
Hide file tree
Showing 26 changed files with 722 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.toolisticon.pogen4selenium.api;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* Meta-Annotation to allow custom annotations.
*
*/

@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Action {

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Action
public @interface ActionClick {

/**
* The locator type to use. Can be ELEMENT for using a generated element or any kind of locator provided by selenium.
* @return the locator to use.
*/
_By by() default _By.ELEMENT;

/** The locator string to use. */
String value();

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Action
public @interface ActionMoveToAndClick {

/**
* The locator type to use. Can be ELEMENT for using a generated element or any kind of locator provided by selenium.
* @return the locator to use.
*/
_By by() default _By.ELEMENT;

/** The locator string to use. */
String value();

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Action
public @interface ActionWrite {

/**
* The locator type to use. Can be ELEMENT for using a generated element or any kind of locator provided by selenium.
* @return the locator to use.
*/
_By by() default _By.ELEMENT;

/** The locator string to use. */
String value();

}
Original file line number Diff line number Diff line change
Expand Up @@ -87,38 +87,50 @@ protected void waitUntilUrl(String urlRegex) {
wait.until(ExpectedConditions.urlMatches(urlRegex));
}

protected void waitForElementToBeClickable(String xpath) {

protected void waitForElementToBeInteractable(String xpath) {
waitForElementToBeInteractable(By.xpath(xpath));
}

protected WebElement waitForElementToBeInteractable(By by) {
Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(15))
.pollingEvery(Duration.ofMillis(300))
.ignoring(ElementNotInteractableException.class);

wait.until(ExpectedConditions.elementToBeClickable(By.xpath(xpath)));
return wait.until(ExpectedConditions.elementToBeClickable(by));
}

protected void waitForElementToBeClickable(WebElement element) {
protected WebElement waitForElementToBeInteractable(WebElement element) {
if(element == null) {
return null;
}

Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(15))
.pollingEvery(Duration.ofMillis(300))
.ignoring(NullPointerException.class);
.ignoring(ElementNotInteractableException.class);

wait.until(ExpectedConditions.elementToBeClickable(element));
return wait.until(ExpectedConditions.elementToBeClickable(element));
}

protected void waitForElementToBePresent(String xpath) {
waitForElementToBePresent(By.xpath(xpath));
}

protected WebElement waitForElementToBePresent(By by) {
Wait<WebDriver> wait =
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(15))
.pollingEvery(Duration.ofMillis(300))
.ignoring(NoSuchElementException.class);

wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
return wait.until(ExpectedConditions.presenceOfElementLocated(by));

}



protected void waitForElementToBeAbsent(String xpath) {
Wait<WebDriver> wait =
new FluentWait<>(driver)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.toolisticon.pogen4selenium.example.withoutpagefactory;

import java.util.List;

import org.openqa.selenium.WebDriver;

import io.toolisticon.pogen4selenium.api.ActionMoveToAndClick;
import io.toolisticon.pogen4selenium.api.ActionWrite;
import io.toolisticon.pogen4selenium.api._By;
import io.toolisticon.pogen4selenium.api.ExtractData;
import io.toolisticon.pogen4selenium.api.ExtractDataValue;
import io.toolisticon.pogen4selenium.api.ExtractDataValue.Kind;
import io.toolisticon.pogen4selenium.api.PageObject;
import io.toolisticon.pogen4selenium.api.PageObjectElement;
import io.toolisticon.pogen4selenium.api.PageObjectParent;
import io.toolisticon.pogen4selenium.api.Pause;

@PageObject
public interface TestPagePageObject extends PageObjectParent<TestPagePageObject>{

static final String DATA_EXTRACTION_FROM_TABLE_XPATH = "//table//tr[contains(@class,'data')]";


TestPagePageObject writeToInputField(@ActionWrite(by=_By.ID, value="input_field") String value);

@ExtractDataValue(by=_By.ID, value = "input_field", kind=Kind.ATTRIBUTE, name="value")
String readInputFieldValue();

@ActionMoveToAndClick(by=_By.XPATH, value = "//fieldset[@name='counter']/input[@type='button']")
@Pause(value = 500L)
TestPagePageObject clickCounterIncrementButton();

@ExtractData(by = io.toolisticon.pogen4selenium.api._By.XPATH, value = DATA_EXTRACTION_FROM_TABLE_XPATH)
List<TestPageTableEntry> getTableEntries();

@ExtractData(by = io.toolisticon.pogen4selenium.api._By.XPATH, value = DATA_EXTRACTION_FROM_TABLE_XPATH)
TestPageTableEntry getFirstTableEntry();

@ExtractDataValue(by = _By.XPATH, value="//fieldset[@name='counter']/span[@id='counter']")
String getCounter();

// you can always provide your own methods and logic
default String providedGetCounter() {
return getDriver().findElement(org.openqa.selenium.By.xpath("//fieldset[@name='counter']/span[@id='counter']")).getText();
}

// Custom entry point for starting your tests
public static TestPagePageObject init(WebDriver driver) {
driver.get("http://localhost:9090/start");
return new TestPagePageObjectImpl(driver);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.toolisticon.pogen4selenium.example.withoutpagefactory;

import io.toolisticon.pogen4selenium.api._By;
import io.toolisticon.pogen4selenium.api.DataObject;
import io.toolisticon.pogen4selenium.api.ExtractDataValue;
import io.toolisticon.pogen4selenium.api.ExtractDataValue.Kind;

@DataObject
public interface TestPageTableEntry {

@ExtractDataValue(by = _By.XPATH, value = "./td[1]")
String name();

@ExtractDataValue(by = _By.XPATH, value = "./td[2]")
String age();

@ExtractDataValue(by = _By.XPATH, value = "./td[3]/a", kind = Kind.ATTRIBUTE, name = "href")
String link();

@ExtractDataValue(by = _By.XPATH, value = "./td[3]/a", kind = Kind.TEXT)
String linkText();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package io.toolisticon.pogen4selenium.example.withpagefactory;

import java.util.List;

import org.openqa.selenium.WebDriver;

import io.toolisticon.pogen4selenium.api.ActionMoveToAndClick;
import io.toolisticon.pogen4selenium.api.ActionWrite;
import io.toolisticon.pogen4selenium.api._By;
import io.toolisticon.pogen4selenium.api.ExtractData;
import io.toolisticon.pogen4selenium.api.ExtractDataValue;
import io.toolisticon.pogen4selenium.api.ExtractDataValue.Kind;
import io.toolisticon.pogen4selenium.api.PageObject;
import io.toolisticon.pogen4selenium.api.PageObjectElement;
import io.toolisticon.pogen4selenium.api.PageObjectParent;
import io.toolisticon.pogen4selenium.api.Pause;

@PageObject
public interface TestPagePageObject extends PageObjectParent<TestPagePageObject>{

static final String DATA_EXTRACTION_FROM_TABLE_XPATH = "//table//tr[contains(@class,'data')]";

@PageObjectElement(elementVariableName=TestPagePageObject.INPUT_FIELD_ID, by = _By.ID, value="input_field" )
static final String INPUT_FIELD_ID = "inputField";

@PageObjectElement(elementVariableName=TestPagePageObject.COUNTER_INCREMENT_BUTTON_ID, by = _By.XPATH, value="//fieldset[@name='counter']/input[@type='button']" )
static final String COUNTER_INCREMENT_BUTTON_ID = "counterIncrementButton";

@PageObjectElement(elementVariableName=TestPagePageObject.DATA_EXTRACTION_FROM_TABLE_ID, by = _By.XPATH, value=DATA_EXTRACTION_FROM_TABLE_XPATH )
static final String DATA_EXTRACTION_FROM_TABLE_ID= "dataExtractionFromTable";

TestPagePageObject writeToInputField(@ActionWrite(INPUT_FIELD_ID) String value);

@ExtractDataValue(by=_By.ELEMENT, value = INPUT_FIELD_ID, kind=Kind.ATTRIBUTE, name="value")
String readInputFieldValue();

@ActionMoveToAndClick(COUNTER_INCREMENT_BUTTON_ID)
@Pause(value = 500L)
TestPagePageObject clickCounterIncrementButton();

@ExtractData(by = io.toolisticon.pogen4selenium.api._By.ELEMENT, value = DATA_EXTRACTION_FROM_TABLE_ID)
List<TestPageTableEntry> getTableEntries();

@ExtractData(by = io.toolisticon.pogen4selenium.api._By.ELEMENT, value = DATA_EXTRACTION_FROM_TABLE_ID)
TestPageTableEntry getFirstTableEntry();


@ExtractDataValue(by = _By.XPATH, value="//fieldset[@name='counter']/span[@id='counter']")
String getCounter();

// you can always provide your own methods and logic
default String providedGetCounter() {
return getDriver().findElement(org.openqa.selenium.By.xpath("//fieldset[@name='counter']/span[@id='counter']")).getText();
}

// Custom entry point for starting your tests
public static TestPagePageObject init(WebDriver driver) {
driver.get("http://localhost:9090/start");
return new TestPagePageObjectImpl(driver);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.toolisticon.pogen4selenium.example.withpagefactory;

import io.toolisticon.pogen4selenium.api._By;
import io.toolisticon.pogen4selenium.api.DataObject;
import io.toolisticon.pogen4selenium.api.ExtractDataValue;
import io.toolisticon.pogen4selenium.api.ExtractDataValue.Kind;

@DataObject
public interface TestPageTableEntry {

@ExtractDataValue(by = _By.XPATH, value = "./td[1]")
String name();

@ExtractDataValue(by = _By.XPATH, value = "./td[2]")
String age();

@ExtractDataValue(by = _By.XPATH, value = "./td[3]/a", kind = Kind.ATTRIBUTE, name = "href")
String link();

@ExtractDataValue(by = _By.XPATH, value = "./td[3]/a", kind = Kind.TEXT)
String linkText();

}
Loading

0 comments on commit 8a09139

Please sign in to comment.