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();
+
+}