From c8e7f80c83dcbe0c9a5e2a77a0d1fa69a04c01cf Mon Sep 17 00:00:00 2001 From: io42630 Date: Tue, 19 Mar 2024 21:17:08 +0100 Subject: [PATCH] + update tabdriver for the new millenium --- .tool-versions | 3 +- README.md => README.adoc | 7 +- deploy.sh | 3 + pom.xml | 62 ++------ .../java/com/olexyn/tabdriver/Constants.java | 1 + .../tabdriver/DefaultTabDriverConfig.java | 32 ++++ src/main/java/com/olexyn/tabdriver/Tab.java | 15 +- .../java/com/olexyn/tabdriver/TabDriver.java | 142 +++++++++++++----- .../olexyn/tabdriver/TabDriverBuilder.java | 59 -------- .../tabdriver/TabDriverConfigProvider.java | 19 +++ 10 files changed, 177 insertions(+), 166 deletions(-) rename README.md => README.adoc (69%) create mode 100644 deploy.sh create mode 100644 src/main/java/com/olexyn/tabdriver/DefaultTabDriverConfig.java delete mode 100644 src/main/java/com/olexyn/tabdriver/TabDriverBuilder.java create mode 100644 src/main/java/com/olexyn/tabdriver/TabDriverConfigProvider.java diff --git a/.tool-versions b/.tool-versions index 571f519..10c55a9 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1,2 @@ -java temurin-17 +java temurin-17.0.9+9 + diff --git a/README.md b/README.adoc similarity index 69% rename from README.md rename to README.adoc index ad5be6f..7f165a4 100644 --- a/README.md +++ b/README.adoc @@ -1,4 +1,9 @@ -# TabDriver += TabDriver + +:stylesheet: ../shared/adoc-styles.css +:toc: +:toclevels: 4 + * Wrapper for `selenium` to make it easier to use. * Must use `Chrome` (not `Chromium`). diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..67da383 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +mvn clean install deploy & \ No newline at end of file diff --git a/pom.xml b/pom.xml index 52bd4fe..c2d17fe 100644 --- a/pom.xml +++ b/pom.xml @@ -2,8 +2,11 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - com.olexyn + + com.olexyn + min-root + jdk17-0.0 + tabdriver 1.2.2 jar @@ -11,8 +14,6 @@ tabdriver - UTF-8 - 17 3.141.59 0.9.7376 @@ -21,8 +22,8 @@ com.olexyn - zeebom - 1.1 + min-bom + jdk17-0.3 pom import @@ -31,9 +32,8 @@ - com.olexyn.min.log + com.olexyn min-log - 0.1.1 @@ -71,55 +71,13 @@ org.projectlombok lombok - com.olexyn - propconf - 1.1 + min-prop - - - - - maven-clean-plugin - 3.1.0 - - - maven-resources-plugin - 3.0.2 - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - ${xx.java.version} - ${xx.java.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M1 - - internal.repo::default::http://localhost:9020/repository/maven-releases/ - - - - - - - - nexus-releases - http://localhost:9020/repository/maven-releases/ - - - nexus-snapshots - http://localhost:9020/repository/maven-snapshots/ - - + diff --git a/src/main/java/com/olexyn/tabdriver/Constants.java b/src/main/java/com/olexyn/tabdriver/Constants.java index 0673e70..d24315a 100644 --- a/src/main/java/com/olexyn/tabdriver/Constants.java +++ b/src/main/java/com/olexyn/tabdriver/Constants.java @@ -11,4 +11,5 @@ public interface Constants { String LABEL = "label"; String CLASS = "class"; String CHECKBOX = "checkbox"; + String ABOUT_BLANK = "about:blank"; } diff --git a/src/main/java/com/olexyn/tabdriver/DefaultTabDriverConfig.java b/src/main/java/com/olexyn/tabdriver/DefaultTabDriverConfig.java new file mode 100644 index 0000000..5af370e --- /dev/null +++ b/src/main/java/com/olexyn/tabdriver/DefaultTabDriverConfig.java @@ -0,0 +1,32 @@ +package com.olexyn.tabdriver; + +import org.openqa.selenium.chrome.ChromeOptions; +import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.DesiredCapabilities; + +import java.util.HashMap; + +public abstract class DefaultTabDriverConfig implements TabDriverConfigProvider { + + + @Override + public DesiredCapabilities getCapabilities() { + var cap = DesiredCapabilities.chrome(); + cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); + + ChromeOptions options = new ChromeOptions(); + options.addArguments("--start-maximized"); + if (isHeadless()) { + options.addArguments("--window-size=1920,1080"); + options.addArguments("--headless"); + } + // see also https://chromium.googlesource.com/chromium/src/+/master/chrome/common/pref_names.cc + HashMap chromePrefs = new HashMap<>(); + chromePrefs.put("profile.default_content_settings.popups", 0); + chromePrefs.put("download.default_directory", getDownloadDir()); + chromePrefs.put("download.prompt_for_download", false); + options.setExperimentalOption("prefs", chromePrefs); + cap.setCapability(ChromeOptions.CAPABILITY, options); + return cap; + } +} diff --git a/src/main/java/com/olexyn/tabdriver/Tab.java b/src/main/java/com/olexyn/tabdriver/Tab.java index 7fa3754..473c849 100644 --- a/src/main/java/com/olexyn/tabdriver/Tab.java +++ b/src/main/java/com/olexyn/tabdriver/Tab.java @@ -3,26 +3,15 @@ package com.olexyn.tabdriver; import lombok.Getter; import lombok.Setter; +@Setter +@Getter public class Tab { - - @Getter - @Setter String handle; - - @Getter - @Setter String name; - - @Getter - @Setter String url; - - @Getter - @Setter String purpose; - public Tab(String handle) { this.handle = handle; } diff --git a/src/main/java/com/olexyn/tabdriver/TabDriver.java b/src/main/java/com/olexyn/tabdriver/TabDriver.java index 009e445..9858ff2 100644 --- a/src/main/java/com/olexyn/tabdriver/TabDriver.java +++ b/src/main/java/com/olexyn/tabdriver/TabDriver.java @@ -1,31 +1,83 @@ package com.olexyn.tabdriver; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - import com.olexyn.min.log.LogU; +import org.checkerframework.checker.nullness.qual.Nullable; import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.Keys; import org.openqa.selenium.NoSuchFrameException; import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeDriverService; -public class TabDriver extends ChromeDriver implements JavascriptExecutor { +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import static com.olexyn.tabdriver.Constants.ABOUT_BLANK; + +@SuppressWarnings("unused") +public class TabDriver implements JavascriptExecutor { + + private final Map tabs = new HashMap<>(); + private final ChromeDriver chromeDriver; + + @SuppressWarnings("deprecation") + public TabDriver(TabDriverConfigProvider configProvider) { + var path = configProvider.getDriverPath(); + var service = new ChromeDriverService.Builder() + .usingDriverExecutable(path.toFile()) + .usingAnyFreePort() + .build(); + chromeDriver = new ChromeDriver(service, configProvider.getCapabilities()); + chromeDriver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS); + } + + public WebDriver.Navigation navigate() { + return chromeDriver.navigate(); + } + + public WebDriver.TargetLocator switchTo() { + return chromeDriver.switchTo(); + } + + public String getWindowHandle() { + return chromeDriver.getWindowHandle(); + } + + public Set getWindowHandles() { + return chromeDriver.getWindowHandles(); + } + + public String getTitle() { + return chromeDriver.getTitle(); + } + + public String getCurrentUrl() { + return chromeDriver.getCurrentUrl(); + } - private final Map TABS = new HashMap<>(); + public String getPageSource() { + return chromeDriver.getPageSource(); + } + + public void close() { + chromeDriver.close(); + } - public TabDriver(ChromeDriverService service, Capabilities capabilities) { - super(service, capabilities); - manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); + public void quit() { + chromeDriver.quit(); + } + + public List findElements(By by) { + return chromeDriver.findElements(by); } public synchronized void registerCurrentTab(String purpose) { @@ -33,28 +85,28 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor { tab.setName(getTitle()); tab.setUrl(getCurrentUrl()); tab.setPurpose(purpose); - TABS.put(tab.getHandle(), tab); + tabs.put(tab.getHandle(), tab); } public synchronized Tab getCurrentTab() { - return TABS.get(getWindowHandle()); + return tabs.get(getWindowHandle()); } public synchronized List getTabByPurpose(String purpose) { - return TABS.values().stream() - .filter(x -> x.getPurpose() == purpose) - .collect(Collectors.toList()); + return tabs.values().stream() + .filter(x -> Objects.equals(x.getPurpose(), purpose)) + .toList(); } public synchronized String registerBlankTab(String purpose) { Set openTabHandles = getWindowHandles(); for (String openTabHandle : openTabHandles) { - if (!TABS.containsKey(openTabHandle)) { + if (!tabs.containsKey(openTabHandle)) { Tab blankTab = new Tab(openTabHandle); - blankTab.setName("about:blank"); - blankTab.setUrl("about:blank"); + blankTab.setName(ABOUT_BLANK); + blankTab.setUrl(ABOUT_BLANK); blankTab.setPurpose(purpose); - TABS.put(openTabHandle, blankTab); + tabs.put(openTabHandle, blankTab); return openTabHandle; } } @@ -68,12 +120,12 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor { tab.setName(getTitle()); tab.setUrl(getCurrentUrl()); tab.setPurpose(purpose); - TABS.put(handle, tab); + tabs.put(handle, tab); return handle; } public synchronized void switchToTab(String handle) { - for (Entry entry : TABS.entrySet()) { + for (Entry entry : tabs.entrySet()) { String tabHandle = entry.getKey(); if (tabHandle.equals(handle)) { switchTo().window(tabHandle); @@ -90,14 +142,15 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor { * If the current tab is empty, it is registered - this happens usually only with the initial tab of the session. */ public synchronized void newTab(String purpose) { - String currentUrl = getCurrentUrl(); + String currentUrl = getCurrentUrl(); // TODO this throws error, just get a new window if (currentUrl.isEmpty() || currentUrl.equals("data:,") - || currentUrl.equals("about:blank")) { + || currentUrl.equals(ABOUT_BLANK)) { registerExistingTab(purpose); } else { executeScript("window.open(arguments[0])"); - switchToTab(registerBlankTab(purpose)); + Optional.ofNullable(registerBlankTab(purpose)) + .ifPresent(this::switchToTab); } } @@ -115,14 +168,12 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor { navigate().refresh(); } - @Override public synchronized void get(String url) { - super.get(url); + chromeDriver.get(url); } - @Override public synchronized WebElement findElement(By by) { - return super.findElement(by); + return chromeDriver.findElement(by); } public synchronized void executeScript(String script) { @@ -182,10 +233,16 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor { return FRAME_ID_NONE_FOUND; } -// @Override -// public boolean isJavascriptEnabled() { -// return false; -// } + @Override + public Object executeScript(String script, Object... args) { + return null; + } + + @Override + public Object executeAsyncScript(String script, Object... args) { + return null; + } + public enum CRITERIA { CLASS, @@ -236,10 +293,6 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor { return filterElementListBy(elements, CRITERIA.NONE, Constants.EMPTY); } - public synchronized List findElements(By by) { - return findElements(by); - } - public synchronized void followContainedLink(WebElement element) { String link = element.getAttribute("href"); if (link != null) { navigate().to(link); } @@ -256,6 +309,15 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor { combo.findElement(By.cssSelector("li[data-value='" + dataValue + "']")).click(); } + + public synchronized Optional findByCss(String css) { + try { + return Optional.of(findElement(By.cssSelector(css))); + } catch (Exception e) { + return Optional.empty(); + } + } + /** * Any-Match. */ diff --git a/src/main/java/com/olexyn/tabdriver/TabDriverBuilder.java b/src/main/java/com/olexyn/tabdriver/TabDriverBuilder.java deleted file mode 100644 index 42fcd3c..0000000 --- a/src/main/java/com/olexyn/tabdriver/TabDriverBuilder.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.olexyn.tabdriver; - -import java.nio.file.Path; -import java.util.HashMap; - -import com.olexyn.propconf.PropConf; -import lombok.experimental.UtilityClass; -import org.openqa.selenium.chrome.ChromeDriverService; -import org.openqa.selenium.chrome.ChromeOptions; -import org.openqa.selenium.remote.CapabilityType; -import org.openqa.selenium.remote.DesiredCapabilities; - -@UtilityClass -public class TabDriverBuilder { - - private static Path CONFIG_PATH; - - public static TabDriver build(Path path) { - CONFIG_PATH = path; - if (CONFIG_PATH == null) { - throw new RuntimeException("CONFIG_PATH must be set to an absolute path."); - } - return new TabDriver(configureService(), configureCapabilities()); - } - - - private static ChromeDriverService configureService() { - PropConf.loadProperties(CONFIG_PATH.toString()); - var path = Path.of(PropConf.get("chrome.driver.path")); - return new ChromeDriverService.Builder() - .usingDriverExecutable(path.toFile()) - .usingAnyFreePort() - .build(); - } - - private static DesiredCapabilities configureCapabilities() { - var cap = DesiredCapabilities.chrome(); - cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); - - ChromeOptions options = new ChromeOptions(); - options.addArguments("--start-maximized"); - if (PropConf.is("headless")) { - options.addArguments("--window-size=1920,1080"); - options.addArguments("--headless"); - } - // see also https://chromium.googlesource.com/chromium/src/+/master/chrome/common/pref_names.cc - HashMap chromePrefs = new HashMap<>(); - chromePrefs.put("profile.default_content_settings.popups", 0); - chromePrefs.put("download.default_directory", PropConf.get("download.dir")); - chromePrefs.put("download.prompt_for_download", false); - options.setExperimentalOption("prefs", chromePrefs); - cap.setCapability(ChromeOptions.CAPABILITY, options); - return cap; - } - - - - -} diff --git a/src/main/java/com/olexyn/tabdriver/TabDriverConfigProvider.java b/src/main/java/com/olexyn/tabdriver/TabDriverConfigProvider.java new file mode 100644 index 0000000..038ad9f --- /dev/null +++ b/src/main/java/com/olexyn/tabdriver/TabDriverConfigProvider.java @@ -0,0 +1,19 @@ +package com.olexyn.tabdriver; + +import org.openqa.selenium.remote.DesiredCapabilities; + +import java.nio.file.Path; + +public interface TabDriverConfigProvider { + + + Path getDriverPath(); + + String getDownloadDir(); + + + boolean isHeadless(); + + DesiredCapabilities getCapabilities(); + +}