From 1e5fdce7cbef57e7882d6adedf370b1b13939dfc Mon Sep 17 00:00:00 2001 From: Tobias Stamann Date: Mon, 21 Oct 2024 00:45:07 +0200 Subject: [PATCH 1/4] Update for next development version --- pogen4selenium-api/pom.xml | 2 +- pogen4selenium-example/pom.xml | 4 ++-- pogen4selenium-integrationTest/pom.xml | 2 +- pogen4selenium-processor/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pogen4selenium-api/pom.xml b/pogen4selenium-api/pom.xml index 4876167..be81f79 100644 --- a/pogen4selenium-api/pom.xml +++ b/pogen4selenium-api/pom.xml @@ -9,7 +9,7 @@ io.toolisticon.pogen4selenium pogen4selenium - 0.1.0 + 0.1.1-SNAPSHOT pogen4selenium-api diff --git a/pogen4selenium-example/pom.xml b/pogen4selenium-example/pom.xml index afe9ebf..3148d7b 100644 --- a/pogen4selenium-example/pom.xml +++ b/pogen4selenium-example/pom.xml @@ -9,7 +9,7 @@ io.toolisticon.pogen4selenium pogen4selenium - 0.1.0 + 0.1.1-SNAPSHOT pogen4selenium-example @@ -33,7 +33,7 @@ io.toolisticon.pogen4selenium pogen4selenium-api - 0.1.0 + 0.1.1-SNAPSHOT diff --git a/pogen4selenium-integrationTest/pom.xml b/pogen4selenium-integrationTest/pom.xml index c5b6565..0a7e615 100644 --- a/pogen4selenium-integrationTest/pom.xml +++ b/pogen4selenium-integrationTest/pom.xml @@ -9,7 +9,7 @@ io.toolisticon.pogen4selenium pogen4selenium - 0.1.0 + 0.1.1-SNAPSHOT pogen4selenium-integrationTest diff --git a/pogen4selenium-processor/pom.xml b/pogen4selenium-processor/pom.xml index f956a77..53453a6 100644 --- a/pogen4selenium-processor/pom.xml +++ b/pogen4selenium-processor/pom.xml @@ -9,7 +9,7 @@ io.toolisticon.pogen4selenium pogen4selenium - 0.1.0 + 0.1.1-SNAPSHOT pogen4selenium-processor diff --git a/pom.xml b/pom.xml index f655b98..86c3427 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 io.toolisticon.pogen4selenium pogen4selenium - 0.1.0 + 0.1.1-SNAPSHOT pom pogen4selenium Please refer to https://github.com/toolisticon/pogen4selenium From 564868db04031a57d320e86cc849082ef337e40c Mon Sep 17 00:00:00 2001 From: Tobias Stamann Date: Mon, 21 Oct 2024 09:38:51 +0200 Subject: [PATCH 2/4] Added reading of single value via annotation --- README.md | 8 +++-- .../io/toolisticon/pogen4selenium/api/By.java | 4 ++- .../pogen4selenium/api/ExtractDataValue.java | 20 +++++++++---- .../example/TestPagePageObject.java | 25 ++++++++++++---- .../pogen4selenium/example/TestPageTest.java | 12 ++++++++ .../dependency-reduced-pom.xml | 2 +- .../ExtractDataValueWrapperExtension.java | 29 +++++++++++++++++++ .../pageobject/MethodsToImplementHelper.java | 3 ++ .../processor/pageobject/package-info.java | 5 ++-- .../src/main/resources/PageObject.tpl | 6 ++-- .../pageobject/TestcaseValidUsage.java | 5 ++++ 11 files changed, 99 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 04c3068..bd56fea 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ public interface TestPagePageObject extends PageObjectParent static final String COUNTER_INCREMENT_BUTTON_ID = "counterIncrementButton"; @ActionMoveToAndClick(COUNTER_INCREMENT_BUTTON_ID) + @Pause(value = 500L) TestPagePageObject clickCounterIncrementButton(); @@ -102,11 +103,14 @@ public interface TestPagePageObject extends PageObjectParent @ExtractData(by = io.toolisticon.pogen4selenium.api.By.XPATH, value = DATA_EXTRACTION_FROM_TABLE_XPATH) TestPageTableEntry getFirstTableEntry(); - default String getCounter() { + @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"); diff --git a/pogen4selenium-api/src/main/java/io/toolisticon/pogen4selenium/api/By.java b/pogen4selenium-api/src/main/java/io/toolisticon/pogen4selenium/api/By.java index 35af24e..9cd4eec 100644 --- a/pogen4selenium-api/src/main/java/io/toolisticon/pogen4selenium/api/By.java +++ b/pogen4selenium-api/src/main/java/io/toolisticon/pogen4selenium/api/By.java @@ -2,7 +2,9 @@ public enum By { ID("id"), - XPATH("xpath"); + XPATH("xpath"), + /** ELEMENT MUST ONLY BE USED TO EXTRACT DATA IN PAGE OBJECTS */ + ELEMENT(""); private final String correspondingByMethodName; diff --git a/pogen4selenium-api/src/main/java/io/toolisticon/pogen4selenium/api/ExtractDataValue.java b/pogen4selenium-api/src/main/java/io/toolisticon/pogen4selenium/api/ExtractDataValue.java index cd21154..1e36d3b 100644 --- a/pogen4selenium-api/src/main/java/io/toolisticon/pogen4selenium/api/ExtractDataValue.java +++ b/pogen4selenium-api/src/main/java/io/toolisticon/pogen4selenium/api/ExtractDataValue.java @@ -29,11 +29,21 @@ String name() default ""; enum Kind{ - TEXT, - ATTRIBUTE, - CSS_VALUE, - TAG_NAME, - ACCESSIBLE_NAME; + TEXT("getText"), + ATTRIBUTE("getAttribute"), + CSS_VALUE("getCssValue"), + TAG_NAME("getTagName"), + ACCESSIBLE_NAME("getAccessibleName"); + + private final String elementMethodName; + + private Kind(String elementMethodName) { + this.elementMethodName = elementMethodName; + } + + public String getElementMethodName() { + return this.elementMethodName; + } } } diff --git a/pogen4selenium-example/src/main/java/io/toolisticon/pogen4selenium/example/TestPagePageObject.java b/pogen4selenium-example/src/main/java/io/toolisticon/pogen4selenium/example/TestPagePageObject.java index 39f0076..0b955b2 100644 --- a/pogen4selenium-example/src/main/java/io/toolisticon/pogen4selenium/example/TestPagePageObject.java +++ b/pogen4selenium-example/src/main/java/io/toolisticon/pogen4selenium/example/TestPagePageObject.java @@ -5,26 +5,36 @@ 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{ static final String DATA_EXTRACTION_FROM_TABLE_XPATH = "//table//tr[contains(@class,'data')]"; - @PageObjectElement(elementVariableName=TestPagePageObject.INPUT_FIELD_ID, by = By.ID, value="" ) - static final String INPUT_FIELD_ID = "searchField"; + @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"; - @ActionMoveToAndClick(COUNTER_INCREMENT_BUTTON_ID) - TestPagePageObject clickCounterIncrementButton(); + 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.XPATH, value = DATA_EXTRACTION_FROM_TABLE_XPATH) List getTableEntries(); @@ -32,11 +42,14 @@ public interface TestPagePageObject extends PageObjectParent @ExtractData(by = io.toolisticon.pogen4selenium.api.By.XPATH, value = DATA_EXTRACTION_FROM_TABLE_XPATH) TestPageTableEntry getFirstTableEntry(); - default String getCounter() { + @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"); diff --git a/pogen4selenium-example/src/test/java/io/toolisticon/pogen4selenium/example/TestPageTest.java b/pogen4selenium-example/src/test/java/io/toolisticon/pogen4selenium/example/TestPageTest.java index 0dfccfe..16cb6bf 100644 --- a/pogen4selenium-example/src/test/java/io/toolisticon/pogen4selenium/example/TestPageTest.java +++ b/pogen4selenium-example/src/test/java/io/toolisticon/pogen4selenium/example/TestPageTest.java @@ -96,5 +96,17 @@ public void incrementCounterTest() { ; } + @Test + public void writeToAndReadFromInputField() { + + TestPagePageObject.init(webDriver) + .writeToInputField("TEST!!!") + .pause(Duration.ofMillis(200L)) + .doAssertions(e -> { + MatcherAssert.assertThat(e.readInputFieldValue(), Matchers.is("TEST!!!")); + }); + + } + } diff --git a/pogen4selenium-processor/dependency-reduced-pom.xml b/pogen4selenium-processor/dependency-reduced-pom.xml index aa8359f..92db545 100644 --- a/pogen4selenium-processor/dependency-reduced-pom.xml +++ b/pogen4selenium-processor/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ pogen4selenium io.toolisticon.pogen4selenium - 0.1.0 + 0.1.1-SNAPSHOT 4.0.0 pogen4selenium-processor diff --git a/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/ExtractDataValueWrapperExtension.java b/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/ExtractDataValueWrapperExtension.java index b1f9866..c7f6e4a 100644 --- a/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/ExtractDataValueWrapperExtension.java +++ b/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/ExtractDataValueWrapperExtension.java @@ -1,5 +1,34 @@ package io.toolisticon.pogen4selenium.processor.pageobject; +import io.toolisticon.aptk.annotationwrapper.api.CustomCodeMethod; +import io.toolisticon.pogen4selenium.api.By; +import io.toolisticon.pogen4selenium.api.ExtractDataValue; + public class ExtractDataValueWrapperExtension { + + @CustomCodeMethod(ExtractDataValue.class) + public static String getFinalMethodCall(ExtractDataValueWrapper extractDataValueWrapper) { + + String command = ( + extractDataValueWrapper.by() == By.ELEMENT ? + extractDataValueWrapper.value() + "Element" + : "getDriver().findElement(By." + extractDataValueWrapper.by().getCorrespondingByMethodName() + "(\"" + extractDataValueWrapper.value() + "\"))" + ) + + "."; + + switch (extractDataValueWrapper.kind()) { + case ATTRIBUTE: + case CSS_VALUE: { + + return command + extractDataValueWrapper.kind().getElementMethodName() + "(\"" + extractDataValueWrapper.name() + "\");"; + } + default: { + + return command + extractDataValueWrapper.kind().getElementMethodName() + "();"; + } + } + + + } } diff --git a/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/MethodsToImplementHelper.java b/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/MethodsToImplementHelper.java index 814fe02..aaec83c 100644 --- a/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/MethodsToImplementHelper.java +++ b/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/MethodsToImplementHelper.java @@ -63,6 +63,9 @@ public Optional getExtractData() { return Optional.ofNullable(ExtractDataWrapper.wrap(this.executableElementWrapper.unwrap())); } + public Optional getExtractDataValue() { + return Optional.ofNullable(ExtractDataValueWrapper.wrap(this.executableElementWrapper.unwrap())); + } public String getNextImplClassName() { diff --git a/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/package-info.java b/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/package-info.java index b5eaa52..52d9a00 100644 --- a/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/package-info.java +++ b/pogen4selenium-processor/src/main/java/io/toolisticon/pogen4selenium/processor/pageobject/package-info.java @@ -1,8 +1,8 @@ /** * This package contains the seleniumap annotation processor. */ -@AnnotationWrapper(value={PageObject.class, PageObjectElement.class, ActionClick.class, ActionMoveToAndClick.class, ActionWrite.class, ExtractData.class,Pause.class} -,bindCustomCode = {PageObjectWrapperExtension.class, ExtractDataWrapperExtension.class} +@AnnotationWrapper(value={PageObject.class, PageObjectElement.class, ActionClick.class, ActionMoveToAndClick.class, ActionWrite.class, ExtractData.class, ExtractDataValue.class ,Pause.class} +,bindCustomCode = {PageObjectWrapperExtension.class, ExtractDataWrapperExtension.class, ExtractDataValueWrapperExtension.class} ,usePublicVisibility = true) package io.toolisticon.pogen4selenium.processor.pageobject; @@ -11,6 +11,7 @@ import io.toolisticon.pogen4selenium.api.ActionMoveToAndClick; import io.toolisticon.pogen4selenium.api.ActionWrite; import io.toolisticon.pogen4selenium.api.ExtractData; +import io.toolisticon.pogen4selenium.api.ExtractDataValue; import io.toolisticon.pogen4selenium.api.PageObject; import io.toolisticon.pogen4selenium.api.PageObjectElement; import io.toolisticon.pogen4selenium.api.Pause; diff --git a/pogen4selenium-processor/src/main/resources/PageObject.tpl b/pogen4selenium-processor/src/main/resources/PageObject.tpl index 611997d..e782973 100644 --- a/pogen4selenium-processor/src/main/resources/PageObject.tpl +++ b/pogen4selenium-processor/src/main/resources/PageObject.tpl @@ -64,11 +64,11 @@ public class ${ toImplementHelper.implementationClassName } ${toImplementHelper. // Move to Element and click new Actions(getDriver()).moveToElement(${method.getElementToMoveToAndClick.get}Element).pause(300).click().build().perform(); !{/if} -!{if method.getExtractData.isPresent} +!{if method.getExtractDataValue.isPresent} + return ${method.getExtractDataValue.get.getFinalMethodCall} +!{elseif method.getExtractData.isPresent} !{if method.getExtractData.get.isList} return getDriver().findElements(By.${method.getExtractData.get.by.correspondingByMethodName}("${method.getExtractData.get.value}")).stream().map( ${method.getExtractData.get.extractedDataImplName}::new).collect(Collectors.toList()); -!{elseif method.getExtractData.get.isString} - return !{else} return new ${method.getExtractData.get.extractedDataImplName}(getDriver().findElement(By.${method.getExtractData.get.by.correspondingByMethodName}("${method.getExtractData.get.value}"))); !{/if} diff --git a/pogen4selenium-processor/src/test/resources/testcases/pageobject/TestcaseValidUsage.java b/pogen4selenium-processor/src/test/resources/testcases/pageobject/TestcaseValidUsage.java index 0e244fa..50b3208 100644 --- a/pogen4selenium-processor/src/test/resources/testcases/pageobject/TestcaseValidUsage.java +++ b/pogen4selenium-processor/src/test/resources/testcases/pageobject/TestcaseValidUsage.java @@ -3,6 +3,8 @@ import io.toolisticon.cute.PassIn; import io.toolisticon.pogen4selenium.api.ActionClick; import io.toolisticon.pogen4selenium.api.ActionWrite; +import io.toolisticon.pogen4selenium.api.By; +import io.toolisticon.pogen4selenium.api.ExtractDataValue; import io.toolisticon.pogen4selenium.api.PageObject; import io.toolisticon.pogen4selenium.api.PageObjectElement; import io.toolisticon.pogen4selenium.api.PageObjectParent; @@ -26,6 +28,9 @@ public interface LoginPage extends PageObjectParent{ LoginPage writeUserName(@ActionWrite(USERNAME_ID) String username); LoginPage writePassword(@ActionWrite(PASSWORD_ID) String password); + @ExtractDataValue(by=By.XPATH, value="/div", kind=ExtractDataValue.Kind.ATTRIBUTE, name="href") + String getLinkHref(); + @ActionClick(SUBMIT_BUTTON_ID) LoginPage clickSubmitButton(); From 757665e2aa0846dfd8ac4b0b8f59be1a36f41c1e Mon Sep 17 00:00:00 2001 From: Tobias Stamann Date: Mon, 21 Oct 2024 10:10:26 +0200 Subject: [PATCH 3/4] Updated README.md --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index bd56fea..dd569aa 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,28 @@ public class TestPageTest { ``` +#### Methods provided by fluent api + +There are some default methods provided by the fluent api: + +##### verify +By using the verify methods it's possible to do check state of elements, i.e. if elements are present or clickable. Expected state is configured in PageObjectElement annotation. If not set explicitely all elements are expected to be present byx default. + +##### doAssertions +It's possible to inline assertions done via your favourite testing tools. +By providing this method it's not necessary to hassle with local variables anymore. + +##### execute +The execute method allows you to do test steps dynamically, like reading data from the web page and doing things based on the extracted data. +It can also be used to switch to another page object type. This can be useful if input data is expected to be validated and should stay on the same page and show an error message. + + +## Best practices + +There are a few things you should consider as best practices + +- Naming convention: Please use specific prefixes for you page object methods. This can be 'do' for all actions and 'get' for reading data. +- Page objects should define just the happy path. Special cases like failing validations can be handled in the unit tests via the execute method(you can map to another page object type in it). ## Example From 2f7ba578c5523a33606521ecfc4ca7757aa91545 Mon Sep 17 00:00:00 2001 From: Tobias Stamann Date: Mon, 21 Oct 2024 10:11:57 +0200 Subject: [PATCH 4/4] Update versions for release --- pogen4selenium-api/pom.xml | 2 +- pogen4selenium-example/pom.xml | 4 ++-- pogen4selenium-processor/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pogen4selenium-api/pom.xml b/pogen4selenium-api/pom.xml index be81f79..9566103 100644 --- a/pogen4selenium-api/pom.xml +++ b/pogen4selenium-api/pom.xml @@ -9,7 +9,7 @@ io.toolisticon.pogen4selenium pogen4selenium - 0.1.1-SNAPSHOT + 0.2.0 pogen4selenium-api diff --git a/pogen4selenium-example/pom.xml b/pogen4selenium-example/pom.xml index 3148d7b..e2786cd 100644 --- a/pogen4selenium-example/pom.xml +++ b/pogen4selenium-example/pom.xml @@ -9,7 +9,7 @@ io.toolisticon.pogen4selenium pogen4selenium - 0.1.1-SNAPSHOT + 0.2.0 pogen4selenium-example @@ -33,7 +33,7 @@ io.toolisticon.pogen4selenium pogen4selenium-api - 0.1.1-SNAPSHOT + 0.2.0 diff --git a/pogen4selenium-processor/pom.xml b/pogen4selenium-processor/pom.xml index 53453a6..62063d6 100644 --- a/pogen4selenium-processor/pom.xml +++ b/pogen4selenium-processor/pom.xml @@ -9,7 +9,7 @@ io.toolisticon.pogen4selenium pogen4selenium - 0.1.1-SNAPSHOT + 0.2.0 pogen4selenium-processor diff --git a/pom.xml b/pom.xml index 9fb4862..824aad4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 io.toolisticon.pogen4selenium pogen4selenium - 0.1.1-SNAPSHOT + 0.2.0 pom pogen4selenium Please refer to https://github.com/toolisticon/pogen4selenium