diff --git a/README.md b/README.md index d671f79e..977701da 100644 --- a/README.md +++ b/README.md @@ -425,45 +425,48 @@ Supported platform values: `web` | `android` | `ios` | `macos` | `windows` ## πŸ›οΈ Architecture ``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Your Test Project β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Feature β”‚ β”‚ Hooks β”‚ β”‚ Page Objects β”‚ β”‚ -β”‚ β”‚ Files β”‚ β”‚ β”‚ β”‚ (Java or JSON) β”‚ β”‚ -β”‚ β”‚(.feature)β”‚ β”‚(@Before/ β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ @After) β”‚ β”‚ β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ β”‚ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ β–Ό β–Ό β–Ό Pickleib β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚BuiltIn β”‚ β”‚Pickleib β”‚ β”‚ PageObjectRegistryβ”‚ β”‚ -β”‚ β”‚Steps β”‚ β”‚WebDriver β”‚ β”‚ or PageObjectJson β”‚ β”‚ -β”‚ β”‚(68 steps)β”‚ β”‚(ThreadL) β”‚ β”‚(ElementRepository)β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β–Ό β–Ό β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ InteractionBase β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚WebInteractionsβ”‚ β”‚PlatformInteractβ”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ (Selenium) β”‚ β”‚ (Appium) β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Utility Helpers β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ClickHlp β”‚ β”‚InputHelp β”‚ β”‚ElementStateHlpβ”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β–Ό β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ RetryPolicy β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Your Test Project β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Feature β”‚ β”‚ Hooks β”‚ β”‚ Page Objects β”‚ β”‚ Test Runner β”‚ β”‚ +β”‚ β”‚ Files β”‚ β”‚ β”‚ β”‚(Java or JSON) β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚(.feature)β”‚ β”‚(@Before/ β”‚ β”‚ β”‚ β”‚ (@Pickleib/ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ @After) β”‚ β”‚ β”‚ β”‚ @CukeOpts) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ β”‚ β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β–Ό β–Ό β–Ό β–Ό β”‚ +β”‚ Pickleib β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚BuiltIn β”‚ β”‚Pickleib β”‚ β”‚ PageObjectRegistryβ”‚ β”‚Pickleib β”‚ β”‚ +β”‚ β”‚Steps β”‚ β”‚WebDriver β”‚ β”‚ or PageObjectJson β”‚ β”‚Runner β”‚ β”‚ +β”‚ β”‚(68 steps)β”‚ β”‚(ThreadL) β”‚ β”‚(ElementRepository)β”‚ β”‚(ExtendW)β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ InteractionBase β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚WebInteractionsβ”‚ β”‚PlatformInteractβ”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ (Selenium) β”‚ β”‚ (Appium) β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Utility Helpers β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ClickHlp β”‚ β”‚InputHelp β”‚ β”‚ElementStateHlpβ”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ RetryPolicy β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- diff --git a/src/main/java/pickleib/annotations/ContextValue.java b/src/main/java/pickleib/annotations/ContextValue.java index dc2bae58..c2fcbf51 100644 --- a/src/main/java/pickleib/annotations/ContextValue.java +++ b/src/main/java/pickleib/annotations/ContextValue.java @@ -5,9 +5,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * Injects a value from the {@link context.ContextStore} into the annotated field. + * Supports {@code {{key}}} replacement patterns. + */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) public @interface ContextValue { + /** @return the context key to look up */ String value(); + /** @return the fallback value if the key is not found */ String defaultValue() default ""; } diff --git a/src/main/java/pickleib/annotations/PageObject.java b/src/main/java/pickleib/annotations/PageObject.java index 8e0186c0..d6895b75 100644 --- a/src/main/java/pickleib/annotations/PageObject.java +++ b/src/main/java/pickleib/annotations/PageObject.java @@ -6,9 +6,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** Marks a class as a page object for automatic registration by {@link pickleib.runner.PickleibRunner}. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface PageObject { + /** @return the target platform for this page object */ Platform platform() default Platform.web; + /** @return custom registry name (defaults to class name) */ String name() default ""; } diff --git a/src/main/java/pickleib/annotations/Pickleib.java b/src/main/java/pickleib/annotations/Pickleib.java index bafc4517..84c3bd99 100644 --- a/src/main/java/pickleib/annotations/Pickleib.java +++ b/src/main/java/pickleib/annotations/Pickleib.java @@ -5,10 +5,14 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** Marks a test runner class for automatic Pickleib element repository setup. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Pickleib { + /** @return packages to scan for {@code @PageObject} / {@code @ScreenObject} classes */ String[] scan() default {}; + /** @return whether to enable built-in Cucumber step definitions */ boolean builtInSteps() default true; + /** @return path to the {@code page-repository.json} file */ String pageRepository() default ""; } diff --git a/src/main/java/pickleib/annotations/ScreenObject.java b/src/main/java/pickleib/annotations/ScreenObject.java index a4feb3f0..d06ed713 100644 --- a/src/main/java/pickleib/annotations/ScreenObject.java +++ b/src/main/java/pickleib/annotations/ScreenObject.java @@ -6,9 +6,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** Marks a class as a mobile screen object for automatic registration. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ScreenObject { + /** @return the target platform for this screen object */ Platform platform() default Platform.android; + /** @return custom registry name (defaults to class name) */ String name() default ""; } diff --git a/src/main/java/pickleib/annotations/StepDefinitions.java b/src/main/java/pickleib/annotations/StepDefinitions.java index 7765aca0..baa353e8 100644 --- a/src/main/java/pickleib/annotations/StepDefinitions.java +++ b/src/main/java/pickleib/annotations/StepDefinitions.java @@ -5,6 +5,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** Marks a class as containing Cucumber step definitions. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface StepDefinitions { diff --git a/src/main/java/pickleib/driver/DriverFactory.java b/src/main/java/pickleib/driver/DriverFactory.java index 9244f7a5..28ab3e7f 100644 --- a/src/main/java/pickleib/driver/DriverFactory.java +++ b/src/main/java/pickleib/driver/DriverFactory.java @@ -20,7 +20,9 @@ public interface DriverFactory { * */ enum DriverType { + /** Selenium WebDriver for web browser automation. */ selenium, + /** Appium driver for mobile/desktop automation. */ appium; /** diff --git a/src/main/java/pickleib/enums/Direction.java b/src/main/java/pickleib/enums/Direction.java index cdf81d14..cb345eff 100644 --- a/src/main/java/pickleib/enums/Direction.java +++ b/src/main/java/pickleib/enums/Direction.java @@ -3,12 +3,16 @@ import lombok.Getter; /** - * Basic direction + * Basic scroll/swipe direction. */ @Getter public enum Direction { + /** Scroll upward. */ up, + /** Scroll downward. */ down, + /** Scroll left. */ left, + /** Scroll right. */ right } diff --git a/src/main/java/pickleib/enums/ElementState.java b/src/main/java/pickleib/enums/ElementState.java index 6002542d..25f2367d 100644 --- a/src/main/java/pickleib/enums/ElementState.java +++ b/src/main/java/pickleib/enums/ElementState.java @@ -3,14 +3,20 @@ import lombok.Getter; /** - * Element states + * Expected states for element verification. */ @Getter public enum ElementState { + /** Element is enabled for interaction. */ enabled, + /** Element is visible on the page. */ displayed, + /** Element is selected (e.g. checkbox). */ selected, + /** Element is disabled. */ disabled, + /** Element is not selected. */ unselected, + /** Element is not present in the DOM. */ absent } diff --git a/src/main/java/pickleib/enums/EmulatedDevice.java b/src/main/java/pickleib/enums/EmulatedDevice.java index 124ff882..527623c5 100644 --- a/src/main/java/pickleib/enums/EmulatedDevice.java +++ b/src/main/java/pickleib/enums/EmulatedDevice.java @@ -3,62 +3,117 @@ import lombok.Getter; import java.util.Map; +/** Chrome DevTools emulated device profiles for mobile testing. */ @Getter public enum EmulatedDevice { + /** iPad Air device profile. */ iPadAir("iPad Air"), + /** iPhone 4 device profile. */ iPhone4("iPhone 4"), + /** iPhone 5/SE device profile. */ iPhone5SE("iPhone 5/SE"), + /** iPhone 6 device profile. */ iPhone6("iPhone 6"), + /** iPhone 7 device profile. */ iPhone7("iPhone 7"), + /** iPhone 8 device profile. */ iPhone8("iPhone 8"), + /** iPhone 6 Plus device profile. */ iPhone6Plus("iPhone 6 Plus"), + /** iPhone 7 Plus device profile. */ iPhone7Plus("iPhone 7 Plus"), + /** iPhone 8 Plus device profile. */ iPhone8Plus("iPhone 8 Plus"), + /** iPhone X device profile. */ iPhoneX("iPhone X"), + /** iPhone 12 Pro device profile. */ iPhone12Pro("iPhone 12 Pro"), + /** Nexus 4 device profile. */ Nexus4("Nexus 4"), + /** Nexus 5 device profile. */ Nexus5("Nexus 5"), + /** Nexus 5X device profile. */ Nexus5X("Nexus 5X"), + /** Nexus 6 device profile. */ Nexus6("Nexus 6"), + /** Nexus 6P device profile. */ Nexus6P("Nexus 6P"), + /** Nexus 7 device profile. */ Nexus7("Nexus 7"), + /** Pixel 2 device profile. */ Pixel2("Pixel 2"), + /** Pixel 2 XL device profile. */ Pixel2XL("Pixel 2 XL"), + /** Microsoft Lumia 550 device profile. */ MicrosoftLumia550("Microsoft Lumia 550"), + /** Microsoft Lumia 950 device profile. */ MicrosoftLumia950("Microsoft Lumia 950"), + /** Galaxy S III device profile. */ GalaxySIII("Galaxy S III"), + /** Galaxy S5 device profile. */ GalaxyS5("Galaxy S5"), + /** Kindle Fire HDX device profile. */ KindleFireHDX("Kindle Fire HDX"), + /** iPad Mini device profile. */ iPadMini("iPad Mini"), + /** iPad device profile. */ iPad("iPad"), + /** iPad Pro device profile. */ iPadPro("iPad Pro"), + /** Nexus 10 device profile. */ Nexus10("Nexus 10"), + /** Galaxy Note 3 device profile. */ GalaxyNote3("Galaxy Note 3"), + /** Galaxy Note II device profile. */ GalaxyNoteII("Galaxy Note II"), + /** Apple iPhone 4 device profile. */ AppleiPhone4("Apple iPhone 4"), + /** Apple iPhone 5 device profile. */ AppleiPhone5("Apple iPhone 5"), + /** Apple iPhone 6 device profile. */ AppleiPhone6("Apple iPhone 6"), + /** BlackBerry Z30 device profile. */ BlackBerryZ30("BlackBerry Z30"), + /** Google Nexus 4 device profile. */ GoogleNexus4("Google Nexus 4"), + /** Google Nexus 5 device profile. */ GoogleNexus5("Google Nexus 5"), + /** Google Nexus 6 device profile. */ GoogleNexus6("Google Nexus 6"), + /** Google Nexus 7 device profile. */ GoogleNexus7("Google Nexus 7"), + /** Google Nexus 10 device profile. */ GoogleNexus10("Google Nexus 10"), + /** LG Optimus L70 device profile. */ LGOptimusL70("LG Optimus L70"), + /** Nokia N9 device profile. */ NokiaN9("Nokia N9"), + /** Nokia Lumia 520 device profile. */ NokiaLumia520("Nokia Lumia 520"), + /** Samsung Galaxy S III device profile. */ SamsungGalaxySIII("Samsung Galaxy S III"), + /** Samsung Galaxy S4 device profile. */ SamsungGalaxyS4("Samsung Galaxy S4"), + /** Samsung Galaxy S20 Ultra device profile. */ SamsungGalaxyS20Ultra("Samsung Galaxy S20 Ultra"), + /** Amazon Kindle Fire HDX device profile. */ AmazonKindleFireHDX("Amazon Kindle Fire HDX"), + /** Apple iPad Mini device profile. */ AppleiPadMini("Apple iPad Mini"), + /** Apple iPad device profile. */ AppleiPad("Apple iPad"), + /** BlackBerry PlayBook device profile. */ BlackBerryPlayBook("BlackBerry PlayBook"), + /** Samsung Galaxy Note 3 device profile. */ SamsungGalaxyNote3("Samsung Galaxy Note 3"), + /** Samsung Galaxy Note II device profile. */ SamsungGalaxyNoteII("Samsung Galaxy Note II"), + /** Laptop with touch device profile. */ Laptopwithtouch("Laptop with touch"), + /** Laptop with HiDPI screen device profile. */ LaptopwithHiDPIscreen("Laptop with HiDPI screen"), + /** Laptop with MDPI screen device profile. */ LaptopwithMDPIscreen("Laptop with MDPI screen"); final String deviceName; @@ -67,10 +122,15 @@ public enum EmulatedDevice { this.deviceName = deviceName; }; + /** @return a map containing the device name for Chrome mobile emulation */ public Map emulate(){ return Map.of("deviceName", this.deviceName); } + /** + * @param text the device name to look up (case-insensitive) + * @return the matching {@link EmulatedDevice}, or {@code null} if not found + */ public static EmulatedDevice getType(String text) { if (text != null) for (EmulatedDevice driverType:values()) diff --git a/src/main/java/pickleib/enums/InteractionType.java b/src/main/java/pickleib/enums/InteractionType.java index 9a26bb94..25b7b28a 100644 --- a/src/main/java/pickleib/enums/InteractionType.java +++ b/src/main/java/pickleib/enums/InteractionType.java @@ -6,8 +6,12 @@ * The available interaction types are click, fill, center, and verify. */ public enum InteractionType { + /** Click on the element. */ click, + /** Fill the element with input. */ fill, + /** Scroll the element to center. */ center, + /** Verify the element state. */ verify } diff --git a/src/main/java/pickleib/enums/Navigation.java b/src/main/java/pickleib/enums/Navigation.java index 6f32551d..83b0b940 100644 --- a/src/main/java/pickleib/enums/Navigation.java +++ b/src/main/java/pickleib/enums/Navigation.java @@ -7,6 +7,8 @@ */ @Getter public enum Navigation { + /** Navigate backwards in browser history. */ backwards, + /** Navigate forwards in browser history. */ forwards } diff --git a/src/main/java/pickleib/enums/Platform.java b/src/main/java/pickleib/enums/Platform.java index 955616c0..5fe9d4ab 100644 --- a/src/main/java/pickleib/enums/Platform.java +++ b/src/main/java/pickleib/enums/Platform.java @@ -1,9 +1,15 @@ package pickleib.enums; +/** Supported automation platforms. */ public enum Platform { + /** Web browser automation. */ web, + /** Android mobile automation. */ android, + /** iOS mobile automation. */ ios, + /** macOS desktop automation. */ macos, + /** Windows desktop automation. */ windows } diff --git a/src/main/java/pickleib/enums/PrimarySelectorType.java b/src/main/java/pickleib/enums/PrimarySelectorType.java index 550d1a6b..dc2a6418 100644 --- a/src/main/java/pickleib/enums/PrimarySelectorType.java +++ b/src/main/java/pickleib/enums/PrimarySelectorType.java @@ -4,6 +4,8 @@ * Defines primary selector types */ public enum PrimarySelectorType { + /** CSS selector. */ css, + /** XPath selector. */ xpath } \ No newline at end of file diff --git a/src/main/java/pickleib/exceptions/PickleibException.java b/src/main/java/pickleib/exceptions/PickleibException.java index c330dbde..ee2fa10f 100644 --- a/src/main/java/pickleib/exceptions/PickleibException.java +++ b/src/main/java/pickleib/exceptions/PickleibException.java @@ -1,8 +1,11 @@ package pickleib.exceptions; +/** Runtime exception thrown by Pickleib when an interaction or verification fails. */ public class PickleibException extends RuntimeException { + /** @param errorMessage the error message */ public PickleibException(String errorMessage) {super(errorMessage);} + /** @param errorMessage the cause exception */ public PickleibException(Exception errorMessage) {super(errorMessage);} } diff --git a/src/main/java/pickleib/exceptions/PickleibVerificationException.java b/src/main/java/pickleib/exceptions/PickleibVerificationException.java index be2f0d08..2199e280 100644 --- a/src/main/java/pickleib/exceptions/PickleibVerificationException.java +++ b/src/main/java/pickleib/exceptions/PickleibVerificationException.java @@ -1,11 +1,14 @@ package pickleib.exceptions; +/** Thrown when a Pickleib element or text verification fails. */ public class PickleibVerificationException extends PickleibException{ + /** @param errorMessage the verification failure message */ public PickleibVerificationException(String errorMessage) { super(errorMessage); } + /** @param errorMessage the cause exception */ public PickleibVerificationException(Exception errorMessage) { super(errorMessage); } diff --git a/src/main/java/pickleib/platform/PickleibScreenObject.java b/src/main/java/pickleib/platform/PickleibScreenObject.java index 86cbb929..708c5620 100644 --- a/src/main/java/pickleib/platform/PickleibScreenObject.java +++ b/src/main/java/pickleib/platform/PickleibScreenObject.java @@ -11,10 +11,10 @@ import java.time.Duration; +/** Base class for mobile/desktop screen page objects with automatic Appium field decoration. */ public abstract class PickleibScreenObject extends PlatformUtilities { /** * PickleibScreenObject for frameworks that use the Pickleib driver - * */ protected PickleibScreenObject(){ super(PickleibAppiumDriver.get()); @@ -32,6 +32,7 @@ protected PickleibScreenObject(){ /** * PickleibScreenObject for frameworks that do not use the Pickleib driver * + * @param driver the RemoteWebDriver instance */ protected PickleibScreenObject(RemoteWebDriver driver){ super(driver); @@ -49,6 +50,8 @@ protected PickleibScreenObject(RemoteWebDriver driver){ /** * PickleibScreenObject for frameworks with custom field decorator that use the Pickleib driver * + * @param the field decorator type + * @param fieldDecorator the custom field decorator */ protected PickleibScreenObject(CustomFieldDecorator fieldDecorator){ super(PickleibWebDriver.get()); @@ -58,6 +61,9 @@ protected PickleibScreenObj /** * PickleibScreenObject for frameworks with custom field decorator that do not use the Pickleib driver * + * @param the field decorator type + * @param fieldDecorator the custom field decorator + * @param driver the RemoteWebDriver instance */ protected PickleibScreenObject( CustomFieldDecorator fieldDecorator, diff --git a/src/main/java/pickleib/platform/interactions/PlatformInteractions.java b/src/main/java/pickleib/platform/interactions/PlatformInteractions.java index 36bced4e..801e103d 100644 --- a/src/main/java/pickleib/platform/interactions/PlatformInteractions.java +++ b/src/main/java/pickleib/platform/interactions/PlatformInteractions.java @@ -28,13 +28,19 @@ import static utils.StringUtilities.contextCheck; import static utils.StringUtilities.*; +/** Implements polymorphic interaction utilities for Appium-based platform testing. */ public class PlatformInteractions extends PlatformUtilities implements PolymorphicUtilities { + /** + * @param driver the RemoteWebDriver instance + * @param wait the FluentWait instance + */ public PlatformInteractions(RemoteWebDriver driver, FluentWait wait) { super(driver); this.wait = wait; } + /** Creates an instance using the default Pickleib Appium driver. */ public PlatformInteractions() { super(PickleibAppiumDriver.get()); } @@ -820,7 +826,6 @@ public void fillInputElement(WebElement inputElement, String elementName, String * Executes interactions on a list of element bundles, based on the specified interaction type. *

* The interaction type is specified in the "Interaction Type" key of the map contained in each element bundle. - *

* * @param bundles A list of element bundles containing the element name, the matching element, and a map of the element's attributes. * @param pageName The name of the page object. diff --git a/src/main/java/pickleib/platform/utilities/PlatformUtilities.java b/src/main/java/pickleib/platform/utilities/PlatformUtilities.java index c5492c0c..b2710dc0 100644 --- a/src/main/java/pickleib/platform/utilities/PlatformUtilities.java +++ b/src/main/java/pickleib/platform/utilities/PlatformUtilities.java @@ -23,6 +23,7 @@ import static utils.StringUtilities.highlighted; import static utils.StringUtilities.Color.*; +/** Base class for platform-specific (mobile/desktop) interaction utilities. */ public abstract class PlatformUtilities extends Utilities { /** @@ -34,11 +35,14 @@ public PlatformUtilities() { /** * MobileUtilities for frameworks that do not use the Pickleib driver + * + * @param driver the RemoteWebDriver instance to use */ public PlatformUtilities(RemoteWebDriver driver) { super(driver, (element) -> centerElement(element, driver)); } + /** @return the active RemoteWebDriver instance */ public RemoteWebDriver driver() { return this.driver; } @@ -59,6 +63,10 @@ public RemoteWebDriver driver() { * Centers the element by iteratively swiping toward it. * First attempts a calculated scroll. If the element is still not in view, * uses RetryPolicy to iteratively swipe until the element is within the viewport. + * + * @param element the element to center + * @param driver the driver instance to use + * @return the centered element */ public static WebElement centerElement(WebElement element, RemoteWebDriver driver) { Point center = new Point( @@ -341,7 +349,8 @@ public void performSequence(Sequence sequence, long initialTime) { /** * Swipes from the center to the point * - * @param point target point + * @param point target point + * @param driver the driver instance */ public static void swipeFromCenter(Point point, RemoteWebDriver driver) { Point center = new Point( @@ -351,6 +360,7 @@ public static void swipeFromCenter(Point point, RemoteWebDriver driver) { swipe(center, point, driver); } + /** @param point target point to swipe to from center */ public void swipeFromCenter(Point point) { swipeFromCenter(point, driver); } @@ -372,8 +382,8 @@ public WebElement swipeElement(WebElement element, Point point) { * Swipes element to the point with coordinates ({xOffset}; {yOffset}). * * @param element target element - * @param xOffset x coordinate of target point - * @param xOffset y coordinate of target point + * @param xOffset x coordinate offset from element center + * @param yOffset y coordinate offset from element center * @return returns the swiped element */ public WebElement swipeWithOffset(WebElement element, Integer xOffset, Integer yOffset) { diff --git a/src/main/java/pickleib/runner/ClasspathScanner.java b/src/main/java/pickleib/runner/ClasspathScanner.java index 1e120dad..3db5e395 100644 --- a/src/main/java/pickleib/runner/ClasspathScanner.java +++ b/src/main/java/pickleib/runner/ClasspathScanner.java @@ -8,10 +8,16 @@ import java.util.Enumeration; import java.util.List; +/** Scans the classpath for classes annotated with a given annotation. */ public class ClasspathScanner { private static final Printer log = new Printer(ClasspathScanner.class); + /** + * @param annotation the annotation to scan for + * @param packages the packages to scan + * @return list of classes annotated with the given annotation + */ public static List> scanForAnnotatedClasses( Class annotation, String... packages) { List> results = new ArrayList<>(); diff --git a/src/main/java/pickleib/runner/ContextValueInjector.java b/src/main/java/pickleib/runner/ContextValueInjector.java index a2971a21..6ffea18a 100644 --- a/src/main/java/pickleib/runner/ContextValueInjector.java +++ b/src/main/java/pickleib/runner/ContextValueInjector.java @@ -7,14 +7,19 @@ import java.lang.reflect.Field; import static utils.StringUtilities.contextCheck; +/** + * Processes {@link ContextValue} annotations by injecting values from the {@link ContextStore}. + */ public class ContextValueInjector { private static final Printer log = new Printer(ContextValueInjector.class); private static final ObjectMapper objectMapper = new ObjectMapper(); /** - * Injects @ContextValue-annotated fields on the given instance. + * Injects {@link ContextValue}-annotated fields on the given instance. * Scans the instance's class hierarchy (including superclasses) for annotated fields. + * + * @param instance the object whose annotated fields will be injected */ public static void injectFields(Object instance) { Class clazz = instance.getClass(); diff --git a/src/main/java/pickleib/runner/PageObjectRegistry.java b/src/main/java/pickleib/runner/PageObjectRegistry.java index 2672b169..72c3dd38 100644 --- a/src/main/java/pickleib/runner/PageObjectRegistry.java +++ b/src/main/java/pickleib/runner/PageObjectRegistry.java @@ -21,6 +21,10 @@ import static utils.StringUtilities.firstLetterDeCapped; +/** + * Registry that maps page object classes to their metadata and provides + * element acquisition via reflection-based field lookup. + */ public class PageObjectRegistry implements ElementRepository { private static final Printer log = new Printer(PageObjectRegistry.class); @@ -33,25 +37,37 @@ public class PageObjectRegistry implements ElementRepository { record PageObjectMetadata(Class pageClass, String name, Platform platform) {} + /** + * @param pageClass the page object class to register + * @param name custom name (empty string uses class simple name) + * @param platform the target platform + */ public void register(Class pageClass, String name, Platform platform) { String key = (name.isEmpty() ? pageClass.getSimpleName() : name).toLowerCase(); registry.put(key, new PageObjectMetadata(pageClass, name.isEmpty() ? pageClass.getSimpleName() : name, platform)); } + /** @param pageName the page name to check + * @return true if the page is registered */ public boolean isRegistered(String pageName) { return registry.containsKey(pageName.toLowerCase()); } + /** @param pageName the page name to look up + * @return the registered page class */ public Class getPageClass(String pageName) { PageObjectMetadata meta = registry.get(pageName.toLowerCase()); if (meta == null) throw new NoSuchElementException("Page '" + pageName + "' not found in registry"); return meta.pageClass(); } + /** @return the number of registered page objects */ public int size() { return registry.size(); } + /** @param pageName the page name to look up + * @return the platform name for the page */ public String getPlatform(String pageName) { PageObjectMetadata meta = registry.get(pageName.toLowerCase()); return meta != null ? meta.platform().name() : "web"; diff --git a/src/main/java/pickleib/runner/PickleibRunner.java b/src/main/java/pickleib/runner/PickleibRunner.java index 5739d600..cbcc1c3a 100644 --- a/src/main/java/pickleib/runner/PickleibRunner.java +++ b/src/main/java/pickleib/runner/PickleibRunner.java @@ -32,9 +32,12 @@ public class PickleibRunner implements BeforeAllCallback, TestInstancePostProces private static final Printer log = new Printer(PickleibRunner.class); private static final PageObjectRegistry registry = new PageObjectRegistry(); + /** Default path for the JSON page repository file. */ public static final String DEFAULT_PAGE_REPOSITORY = "src/test/resources/page-repository.json"; + /** Default package to scan for {@code @PageObject} / {@code @ScreenObject} classes. */ public static final String DEFAULT_SCAN_PACKAGE = "pages"; + /** @return the shared page object registry */ public static PageObjectRegistry getRegistry() { return registry; } diff --git a/src/main/java/pickleib/steps/BuiltInSteps.java b/src/main/java/pickleib/steps/BuiltInSteps.java index 326df5d0..58da90b2 100644 --- a/src/main/java/pickleib/steps/BuiltInSteps.java +++ b/src/main/java/pickleib/steps/BuiltInSteps.java @@ -74,6 +74,7 @@ private static void installSkill() { } catch (IOException ignored) {} } + /** Creates a new instance and clears cached page object instances to avoid stale driver proxies between scenarios. */ public BuiltInSteps() { super(true, true); // Clear cached page object instances to avoid stale driver proxies between scenarios @@ -84,6 +85,8 @@ public BuiltInSteps() { * Sets the element repository used by all built-in steps. * Call this from your project's Hooks or step class to use a custom repository * instead of the PickleibRunner's auto-discovered registry. + * + * @param repository the element repository to use */ public static void setElementRepository(ElementRepository repository) { elementRepository = repository; @@ -141,11 +144,16 @@ private void autoDetectRepository() { // ─── Platform / Context ────────────────────────────────────────────── + /** @param type the default driver type to use for interactions */ @Given("^Set default platform as (appium|selenium)$") public void setDefaultPlatform(DriverFactory.DriverType type) { defaultPlatform = type; } + /** + * @param key the context key + * @param value the context value + */ @Given("Update context {} -> {}") public void updateContext(String key, String value) { value = contextCheck(value); @@ -153,6 +161,10 @@ public void updateContext(String key, String value) { ContextStore.put(key, value); } + /** + * @param contextKey the source context key + * @param newContextKey the destination context key + */ @Given("Save context value from {} context key to {}") public void saveContextValueFromOneContextKeyToAnother(String contextKey, String newContextKey) { Object value = ContextStore.get(contextKey); @@ -162,17 +174,20 @@ public void saveContextValueFromOneContextKeyToAnother(String contextKey, String // ─── Navigation ───────────────────────────────────────────────────── + /** @param url the URL to navigate to */ @Given("Navigate to url: {}") public void getUrl(String url) { webInteractions.getUrl(url); } + /** Navigates to the URL stored in the {@code test-url} context key. */ @Given("Navigate to test url") public void navigateToTestPage() { String url = ContextStore.get("test-url", ""); webInteractions.navigate(url); } + /** @param page the page path to append to the current URL */ @Given("Go to the {} page") public void toPage(String page) { String url = PickleibWebDriver.get().getCurrentUrl(); @@ -180,11 +195,13 @@ public void toPage(String page) { webInteractions.navigate(pageUrl); } + /** Refreshes the current page. */ @Given("Refresh the page") public void refresh() { webInteractions.refresh(); } + /** @param direction the browser navigation direction (backwards or forwards) */ @Given("^Navigate browser (backwards|forwards)$") public void browserNavigate(Navigation direction) { webInteractions.navigateBrowser(direction); @@ -192,17 +209,20 @@ public void browserNavigate(Navigation direction) { // ─── Window / Tab ─────────────────────────────────────────────────── + /** Switches to the next browser tab and saves the parent handle to context. */ @Given("Switch to the next tab") public void switchTab() { String parentHandle = webInteractions.switchWindowByHandle(null); ContextStore.put("parentHandle", parentHandle); } + /** Switches back to the parent tab using the saved handle from context. */ @Given("Switch back to the parent tab") public void switchToParentTab() { webInteractions.switchWindowByHandle(ContextStore.get("parentHandle").toString()); } + /** @param handle the window handle to switch to */ @Given("Switch to the tab with handle: {}") public void switchTab(String handle) { handle = contextCheck(handle); @@ -210,12 +230,14 @@ public void switchTab(String handle) { ContextStore.put("parentHandle", parentHandle); } + /** @param handle the tab index to switch to */ @Given("Switch to the tab number {}") public void switchTab(Integer handle) { String parentHandle = webInteractions.switchWindowByIndex(handle); ContextStore.put("parentHandle", parentHandle); } + /** Switches to the next active window using the Appium driver. */ @Given("Switch to the next active window") public void switchToNextActiveWindow() { PickleibAppiumDriver.get().switchTo().window( @@ -223,6 +245,7 @@ public void switchToNextActiveWindow() { ); } + /** Saves the current browser URL to the context store under the key {@code currentUrl}. */ @Given("Save current url to context") public void saveCurrentUrl() { String currentUrl = webInteractions.driver.getCurrentUrl(); @@ -230,6 +253,10 @@ public void saveCurrentUrl() { log.info("Current URL is saved to context " + currentUrl); } + /** + * @param width the window width in pixels + * @param height the window height in pixels + */ @Given("Set window width & height as {} & {}") public void setFrameSize(Integer width, Integer height) { webInteractions.setWindowSize(width, height); @@ -237,21 +264,28 @@ public void setFrameSize(Integer width, Integer height) { // ─── Storage ──────────────────────────────────────────────────────── + /** @param valueTable the key-value pairs to add to local storage */ @Given("Add the following values to LocalStorage:") public void addLocalStorageValues(DataTable valueTable) { webInteractions.addLocalStorageValues(valueTable.asMap()); } + /** @param cookieTable the cookie name-value pairs to add */ @Given("Add the following cookies:") public void addCookies(DataTable cookieTable) { webInteractions.addCookies(cookieTable.asMap()); } + /** + * @param cookieValue the new cookie value + * @param cookieName the name of the cookie to update + */ @Given("Update value to {} for cookie named {}") public void updateCookie(String cookieValue, String cookieName) { webInteractions.updateCookies(cookieValue, cookieName); } + /** Deletes all browser cookies. */ @Given("Delete cookies") public void deleteCookies() { webInteractions.driver.manage().deleteAllCookies(); @@ -259,34 +293,58 @@ public void deleteCookies() { // ─── Click ────────────────────────────────────────────────────────── + /** + * @param buttonName the name of the element to click + * @param pageName the page object containing the element + */ @Given("^(?:Click|Tap) the (\\w+) on the (\\w+)$") public void click(String buttonName, String pageName) { WebElement element = getElementRepository().acquireElementFromPage(buttonName, pageName); getInteractions(element).clickElement(element, buttonName, pageName, !isPlatformElement(element)); } + /** + * @param text the visible text of the button to click + * @param driverType the driver type to use (mobile or web), or null for auto-detect + */ @Given("^(?:Click|Tap) button with (.+?(?:\\s+.+?)*) text(?: using (mobile|web) driver)?$") public void clickWithText(String text, String driverType) { getInteractions(getType(driverType)).clickByText(text); } + /** @param text the CSS selector of the button to click */ @Given("Click button with {} css locator") public void clickWithLocator(String text) { webInteractions.clickByCssSelector(text); } + /** + * @param elementName the name of the listed element to click + * @param listName the name of the element list + * @param pageName the page object containing the list + */ @Given("^(?:Click|Tap) listed element (.+?(?:\\s+.+?)*) from (\\w+) list on the (\\w+)$") public void clickListedButton(String elementName, String listName, String pageName) { WebElement element = getElementRepository().acquireListedElementFromPage(elementName, listName, pageName); getInteractions(element).clickElement(element, elementName, pageName); } + /** + * @param attributeValue the attribute value to match + * @param attributeName the attribute name to match against + * @param listName the name of the element list + * @param pageName the page object containing the list + */ @Given("^Click listed attribute element that has (.+?(?:\\s+.+?)*) value for its (\\w+) attribute from (\\w+) list on the (\\w+)$") public void clickListedButtonByAttribute(String attributeValue, String attributeName, String listName, String pageName) { WebElement element = getElementRepository().acquireListedElementByAttribute(attributeName, attributeValue, listName, pageName); getInteractions(element).clickElement(element, attributeName + " attribute named element", pageName); } + /** + * @param elementName the name of the element to click if present + * @param pageName the page object containing the element + */ @Given("^If present, click the (\\w+) on the (\\w+)$") public void clickIfPresent(String elementName, String pageName) { try { @@ -298,6 +356,10 @@ public void clickIfPresent(String elementName, String pageName) { } } + /** + * @param elementName the name of the element to click if enabled + * @param pageName the page object containing the element + */ @Given("^If enabled, (?:click|tap) the (\\w+) on the (\\w+)$") public void clickIfEnabled(String elementName, String pageName) { try { @@ -309,12 +371,21 @@ public void clickIfEnabled(String elementName, String pageName) { } } + /** + * @param elementName the name of the element to click towards + * @param pageName the page object containing the element + */ @Given("^Click towards the (\\w+) on the (\\w+)$") public void clickTowardsElement(String elementName, String pageName) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); getInteractions(element).clickTowards(element, elementName, pageName); } + /** + * @param elementName the name of the element inside the iframe to click + * @param iframeName the name of the iframe element + * @param pageName the page object containing the elements + */ @Given("Click i-frame element {} in {} on the {}") public void clickIframeElement(String elementName, String iframeName, String pageName) { WebElement iframe = getElementRepository().acquireElementFromPage(iframeName, pageName); @@ -324,6 +395,12 @@ public void clickIframeElement(String elementName, String iframeName, String pag // ─── Input ────────────────────────────────────────────────────────── + /** + * @param inputName the name of the input element + * @param pageName the page object containing the input + * @param verify verification mode (verified, un-verified, or null) + * @param input the text to fill into the input + */ @Given("^Fill input (\\w+) on the (\\w+) with (?:(un-verified|verified) )?text: (.+?(?:\\s+.+?)*)$") public void fill(String inputName, String pageName, String verify, String input) { input = contextCheck(input); @@ -340,6 +417,11 @@ public void fill(String inputName, String pageName, String verify, String input) ); } + /** + * @param pageName the page object containing the form inputs + * @param driverType the driver type to use (mobile or web), or null for auto-detect + * @param formInputs the list of form input specifications + */ @Given("^Fill form input on the (\\w+)(?: using (mobile|web) driver)?$") public void fillForm(String pageName, String driverType, List formInputs) { List> inputBundles = getElementRepository().acquireElementList(formInputs, pageName); @@ -349,6 +431,11 @@ public void fillForm(String pageName, String driverType, List formInp interactions.fillForm(inputBundles, pageName); } + /** + * @param optionText the visible text of the option to select + * @param elementName the name of the select element + * @param pageName the page object containing the select element + */ @Given("^Select option (.+?(?:\\s+.+?)*) from (\\w+) on the (\\w+)$") public void selectOption(String optionText, String elementName, String pageName) { optionText = contextCheck(optionText); @@ -358,6 +445,12 @@ public void selectOption(String optionText, String elementName, String pageName) highlighted(BLUE, elementName) + highlighted(GRAY, " on ") + highlighted(BLUE, pageName)); } + /** + * @param inputName the name of the listed input element + * @param listName the name of the element list + * @param pageName the page object containing the list + * @param input the text to fill into the input + */ @Given("^Fill listed input (\\w+) from (\\w+) list on the (\\w+) with text: (.+?(?:\\s+.+?)*)$") public void fillListedInput(String inputName, String listName, String pageName, String input) { WebElement inputElement = getElementRepository().acquireListedElementFromPage(inputName, listName, pageName); @@ -373,6 +466,12 @@ public void fillListedInput(String inputName, String listName, String pageName, ); } + /** + * @param inputName the name of the input element inside the iframe + * @param iframeName the name of the iframe element + * @param pageName the page object containing the elements + * @param inputText the text to fill into the input + */ @Given("Fill iFrame element {} of {} on the {} with text: {}") public void fillIframeInput(String inputName, String iframeName, String pageName, String inputText) { WebElement iframe = getElementRepository().acquireElementFromPage(iframeName, pageName); @@ -382,28 +481,50 @@ public void fillIframeInput(String inputName, String iframeName, String pageName // ─── Scroll / Center ──────────────────────────────────────────────── + /** + * @param direction the scroll direction + * @param driverType the driver type to use (mobile or web) + */ @Given("^(?:Scroll|Swipe) (up|down|left|right) using (mobile|web) driver$") public void scrollTo(Direction direction, String driverType) { getInteractions(getType(driverType)).scrollInDirection(direction); } + /** + * @param elementText the text of the element to find + * @param listName the name of the element list to scroll through + * @param screenName the page object containing the list + */ @Given("^(?:Scroll|Swipe) until listed (.+?(?:\\s+.+?)*) element from (\\w+) list is found on the (\\w+)$") public void swipeUntilElementFound(String elementText, String listName, String screenName) { List elements = getElementRepository().acquireElementsFromPage(listName, screenName); getInteractions(elements.get(0)).scrollInList(elementText, elements); } + /** + * @param elementText the exact text of the element to find + * @param driverType the driver type to use (mobile or web) + */ @Given("^(?:Scroll|Swipe) until element with exact text (.+?(?:\\s+.+?)*) is found using (web|mobile) driver$") public void swipeUntilElementFound(String elementText, String driverType) { getInteractions(getType(driverType)).scrollUntilFound(elementText); } + /** + * @param elementName the name of the element to center + * @param pageName the page object containing the element + */ @Given("Center the {} on the {}") public void center(String elementName, String pageName) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); webInteractions.centerElement(element, elementName, pageName); } + /** + * @param elementName the name of the listed element to center + * @param elementListName the name of the element list + * @param pageName the page object containing the list + */ @Given("Center element named {} on the {} from {}") public void centerListedElement(String elementName, String elementListName, String pageName) { elementName = contextCheck(elementName); @@ -413,6 +534,11 @@ public void centerListedElement(String elementName, String elementListName, Stri // ─── Verification ─────────────────────────────────────────────────── + /** + * @param elementName the name of the element to verify + * @param pageName the page object containing the element + * @param expectedText the expected text content + */ @Given("^Verify the text of (\\w+) on the (\\w+) to be: (.+?(?:\\s+.+?)*)$") public void verifyText(String elementName, String pageName, String expectedText) { expectedText = contextCheck(expectedText); @@ -422,6 +548,11 @@ public void verifyText(String elementName, String pageName, String expectedText) getInteractions(element).verifyText(element, elementName, pageName, expectedText); } + /** + * @param elementName the name of the element to verify + * @param pageName the page object containing the element + * @param expectedText the text expected to be contained + */ @Given("^Verify the text of (\\w+) on the (\\w+) contains: (.+?(?:\\s+.+?)*)$") public void verifyContainsText(String elementName, String pageName, String expectedText) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); @@ -430,6 +561,11 @@ public void verifyContainsText(String elementName, String pageName, String expec getInteractions(element).verifyElementContainsText(element, elementName, pageName, expectedText); } + /** + * @param elementName the name of the element to verify absence of + * @param pageName the page object containing the element + * @param driverType the driver type to use (mobile or web), or null for auto-detect + */ @Given("^Verify absence of element (\\w+) on the (\\w+)(?: using (mobile|web) driver)?$") public void verifyAbsence(String elementName, String pageName, String driverType) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); @@ -439,18 +575,33 @@ public void verifyAbsence(String elementName, String pageName, String driverType interactions.verifyElementState(element, elementName, pageName, ElementState.absent); } + /** + * @param elementName the name of the element to verify presence of + * @param pageName the page object containing the element + */ @Given("^Verify presence of element (\\w+) on the (\\w+)$") public void verifyPresence(String elementName, String pageName) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); getInteractions(element).verifyElementState(element, elementName, pageName, ElementState.displayed); } + /** + * @param elementName the name of the element to verify + * @param pageName the page object containing the element + * @param expectedState the expected element state + */ @Given("^Verify that element (\\w+) on the (\\w+) is in (\\w+) state$") public void verifyState(String elementName, String pageName, ElementState expectedState) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); getInteractions(element).verifyElementState(element, elementName, pageName, expectedState); } + /** + * @param elementName the name of the element to verify + * @param pageName the page object containing the element + * @param attributeValue the expected attribute value + * @param attributeName the name of the attribute to check + */ @Given("^Verify that element (\\w+) on the (\\w+) has (.+?(?:\\s+.+?)*) value for its (.+?(?:\\s+.+?)*) attribute$") public void verifyElementContainsAttribute( String elementName, @@ -461,6 +612,12 @@ public void verifyElementContainsAttribute( getInteractions(element).verifyElementContainsAttribute(element, elementName, pageName, attributeName, attributeValue); } + /** + * @param attributeName the name of the attribute to check + * @param elementName the name of the element to verify + * @param pageName the page object containing the element + * @param value the value expected to be contained in the attribute + */ @Given("^Verify that (\\w+) attribute of element (\\w+) on the (\\w+) contains (.+?(?:\\s+.+?)*) value") public void verifyElementAttributeContainsValue( String attributeName, @@ -473,6 +630,12 @@ public void verifyElementAttributeContainsValue( log.info("-> " + markup(BLUE, value)); } + /** + * @param attributeName the CSS attribute name to check + * @param elementName the name of the element to verify + * @param pageName the page object containing the element + * @param attributeValue the expected CSS attribute value + */ @Given("Verify {} css attribute of element {} on the {} is {}") public void verifyElementColor( String attributeName, @@ -483,6 +646,13 @@ public void verifyElementColor( webInteractions.verifyElementColor(element, attributeName, elementName, pageName, attributeValue); } + /** + * @param elementName the name of the listed element to verify + * @param listName the name of the element list + * @param pageName the page object containing the list + * @param attributeValue the expected attribute value + * @param attributeName the name of the attribute to check + */ @Given("^Verify that element ([A-Za-z0-9 ]+) from (\\w+) list on the (\\w+) has (.+?(?:\\s+.+?)*) value for its (\\w+) attribute$") public void verifyListedElementContainsAttribute( String elementName, @@ -494,6 +664,12 @@ public void verifyListedElementContainsAttribute( getInteractions(element).verifyElementContainsAttribute(element, elementName, pageName, attributeName, attributeValue); } + /** + * @param elementName the partial text of the listed element to select + * @param listName the name of the element list + * @param pageName the page object containing the list + * @param expectedText the text expected to be contained in the element + */ @Given("^Select listed element containing partial text (.+?(?:\\s+.+?)*) from the (\\w+) on the (\\w+) and verify its text contains (.+?(?:\\s+.+?)*)$") public void verifyListedElementContainsText( String elementName, @@ -504,6 +680,11 @@ public void verifyListedElementContainsText( getInteractions(element).verifyElementContainsText(element, elementName, pageName, expectedText); } + /** + * @param listName the name of the element list to verify + * @param pageName the page object containing the list + * @param expectedText the text expected to be contained in each element + */ @Given("Perform text verification for listed elements of {} list on the {} contains {}") public void textVerificationForListedElement( String listName, @@ -524,6 +705,7 @@ public void textVerificationForListedElement( } } + /** @param text the text expected to be contained in the current URL */ @Given("Verify the page is redirecting to the page {}") @Given("Verify the url contains with the text {}") public void verifyTextUrl(String text) { @@ -533,6 +715,10 @@ public void verifyTextUrl(String text) { // ─── Assertions ───────────────────────────────────────────────────── + /** + * @param expectedValue the expected value + * @param actualValue the actual value to compare against + */ @Given("Assert that value of {} is equal to {}") public void verifyText(String expectedValue, String actualValue) { log.info("Checking values..."); @@ -542,6 +728,10 @@ public void verifyText(String expectedValue, String actualValue) { log.success("Values verified as: " + actualValue); } + /** + * @param expectedValue the value expected to be contained + * @param actualValue the actual value to check against + */ @Given("Assert that value of {} is contains {}") public void assertContains(String expectedValue, String actualValue) { log.info("Checking values..."); @@ -551,6 +741,10 @@ public void assertContains(String expectedValue, String actualValue) { else throw new PickleibVerificationException("'" + actualValue + "' not contains '" + expectedValue + "'"); } + /** + * @param expectedValue the value expected to differ + * @param actualValue the actual value to compare against + */ @Given("Assert that value of {} is not equal to {}") public void verifyNoText(String expectedValue, String actualValue) { log.info("Checking values..."); @@ -560,6 +754,12 @@ public void verifyNoText(String expectedValue, String actualValue) { log.success("Values verified as: " + actualValue); } + /** + * @param attributeName the attribute name to check + * @param elementName the name of the element + * @param pageName the page object containing the element + * @param actualValue the expected attribute value + */ @Given("Assert the value of {} attribute for {} element on {} is equal to {}") public void assertAttribute(String attributeName, String elementName, String pageName, String actualValue) { log.info("Acquiring the" + attributeName + " value..."); @@ -571,11 +771,17 @@ public void assertAttribute(String attributeName, String elementName, String pag // ─── Wait ─────────────────────────────────────────────────────────── + /** @param duration the number of seconds to wait */ @Given("^Wait (\\d+) seconds$") public void wait(double duration) { PolymorphicUtilities.waitFor(duration); } + /** + * @param elementName the name of the element to wait for absence of + * @param pageName the page object containing the element + * @param driverType the driver type to use (mobile or web), or null for auto-detect + */ @Given("^Wait for absence of element (\\w+) on the (\\w+)(?: using (mobile|web) driver)?$") public void waitUntilAbsence(String elementName, String pageName, String driverType) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); @@ -585,12 +791,22 @@ public void waitUntilAbsence(String elementName, String pageName, String driverT interactions.waitUntilAbsence(element, elementName, pageName); } + /** + * @param elementName the name of the element to wait for + * @param pageName the page object containing the element + */ @Given("^Wait for element (\\w+) on the (\\w+) to be visible$") public void waitUntilVisible(String elementName, String pageName) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); getInteractions(element).waitUntilVisible(element, elementName, pageName); } + /** + * @param elementName the name of the element to wait for + * @param pageName the page object containing the element + * @param attributeValue the expected attribute value + * @param attributeName the name of the attribute to check + */ @Given("^Wait until element (\\w+) on the (\\w+) has (.+?(?:\\s+.+?)*) value for its (\\w+) attribute$") public void waitUntilElementContainsAttribute( String elementName, @@ -607,6 +823,11 @@ public void waitUntilElementContainsAttribute( // ─── Attribute ────────────────────────────────────────────────────── + /** + * @param attributeName the name of the attribute to acquire + * @param elementName the name of the element + * @param pageName the page object containing the element + */ @Given("^Acquire the (\\w+) attribute of (\\w+) on the (\\w+)$") public void getAttributeValue(String attributeName, String elementName, String pageName) { WebElement element = getElementRepository().acquireElementFromPage(elementName, pageName); @@ -615,6 +836,11 @@ public void getAttributeValue(String attributeName, String elementName, String p // ─── File Upload ──────────────────────────────────────────────────── + /** + * @param inputName the name of the file input element + * @param pageName the page object containing the input + * @param path the file path to upload + */ @Given("Upload file on input {} on the {} with file: {}") public void uploadFile(String inputName, String pageName, String path) { WebElement inputElement = getElementRepository().acquireElementFromPage(inputName, pageName); @@ -623,11 +849,16 @@ public void uploadFile(String inputName, String pageName, String path) { // ─── JavaScript ───────────────────────────────────────────────────── + /** @param script the JavaScript command to execute */ @Given("Execute JS command: {}") public void executeJSCommand(String script) { webInteractions.executeJSCommand(script); } + /** + * @param script the JavaScript to execute on the element + * @param elementText the visible text of the target element + */ @Given("Execute script {string} on element with text {string}") public void executeScript(String script, String elementText) { WebElement element = webInteractions.getElementContainingText(elementText); @@ -636,11 +867,18 @@ public void executeScript(String script, String elementText) { // ─── Mobile ───────────────────────────────────────────────────────── + /** @param command the mobile editor action to perform */ @Given("Execute mobile editor command: {}") public void executeMobileEditCommand(String command) { PickleibAppiumDriver.get().executeScript("mobile:performEditorAction", ImmutableMap.of("action", command)); } + /** + * @param command the mobile command to execute + * @param parameter the parameter key for the command + * @param elementName the name of the target element + * @param pageName the page object containing the element + */ @Given("Execute {} mobile command with {} parameter for {} from {}") public void executeGenericMobileCommand(String command, String parameter, String elementName, String pageName) { Map params = new HashMap<>(); @@ -652,12 +890,21 @@ public void executeGenericMobileCommand(String command, String parameter, String // ─── Event Listening ──────────────────────────────────────────────── + /** + * @param eventName the event name to listen for + * @param objectScript the object script to print + */ @Given("Listen to {} event & print {} object") public void listenGetAndPrintObjectStep(String eventName, String objectScript) { String listenerScript = "_ddm.listen(" + eventName + ");"; webInteractions.listenGetAndPrintObject(listenerScript, eventName, objectScript); } + /** + * @param eventName the event name to listen for + * @param nodeSource the node source to verify + * @param expectedValue the expected value of the node + */ @Given("Listen to {} event & verify value of {} node is {}") public void listenGetAndVerifyObjectStep(String eventName, String nodeSource, String expectedValue) { log.info("Verifying value of '" + nodeSource + "' node"); @@ -665,6 +912,10 @@ public void listenGetAndVerifyObjectStep(String eventName, String nodeSource, St webInteractions.listenGetAndVerifyObject(listenerScript, eventName, nodeSource, expectedValue); } + /** + * @param eventName the event name to listen for + * @param nodeTable the data table of node-value pairs to verify + */ @Given("Listen to {} event & verify values of the following nodes") public void listenGetAndVerifyObjectStep(String eventName, DataTable nodeTable) { String listenerScript = "_ddm.listen(" + eventName + ");"; @@ -673,6 +924,11 @@ public void listenGetAndVerifyObjectStep(String eventName, DataTable nodeTable) // ─── String Replacement ───────────────────────────────────────────── + /** + * @param attributeText the context value to perform replacement on + * @param splitValue the substring to remove + * @param attributeName the context key to store the result + */ @Given("Perform text replacement on {} context by replacing {} value in {}") public void replaceAttributeValue(String attributeText, String splitValue, String attributeName) { attributeText = contextCheck(attributeText); @@ -684,6 +940,11 @@ public void replaceAttributeValue(String attributeText, String splitValue, Strin // ─── Element Bundle Interaction ───────────────────────────────────── + /** + * @param pageName the page object containing the elements + * @param driverType the driver type to use (mobile or web) + * @param specifications the data table of element interaction specifications + */ @Given("^Interact with element on the (\\w+) of (mobile|web) driver?$") public void pageElementInteraction(String pageName, String driverType, DataTable specifications) { List>> bundles = getElementRepository().acquireElementBundlesFromPage( diff --git a/src/main/java/pickleib/utilities/RetryPolicy.java b/src/main/java/pickleib/utilities/RetryPolicy.java index d7a323a9..13d6bf25 100644 --- a/src/main/java/pickleib/utilities/RetryPolicy.java +++ b/src/main/java/pickleib/utilities/RetryPolicy.java @@ -20,6 +20,9 @@ public class RetryPolicy { /** * Retries a void action until it succeeds or the timeout is reached. * Throws PickleibException wrapping the last caught exception on timeout. + * + * @param action the action to retry + * @param timeoutMs maximum time in milliseconds */ public static void execute(Runnable action, long timeoutMs) { execute(() -> { action.run(); return null; }, timeoutMs); @@ -28,6 +31,11 @@ public static void execute(Runnable action, long timeoutMs) { /** * Retries a supplier action until it returns a value or the timeout is reached. * Throws PickleibException wrapping the last caught exception on timeout. + * + * @param the return type + * @param action the supplier action to retry + * @param timeoutMs maximum time in milliseconds + * @return the result of the supplier */ public static T execute(Supplier action, long timeoutMs) { long startTime = System.currentTimeMillis(); @@ -51,6 +59,10 @@ public static T execute(Supplier action, long timeoutMs) { /** * Polls until a condition returns true or the timeout is reached. * Returns false on timeout (does not throw). + * + * @param condition the condition to poll + * @param timeoutMs maximum time in milliseconds + * @return true if the condition was met, false on timeout */ public static boolean pollUntil(BooleanSupplier condition, long timeoutMs) { return pollUntil(condition, timeoutMs, null, null, null); diff --git a/src/main/java/pickleib/utilities/Utilities.java b/src/main/java/pickleib/utilities/Utilities.java index 6032ef2e..d30a6cc3 100644 --- a/src/main/java/pickleib/utilities/Utilities.java +++ b/src/main/java/pickleib/utilities/Utilities.java @@ -46,22 +46,39 @@ @SuppressWarnings({"unused", "UnusedReturnValue"}) public abstract class Utilities { + /** JSON object mapper instance. */ public ObjectMapper objectMapper = new ObjectMapper(); + /** Logger instance. */ public Printer log = new Printer(this.getClass()); + /** The WebDriver instance used for browser interactions. */ public RemoteWebDriver driver; + /** Fluent wait instance configured for element polling. */ public FluentWait wait; + /** Scroll function used to bring elements into view. */ public ScrollFunction scroller; + /** Timeout in milliseconds for element-level waits. */ @ContextValue(value = "element-timeout", defaultValue = "15000") public long elementTimeout; + /** Timeout in milliseconds for driver-level waits. */ @ContextValue(value = "driver-timeout", defaultValue = "15000") public long driverTimeout; + /** Helper for click interactions. */ protected ClickHelper clickHelper; + /** Helper for input interactions. */ protected InputHelper inputHelper; + /** Helper for element state checks and verifications. */ protected ElementStateHelper elementStateHelper; + /** Helper for drag-and-drop interactions. */ protected DragDropHelper dragDropHelper; + /** + * Constructs a Utilities instance with an explicit FluentWait. + * + * @param driver the RemoteWebDriver instance + * @param wait the pre-configured FluentWait instance + */ public Utilities(RemoteWebDriver driver, FluentWait wait) { ContextValueInjector.injectFields(this); this.driverTimeout = this.driverTimeout / 1000; @@ -73,6 +90,12 @@ public Utilities(RemoteWebDriver driver, FluentWait wait) { this.dragDropHelper = new DragDropHelper(driver); } + /** + * Constructs a Utilities instance with a scroll function, creating a default FluentWait. + * + * @param driver the RemoteWebDriver instance + * @param scroller the scroll function for bringing elements into view + */ public Utilities(RemoteWebDriver driver, ScrollFunction scroller) { ContextValueInjector.injectFields(this); this.driverTimeout = this.driverTimeout / 1000; @@ -117,6 +140,12 @@ public String getAttribute(WebElement element, String attribute) { */ public void clickElement(WebElement element, boolean scroll) { clickHelper.clickElement(element, scroll); } + /** + * Checks whether the given element is within the browser viewport. + * + * @param element the element to check + * @return {@code true} if the element is fully within the viewport + */ public boolean isElementInViewPort(WebElement element) { int windowHeight = driver.manage().window().getSize().getHeight(); int windowWidth = driver.manage().window().getSize().getWidth(); @@ -161,6 +190,7 @@ public boolean isElementInViewPort(WebElement element) { /** * Press {target key} key on {element name} element of the {} * + * @param element the target web element * @param keys target keys * @param elementName target element name * @param pageName specified page instance name @@ -219,6 +249,7 @@ public void fillAndVerifyInput(WebElement inputElement, String inputText) { * * @param inputElement target input element * @param inputText input text + * @param scroll whether to scroll to the element before filling */ public void fillAndVerifyInput(WebElement inputElement, String inputText, boolean scroll) { inputHelper.fillAndVerifyInput(inputElement, inputText, scroll); @@ -273,6 +304,7 @@ public void fillInputElement(WebElement inputElement, String inputText, boolean * * @param inputElement target input element * @param inputText input text + * @param scroll whether to scroll to the element before filling * @param clear If true, clears the input field before entering text. If false, does not clear. * @param verify verifies the input text value equals to an expected text if true */ @@ -363,6 +395,7 @@ public void clickButtonWithText(String buttonText, boolean scroll) { * Clears an input element * * @param element target element + * @return the cleared element */ public WebElement clearInputField(@NotNull WebElement element) { return inputHelper.clearInputField(element); @@ -372,6 +405,7 @@ public WebElement clearInputField(@NotNull WebElement element) { * Acquires an element by its text * * @param elementText target element text + * @return the located WebElement */ public WebElement waitAndGetElementByText(String elementText) { try { @@ -388,6 +422,7 @@ public WebElement waitAndGetElementByText(String elementText) { * Acquires an element by its text * * @param elementText target element text + * @return the located WebElement, or {@code null} if not found */ public WebElement getElementByText(String elementText) { String queryAttribute = getTextAttributeNameFor(getDriverPlatform(driver)); @@ -410,6 +445,7 @@ public WebElement getElementByText(String elementText) { * Acquires an element that contains a certain text * * @param elementText target element text + * @return the located WebElement */ public WebElement getElementContainingText(String elementText) { try { @@ -488,6 +524,7 @@ public void uploadFile(@NotNull WebElement fileUploadInput, String directory, St * Combines the given keys * * @param keys key inputs + * @return the combined key chord string */ public String combineKeys(Keys... keys) { return Keys.chord(keys); @@ -628,6 +665,8 @@ public void verifyElementText(WebElement element, String expectedText) { * Verify the text of {element name} on the {page name} to be: {expected text} * * @param element target element + * @param elementName the name of the target element + * @param pageName specified page instance name * @param expectedText expected text */ public void verifyElementContainsText(WebElement element, String elementName, String pageName, String expectedText) { @@ -637,6 +676,7 @@ public void verifyElementContainsText(WebElement element, String elementName, St /** * Verify the text of an element from the list on the {page name} * + * @param bundles list of element bundles containing elements and their expected texts * @param pageName specified page instance name */ public void verifyListedElementText( @@ -648,7 +688,10 @@ public void verifyListedElementText( /** * Verify the text of an element from the list on the {page name} * - * @param pageName specified page instance name + * @param elements the list of elements to search + * @param expectedText the expected text to find in the list + * @param listName the name of the element list + * @param pageName specified page instance name */ public void verifyListContainsElementByText( List elements, @@ -674,6 +717,7 @@ public void fillInputForm(List> bundles, String pageName) * @param element target element * @param attributeValue expected attribute value * @param attributeName target attribute name + * @return {@code true} if the element contains the specified attribute value */ public boolean elementContainsAttribute( WebElement element, @@ -688,6 +732,7 @@ public boolean elementContainsAttribute( * @param elementName the name of the element to be verified * @param attributeName the name of the attribute to be verified * @param value the expected part of value of the attribute + * @return {@code true} if the attribute contains the specified value */ public boolean elementAttributeContainsValue( WebElement elementName, diff --git a/src/main/java/pickleib/utilities/element/ElementBundle.java b/src/main/java/pickleib/utilities/element/ElementBundle.java index b926988e..fab98233 100644 --- a/src/main/java/pickleib/utilities/element/ElementBundle.java +++ b/src/main/java/pickleib/utilities/element/ElementBundle.java @@ -2,5 +2,14 @@ import org.openqa.selenium.WebElement; +/** + * Groups a {@link WebElement} with its metadata and associated data payload. + * + * @param element the web element + * @param elementName the element's name in the repository + * @param platform the target platform + * @param data additional data associated with the element + * @param the type of the data payload + */ public record ElementBundle(WebElement element, String elementName, String platform, Data data) { } \ No newline at end of file diff --git a/src/main/java/pickleib/utilities/element/FormInput.java b/src/main/java/pickleib/utilities/element/FormInput.java index 5a093c16..35a89223 100644 --- a/src/main/java/pickleib/utilities/element/FormInput.java +++ b/src/main/java/pickleib/utilities/element/FormInput.java @@ -1,3 +1,9 @@ package pickleib.utilities.element; +/** + * A form input pair mapping an element name to its input value. + * + * @param element the element name + * @param input the input value + */ public record FormInput(String element, String input) {} diff --git a/src/main/java/pickleib/utilities/element/acquisition/design/PageObjectJson.java b/src/main/java/pickleib/utilities/element/acquisition/design/PageObjectJson.java index 61ef8f7e..ffdb528b 100644 --- a/src/main/java/pickleib/utilities/element/acquisition/design/PageObjectJson.java +++ b/src/main/java/pickleib/utilities/element/acquisition/design/PageObjectJson.java @@ -486,6 +486,9 @@ public final List getElementsByAttributes( *
* Example output: {@code [type='submit'][class='btn']} *

+ * + * @param attributePairs pairs of attribute name and value + * @return the generated CSS selector string */ @SafeVarargs public final String generateCssByAttributes(Pair... attributePairs){ @@ -508,6 +511,9 @@ public final String generateCssByAttributes(Pair... attributePai *
* Example output: {@code //*[@type='submit']} *

+ * + * @param attributePairs pairs of attribute name and value + * @return the generated XPath selector string */ @SafeVarargs public final String generateXPathByAttributes(Pair... attributePairs){ @@ -585,6 +591,9 @@ public JsonObject getPageJson(String pageName, JsonObject objectRepository) { /** * Helper method to get the correct driver instance (Web vs Appium) based on the "platform" key in the page JSON. + * + * @param pageJson the page JSON object containing a "platform" key + * @return the active driver instance for the page's platform */ public RemoteWebDriver getDriverForPage(JsonObject pageJson) { DriverFactory.DriverType driverType = DriverFactory.DriverType.getType( @@ -598,6 +607,9 @@ public RemoteWebDriver getDriverForPage(JsonObject pageJson) { /** * Helper method to return the active driver instance for a specific driver type. + * + * @param driverType the driver type to get the instance for + * @return the active driver instance */ public RemoteWebDriver getDriverForType(DriverFactory.DriverType driverType){ switch (driverType){ @@ -613,6 +625,9 @@ public RemoteWebDriver getDriverForType(DriverFactory.DriverType driverType){ /** * Helper method to get the correct FluentWait instance based on the "platform" key in the page JSON. + * + * @param pageJson the page JSON object containing a "platform" key + * @return the FluentWait instance for the page's platform */ public FluentWait getWaitForPage(JsonObject pageJson) { DriverFactory.DriverType driverType = DriverFactory.DriverType.getType( @@ -626,6 +641,9 @@ public FluentWait getWaitForPage(JsonObject pageJson) { /** * Helper method to return the active FluentWait instance for a specific driver type. + * + * @param driverType the driver type to get the wait instance for + * @return the active FluentWait instance */ public FluentWait getWaitForType(DriverFactory.DriverType driverType){ switch (driverType){ diff --git a/src/main/java/pickleib/utilities/element/interactions/InteractionBase.java b/src/main/java/pickleib/utilities/element/interactions/InteractionBase.java index 331fb77f..4d3e8480 100644 --- a/src/main/java/pickleib/utilities/element/interactions/InteractionBase.java +++ b/src/main/java/pickleib/utilities/element/interactions/InteractionBase.java @@ -29,6 +29,7 @@ public class InteractionBase { */ public DriverFactory.DriverType defaultPlatform = DriverFactory.DriverType.selenium; + /** Logger instance for this class. */ public Printer log = new Printer(this.getClass()); /** diff --git a/src/main/java/pickleib/utilities/helpers/ClickHelper.java b/src/main/java/pickleib/utilities/helpers/ClickHelper.java index cba6e280..ea72ee7e 100644 --- a/src/main/java/pickleib/utilities/helpers/ClickHelper.java +++ b/src/main/java/pickleib/utilities/helpers/ClickHelper.java @@ -73,6 +73,9 @@ public void clickButtonIfPresent(WebElement element) { * Clicks element if present. Only catches NoSuchElementException and StaleElementReferenceException * (directly or wrapped in PickleibException by RetryPolicy). * Other WebDriverExceptions (session-not-created, etc.) propagate. + * + * @param element the element to click + * @param scroll if true, scrolls to the element before clicking */ public void clickButtonIfPresent(WebElement element, boolean scroll) { try { @@ -119,6 +122,8 @@ public void clickIfPresent(WebElement element) { /** * Waits for the element to be visible, then clicks at its center coordinates. * Preserves the visibility check from the original Utilities.clickTowards. + * + * @param element the element to click towards */ public void clickTowards(WebElement element) { wait.until(ExpectedConditions.visibilityOf(element)); diff --git a/src/main/java/pickleib/utilities/interfaces/PolymorphicUtilities.java b/src/main/java/pickleib/utilities/interfaces/PolymorphicUtilities.java index f0627708..574c4a3c 100644 --- a/src/main/java/pickleib/utilities/interfaces/PolymorphicUtilities.java +++ b/src/main/java/pickleib/utilities/interfaces/PolymorphicUtilities.java @@ -250,6 +250,7 @@ public interface PolymorphicUtilities { * Clears an input element * * @param element target element + * @return returns the cleared element */ WebElement clearInputField(@NotNull WebElement element); @@ -259,6 +260,7 @@ public interface PolymorphicUtilities { * @param element target element * @param elementName target element name * @param pageName specified page instance name + * @return returns the cleared element */ WebElement clearInputField(@NotNull WebElement element, String elementName, String pageName); @@ -266,6 +268,7 @@ public interface PolymorphicUtilities { * Acquires an element by its text * * @param elementText target element text + * @return returns the element matching the text */ WebElement getElementByText(String elementText); @@ -274,6 +277,7 @@ public interface PolymorphicUtilities { * * @param elementText target element text * @param pageName specified page instance name + * @return returns the element matching the text */ WebElement getElementByText(String elementText, String pageName); @@ -281,6 +285,7 @@ public interface PolymorphicUtilities { * Acquires an element that contains a certain text * * @param elementText target element text + * @return returns the element containing the text */ WebElement getElementContainingText(String elementText); @@ -289,6 +294,7 @@ public interface PolymorphicUtilities { * * @param elementText target element text * @param pageName specified page instance name + * @return returns the element containing the text */ WebElement getElementContainingText(String elementText, String pageName); @@ -401,6 +407,7 @@ public interface PolymorphicUtilities { * Combines the given keys * * @param keys key inputs + * @return returns the combined key string */ String combineKeys(Keys... keys); @@ -529,8 +536,10 @@ static void waitFor(double seconds) { /** * Verifies the text of an element from a list on the {page name}. * - * @param elements list of elements - * @param pageName specified page instance name + * @param elements list of elements + * @param expectedText expected element text + * @param listName target list name + * @param pageName specified page instance name */ void verifyListContainsElementByText( List elements, @@ -591,6 +600,7 @@ void verifyListContainsElementByText( /** * Verifies that an attribute {attribute name} of element {element name} on the {page name} contains a specific {value}. * + * @param element target element * @param attributeName the name of the attribute to be verified * @param elementName the name of the element to be verified * @param pageName the name of the page containing the element @@ -613,6 +623,8 @@ void verifyListContainsElementByText( * Verifies the presence of listed element from a list on the {page name} * * @param bundles list that contains element, elementName, elementText + * @param element target element + * @param elements list of target elements * @param pageName specified page instance name * @param signForms table that has key as "Input" and value as "Input Element" (dataTable.asMaps()) */ @@ -629,6 +641,7 @@ void verifyListContainsElementByText( /** * Presses {target key} key on {element name} element of the {} * + * @param element target element * @param keys target key * @param elementName target element name * @param pageName specified page instance name @@ -655,7 +668,6 @@ void verifyListContainsElementByText( * Executes interactions on a list of element bundles, based on the specified interaction type. *

* The interaction type is specified in the "Interaction Type" key of the map contained in each element bundle. - *

* * @param bundles A list of element bundles containing the element name, the matching element, and a map of the element's attributes. * @param pageName The name of the page object. diff --git a/src/main/java/pickleib/utilities/interfaces/functions/ClickFunction.java b/src/main/java/pickleib/utilities/interfaces/functions/ClickFunction.java index 47363dda..d57b0b6e 100644 --- a/src/main/java/pickleib/utilities/interfaces/functions/ClickFunction.java +++ b/src/main/java/pickleib/utilities/interfaces/functions/ClickFunction.java @@ -2,7 +2,9 @@ import org.openqa.selenium.WebElement; +/** Functional interface for click operations on web elements. */ @FunctionalInterface public interface ClickFunction { + /** @param element the element to click */ void click(WebElement element); } diff --git a/src/main/java/pickleib/utilities/interfaces/functions/LocateElement.java b/src/main/java/pickleib/utilities/interfaces/functions/LocateElement.java index f9f5a9af..359d9f1f 100644 --- a/src/main/java/pickleib/utilities/interfaces/functions/LocateElement.java +++ b/src/main/java/pickleib/utilities/interfaces/functions/LocateElement.java @@ -2,7 +2,13 @@ import org.openqa.selenium.WebElement; +/** Functional interface for locating a {@link WebElement}. */ @FunctionalInterface public interface LocateElement { + /** + * Locates and returns a web element. + * + * @return the located {@link WebElement} + */ WebElement locate(); } diff --git a/src/main/java/pickleib/utilities/interfaces/functions/ScrollFunction.java b/src/main/java/pickleib/utilities/interfaces/functions/ScrollFunction.java index 97258c9a..2971e75d 100644 --- a/src/main/java/pickleib/utilities/interfaces/functions/ScrollFunction.java +++ b/src/main/java/pickleib/utilities/interfaces/functions/ScrollFunction.java @@ -2,7 +2,10 @@ import org.openqa.selenium.WebElement; +/** Functional interface for scroll operations that bring elements into view. */ @FunctionalInterface public interface ScrollFunction { + /** @param element the element to scroll into view + * @return the element after scrolling */ WebElement scroll(WebElement element); } diff --git a/src/main/java/pickleib/utilities/interfaces/repository/ElementRepository.java b/src/main/java/pickleib/utilities/interfaces/repository/ElementRepository.java index 49632e99..0343f544 100644 --- a/src/main/java/pickleib/utilities/interfaces/repository/ElementRepository.java +++ b/src/main/java/pickleib/utilities/interfaces/repository/ElementRepository.java @@ -22,6 +22,7 @@ */ public interface ElementRepository { + /** Shared logger instance for element repository implementations. */ Printer log = new Printer(ElementRepository.class); /** diff --git a/src/main/java/pickleib/utilities/interfaces/repository/PageObjectRepository.java b/src/main/java/pickleib/utilities/interfaces/repository/PageObjectRepository.java index b8c394bf..1556a5f8 100644 --- a/src/main/java/pickleib/utilities/interfaces/repository/PageObjectRepository.java +++ b/src/main/java/pickleib/utilities/interfaces/repository/PageObjectRepository.java @@ -1,5 +1,5 @@ package pickleib.utilities.interfaces.repository; +/** Symbolic marker interface for classes containing page objects. */ public interface PageObjectRepository { - //Symbolic interface for classes containing page objects. } diff --git a/src/main/java/pickleib/utilities/interfaces/repository/PageRepository.java b/src/main/java/pickleib/utilities/interfaces/repository/PageRepository.java index f5569758..238a5df6 100644 --- a/src/main/java/pickleib/utilities/interfaces/repository/PageRepository.java +++ b/src/main/java/pickleib/utilities/interfaces/repository/PageRepository.java @@ -17,5 +17,6 @@ */ public interface PageRepository { + /** @return the element repository for acquiring page-level elements */ ElementRepository getElementRepository(); } diff --git a/src/main/java/pickleib/utilities/screenshot/ScreenCaptureUtility.java b/src/main/java/pickleib/utilities/screenshot/ScreenCaptureUtility.java index 766b1ef0..f44053aa 100644 --- a/src/main/java/pickleib/utilities/screenshot/ScreenCaptureUtility.java +++ b/src/main/java/pickleib/utilities/screenshot/ScreenCaptureUtility.java @@ -8,6 +8,7 @@ import utils.Printer; import java.io.File; +/** Utility for capturing screenshots from WebDriver sessions. */ @SuppressWarnings("unused") public class ScreenCaptureUtility { static Printer log = new Printer(ScreenCaptureUtility.class); @@ -15,6 +16,7 @@ public class ScreenCaptureUtility { /** * Captures screen * @param name screenshot name + * @param extension file extension (e.g. ".png") * @param driver session driver * @return returns the screenshot file */ @@ -38,8 +40,9 @@ public static File captureScreen(String name, String extension, RemoteWebDriver } /** - * Captures screen + * Captures screen silently (no logging) * @param name screenshot name + * @param extension file extension (e.g. ".png") * @param driver session driver * @return returns the screenshot file */ diff --git a/src/main/java/pickleib/utilities/steps/design/PageObjectDesign.java b/src/main/java/pickleib/utilities/steps/design/PageObjectDesign.java index 96c24df4..6bc2f0b3 100644 --- a/src/main/java/pickleib/utilities/steps/design/PageObjectDesign.java +++ b/src/main/java/pickleib/utilities/steps/design/PageObjectDesign.java @@ -32,6 +32,8 @@ public class PageObjectDesign * * @param objectRepositoryClass The class of the object repository which will be used to initialize * the page object model, element interactions, and reflections. + * @param mobileDriverActive whether the mobile/Appium driver is active + * @param webDriverActive whether the web/Selenium driver is active */ public PageObjectDesign( Class objectRepositoryClass, diff --git a/src/main/java/pickleib/web/driver/PickleibWebDriver.java b/src/main/java/pickleib/web/driver/PickleibWebDriver.java index 90776aef..a0147723 100644 --- a/src/main/java/pickleib/web/driver/PickleibWebDriver.java +++ b/src/main/java/pickleib/web/driver/PickleibWebDriver.java @@ -34,6 +34,7 @@ public class PickleibWebDriver { */ private static final ThreadLocal> wait = new ThreadLocal<>(); + /** Logger instance for web driver operations. */ public static Printer log = new Printer(PickleibWebDriver.class); /** diff --git a/src/main/java/pickleib/web/driver/WebDriverFactory.java b/src/main/java/pickleib/web/driver/WebDriverFactory.java index 06831296..a44b3667 100644 --- a/src/main/java/pickleib/web/driver/WebDriverFactory.java +++ b/src/main/java/pickleib/web/driver/WebDriverFactory.java @@ -300,10 +300,15 @@ static RemoteWebDriver driverSwitch( * Enumeration of supported browser types. */ public enum BrowserType { + /** Google Chrome browser. */ CHROME("Chrome"), + /** Mozilla Firefox browser. */ FIREFOX("Firefox"), + /** Apple Safari browser. */ SAFARI("Safari"), + /** Microsoft Edge browser. */ EDGE("Edge"), + /** Opera browser. */ OPERA("Opera"); final String driverName; @@ -312,6 +317,11 @@ public enum BrowserType { this.driverName = driverName; } + /** + * Returns the driver key in lowercase (used for capability matching). + * + * @return the lowercase driver key + */ public String getDriverKey() { return driverName.toLowerCase(); } @@ -330,6 +340,11 @@ public static BrowserType fromString(String text) { return null; } + /** + * Returns the display name of the browser. + * + * @return the browser display name + */ public String getDriverName() { return driverName; } @@ -341,6 +356,8 @@ public String getDriverName() { * Sets the browser window width in pixels. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param frameWidth the width in pixels */ public static void setFrameWidth(int frameWidth) { WebDriverFactory.frameWidth = frameWidth; @@ -350,6 +367,8 @@ public static void setFrameWidth(int frameWidth) { * Sets the browser window height in pixels. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param frameHeight the height in pixels */ public static void setFrameHeight(int frameHeight) { WebDriverFactory.frameHeight = frameHeight; @@ -359,6 +378,8 @@ public static void setFrameHeight(int frameHeight) { * Enables or disables headless mode. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param headless true to enable headless mode */ public static void setHeadless(boolean headless) { WebDriverFactory.headless = headless; @@ -368,6 +389,8 @@ public static void setHeadless(boolean headless) { * Enables or disables window maximization on driver startup. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param maximise true to maximize the window on startup */ public static void setMaximise(boolean maximise) { WebDriverFactory.maximise = maximise; @@ -377,6 +400,8 @@ public static void setMaximise(boolean maximise) { * Sets the implicit wait timeout (in seconds) for the driver. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param driverTimeout the timeout in seconds */ public static void setDriverTimeout(long driverTimeout) { WebDriverFactory.driverTimeout = driverTimeout; @@ -386,6 +411,8 @@ public static void setDriverTimeout(long driverTimeout) { * Enables or disables cookie deletion on driver initialization. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param deleteCookies true to delete cookies on initialization */ public static void setDeleteCookies(boolean deleteCookies) { WebDriverFactory.deleteCookies = deleteCookies; @@ -395,6 +422,8 @@ public static void setDeleteCookies(boolean deleteCookies) { * Enables or disables Selenium Grid usage. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param useSeleniumGrid true to use Selenium Grid */ public static void setUseSeleniumGrid(boolean useSeleniumGrid) { WebDriverFactory.useSeleniumGrid = useSeleniumGrid; @@ -404,6 +433,8 @@ public static void setUseSeleniumGrid(boolean useSeleniumGrid) { * Enables or disables acceptance of insecure SSL certificates. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param insecureLocalHost true to accept insecure certificates */ public static void setInsecureLocalHost(boolean insecureLocalHost) { WebDriverFactory.insecureLocalHost = insecureLocalHost; @@ -413,6 +444,8 @@ public static void setInsecureLocalHost(boolean insecureLocalHost) { * Enables or disables browser notifications. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param disableNotifications true to disable browser notifications */ public static void setDisableNotifications(boolean disableNotifications) { WebDriverFactory.disableNotifications = disableNotifications; @@ -422,6 +455,8 @@ public static void setDisableNotifications(boolean disableNotifications) { * Sets the page load strategy for the driver. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param loadStrategy the page load strategy */ public static void setLoadStrategy(PageLoadStrategy loadStrategy) { WebDriverFactory.loadStrategy = loadStrategy; @@ -431,6 +466,8 @@ public static void setLoadStrategy(PageLoadStrategy loadStrategy) { * Enables or disables WebDriverManager for automatic driver binary management. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param useWDM true to enable WebDriverManager */ public static void setUseWDM(Boolean useWDM) { WebDriverFactory.useWDM = useWDM; @@ -440,6 +477,8 @@ public static void setUseWDM(Boolean useWDM) { * Enables or disables allowing remote origins (fixes connection issues in newer Chrome). *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param allowRemoteOrigin true to allow remote origins */ public static void setAllowRemoteOrigin(Boolean allowRemoteOrigin) { WebDriverFactory.allowRemoteOrigin = allowRemoteOrigin; @@ -449,6 +488,8 @@ public static void setAllowRemoteOrigin(Boolean allowRemoteOrigin) { * Sets the Selenium log level (e.g., "off", "info", "debug"). *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param logLevel the log level string */ public static void setLogLevel(String logLevel) { WebDriverFactory.logLevel = logLevel; @@ -458,6 +499,8 @@ public static void setLogLevel(String logLevel) { * Sets the Selenium Grid hub URL. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param hubUrl the Selenium Grid hub URL */ public static void setHubUrl(String hubUrl) { WebDriverFactory.hubUrl = hubUrl; @@ -467,6 +510,8 @@ public static void setHubUrl(String hubUrl) { * Sets the default browser type (e.g., "chrome", "firefox"). *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param browser the browser name */ public static void setBrowser(String browser) { WebDriverFactory.browser = browser; @@ -476,70 +521,88 @@ public static void setBrowser(String browser) { * Enables or disables the --no-sandbox browser argument. *

Thread Safety: This setter modifies shared static state. * It must be called before parallel driver initialization, not during.

+ * + * @param noSandbox true to add --no-sandbox argument */ public static void setNoSandbox(boolean noSandbox) {WebDriverFactory.noSandbox = noSandbox;} // Getters for configuration values + /** @return the browser window width in pixels */ public static int getFrameWidth() { return frameWidth; } + /** @return the browser window height in pixels */ public static int getFrameHeight() { return frameHeight; } + /** @return true if headless mode is enabled */ public static boolean isHeadless() { return headless; } + /** @return true if window maximization is enabled */ public static boolean isMaximise() { return maximise; } + /** @return the driver timeout in seconds */ public static long getDriverTimeout() { return driverTimeout; } + /** @return true if cookies are deleted on initialization */ public static boolean isDeleteCookies() { return deleteCookies; } + /** @return true if Selenium Grid is enabled */ public static boolean isUseSeleniumGrid() { return useSeleniumGrid; } + /** @return true if insecure certificates are accepted */ public static boolean isInsecureLocalHost() { return insecureLocalHost; } + /** @return true if browser notifications are disabled */ public static boolean isDisableNotifications() { return disableNotifications; } + /** @return the page load strategy */ public static PageLoadStrategy getLoadStrategy() { return loadStrategy; } + /** @return true if WebDriverManager is enabled */ public static Boolean getUseWDM() { return useWDM; } + /** @return true if remote origins are allowed */ public static Boolean getAllowRemoteOrigin() { return allowRemoteOrigin; } + /** @return the Selenium log level */ public static String getLogLevel() { return logLevel; } + /** @return the Selenium Grid hub URL */ public static String getHubUrl() { return hubUrl; } + /** @return the default browser name */ public static String getBrowser() { return browser; } + /** @return true if --no-sandbox is enabled */ public static boolean isNoSandbox() {return noSandbox;} } diff --git a/src/main/java/pickleib/web/interactions/WebInteractions.java b/src/main/java/pickleib/web/interactions/WebInteractions.java index d94bff09..93f914d2 100644 --- a/src/main/java/pickleib/web/interactions/WebInteractions.java +++ b/src/main/java/pickleib/web/interactions/WebInteractions.java @@ -40,11 +40,20 @@ */ public class WebInteractions extends WebUtilities implements PolymorphicUtilities { + /** + * Constructs a WebInteractions instance with a custom driver and wait. + * + * @param driver the WebDriver instance + * @param wait the FluentWait instance + */ public WebInteractions(RemoteWebDriver driver, FluentWait wait) { super(driver); this.wait = wait; } + /** + * Constructs a WebInteractions instance using the singleton {@link PickleibWebDriver}. + */ public WebInteractions() { super(PickleibWebDriver.get()); } @@ -803,7 +812,7 @@ public void fillInputElement(WebElement inputElement, String elementName, String * Executes interactions on a list of element bundles, based on the specified interaction type. *

* The interaction type is specified in the "Interaction Type" key of the map contained in each element bundle. - *

+ *

* * @param bundles A list of element bundles containing the element name, the matching element, and a map of the element's attributes. * @param pageName The name of the page object. @@ -1037,7 +1046,9 @@ public String generateXPath(@NotNull WebElement childElement, String elementName } /** - * Waits actively for the page to load up to 10 seconds + * Waits actively for the page to load up to the specified time. + * + * @param waitingTime maximum wait time in seconds */ public void waitUntilPageLoads(int waitingTime) { log.info("Waiting for the page to load up " + @@ -1141,8 +1152,9 @@ public void executeJSCommand(String script) { * Listen to {event name} event and print {specified script} object * example -> listenerScript = "_ddm.listen(" + eventName + ");"; * - * @param eventName target event name - * @param objectScript object script + * @param listenerScript the JS listener script + * @param eventName target event name + * @param objectScript object script */ //@Given("Listen to {} event & print {} object") public void listenGetAndPrintObject(String listenerScript, String eventName, String objectScript) { @@ -1157,9 +1169,10 @@ public void listenGetAndPrintObject(String listenerScript, String eventName, Str * Listen to {event name} event and verify value of {node source} node is {expected value} * example -> listenerScript = "_ddm.listen(" + eventName + ");"; * - * @param eventName evet name - * @param nodeSource node source - * @param expectedValue expected value + * @param listenerScript the JS listener script + * @param eventName event name + * @param nodeSource node source + * @param expectedValue expected value */ public void listenGetAndVerifyObject(String listenerScript, String eventName, String nodeSource, String expectedValue) { log.info("Verifying value of '" + nodeSource + "' node"); @@ -1181,8 +1194,9 @@ public void listenGetAndVerifyObject(String listenerScript, String eventName, St * Listen to {event name} event and verify the values of the following nodes * example -> listenerScript = "_ddm.listen(" + eventName + ");"; * - * @param eventName event name - * @param nodeList target node list + * @param listenerScript the JS listener script + * @param eventName event name + * @param nodeList target node list */ public void listenGetAndVerifyObject(String listenerScript, String eventName, List> nodeList) { if (isEventFired(eventName, listenerScript)) { diff --git a/src/main/java/pickleib/web/utilities/WebUtilities.java b/src/main/java/pickleib/web/utilities/WebUtilities.java index 28e2d16c..f6ede2c5 100644 --- a/src/main/java/pickleib/web/utilities/WebUtilities.java +++ b/src/main/java/pickleib/web/utilities/WebUtilities.java @@ -4,21 +4,18 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import dev.failsafe.internal.util.Assert; -import io.appium.java_client.functions.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedCondition; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.openqa.selenium.*; -import org.openqa.selenium.html5.LocalStorage; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.logging.LogEntries; import org.openqa.selenium.logging.LogEntry; import org.openqa.selenium.logging.LogType; -import org.openqa.selenium.remote.RemoteExecuteMethod; import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.remote.html5.RemoteWebStorage; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.FluentWait; import org.openqa.selenium.support.ui.WebDriverWait; @@ -74,6 +71,11 @@ public WebUtilities(RemoteWebDriver driver) { super(driver, (element) -> centerElement(element, driver)); } + /** + * Returns the active {@link RemoteWebDriver} instance. + * + * @return the driver instance + */ public RemoteWebDriver driver() { return this.driver; } @@ -564,6 +566,7 @@ public boolean isEventFiredByScript(String eventKey, String listenerScript) { * Executes a JS script and returns the responding object * * @param script script that is to be executed + * @param args arguments to pass to the script * * @return object if the scripts yield one */ @@ -578,11 +581,10 @@ public Object executeScript(String script, Object... args) { * @param form Map(String, String) */ public void addValuesToLocalStorage(Map form) { + JavascriptExecutor js = (JavascriptExecutor) driver; for (String valueKey : form.keySet()) { - RemoteExecuteMethod executeMethod = new RemoteExecuteMethod(driver); - RemoteWebStorage webStorage = new RemoteWebStorage(executeMethod); - LocalStorage storage = webStorage.getLocalStorage(); - storage.setItem(valueKey, contextCheck(form.get(valueKey))); + js.executeScript("window.localStorage.setItem(arguments[0], arguments[1]);", + valueKey, contextCheck(form.get(valueKey))); } } @@ -635,6 +637,8 @@ public Alert getAlert() { /** * Waits actively for the page to load up to 10 seconds + * + * @param waitingTime maximum wait time in seconds */ protected void waitUntilLoads(int waitingTime) { long startTime = System.currentTimeMillis();