+ update tabdriver for the new millenium

master
io42630 1 year ago
parent 220243fbd8
commit c8e7f80c83

@ -1 +1,2 @@
java temurin-17 java temurin-17.0.9+9

@ -1,4 +1,9 @@
# TabDriver = TabDriver
:stylesheet: ../shared/adoc-styles.css
:toc:
:toclevels: 4
* Wrapper for `selenium` to make it easier to use. * Wrapper for `selenium` to make it easier to use.
* Must use `Chrome` (not `Chromium`). * Must use `Chrome` (not `Chromium`).

@ -0,0 +1,3 @@
#!/bin/bash
mvn clean install deploy &

@ -2,8 +2,11 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.olexyn</groupId> <groupId>com.olexyn</groupId>
<artifactId>min-root</artifactId>
<version>jdk17-0.0</version>
</parent>
<artifactId>tabdriver</artifactId> <artifactId>tabdriver</artifactId>
<version>1.2.2</version> <version>1.2.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -11,8 +14,6 @@
<name>tabdriver</name> <name>tabdriver</name>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<xx.java.version>17</xx.java.version>
<xx.selenium.version>3.141.59</xx.selenium.version> <xx.selenium.version>3.141.59</xx.selenium.version>
<xx.webdriver.version>0.9.7376</xx.webdriver.version> <xx.webdriver.version>0.9.7376</xx.webdriver.version>
</properties> </properties>
@ -21,8 +22,8 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.olexyn</groupId> <groupId>com.olexyn</groupId>
<artifactId>zeebom</artifactId> <artifactId>min-bom</artifactId>
<version>1.1</version> <version>jdk17-0.3</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
@ -31,9 +32,8 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.olexyn.min.log</groupId> <groupId>com.olexyn</groupId>
<artifactId>min-log</artifactId> <artifactId>min-log</artifactId>
<version>0.1.1</version>
</dependency> </dependency>
<dependency> <dependency>
<!-- must come before selenium --> <!-- must come before selenium -->
@ -71,55 +71,13 @@
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.olexyn</groupId> <groupId>com.olexyn</groupId>
<artifactId>propconf</artifactId> <artifactId>min-prop</artifactId>
<version>1.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${xx.java.version}</source>
<target>${xx.java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<altDeploymentRepository>internal.repo::default::http://localhost:9020/repository/maven-releases/</altDeploymentRepository>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<distributionManagement>
<repository>
<id>nexus-releases</id>
<url>http://localhost:9020/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>http://localhost:9020/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
</project> </project>

@ -11,4 +11,5 @@ public interface Constants {
String LABEL = "label"; String LABEL = "label";
String CLASS = "class"; String CLASS = "class";
String CHECKBOX = "checkbox"; String CHECKBOX = "checkbox";
String ABOUT_BLANK = "about:blank";
} }

@ -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<String, Object> 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;
}
}

@ -3,26 +3,15 @@ package com.olexyn.tabdriver;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@Setter
@Getter
public class Tab { public class Tab {
@Getter
@Setter
String handle; String handle;
@Getter
@Setter
String name; String name;
@Getter
@Setter
String url; String url;
@Getter
@Setter
String purpose; String purpose;
public Tab(String handle) { public Tab(String handle) {
this.handle = handle; this.handle = handle;
} }

@ -1,31 +1,83 @@
package com.olexyn.tabdriver; 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 com.olexyn.min.log.LogU;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.openqa.selenium.By; import org.openqa.selenium.By;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys; import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchFrameException; import org.openqa.selenium.NoSuchFrameException;
import org.openqa.selenium.SearchContext; import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement; import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService; 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<String, Tab> 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<String> getWindowHandles() {
return chromeDriver.getWindowHandles();
}
public String getTitle() {
return chromeDriver.getTitle();
}
public String getCurrentUrl() {
return chromeDriver.getCurrentUrl();
}
private final Map<String, Tab> TABS = new HashMap<>(); public String getPageSource() {
return chromeDriver.getPageSource();
}
public void close() {
chromeDriver.close();
}
public TabDriver(ChromeDriverService service, Capabilities capabilities) { public void quit() {
super(service, capabilities); chromeDriver.quit();
manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); }
public List<WebElement> findElements(By by) {
return chromeDriver.findElements(by);
} }
public synchronized void registerCurrentTab(String purpose) { public synchronized void registerCurrentTab(String purpose) {
@ -33,28 +85,28 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor {
tab.setName(getTitle()); tab.setName(getTitle());
tab.setUrl(getCurrentUrl()); tab.setUrl(getCurrentUrl());
tab.setPurpose(purpose); tab.setPurpose(purpose);
TABS.put(tab.getHandle(), tab); tabs.put(tab.getHandle(), tab);
} }
public synchronized Tab getCurrentTab() { public synchronized Tab getCurrentTab() {
return TABS.get(getWindowHandle()); return tabs.get(getWindowHandle());
} }
public synchronized List<Tab> getTabByPurpose(String purpose) { public synchronized List<Tab> getTabByPurpose(String purpose) {
return TABS.values().stream() return tabs.values().stream()
.filter(x -> x.getPurpose() == purpose) .filter(x -> Objects.equals(x.getPurpose(), purpose))
.collect(Collectors.toList()); .toList();
} }
public synchronized String registerBlankTab(String purpose) { public synchronized String registerBlankTab(String purpose) {
Set<String> openTabHandles = getWindowHandles(); Set<String> openTabHandles = getWindowHandles();
for (String openTabHandle : openTabHandles) { for (String openTabHandle : openTabHandles) {
if (!TABS.containsKey(openTabHandle)) { if (!tabs.containsKey(openTabHandle)) {
Tab blankTab = new Tab(openTabHandle); Tab blankTab = new Tab(openTabHandle);
blankTab.setName("about:blank"); blankTab.setName(ABOUT_BLANK);
blankTab.setUrl("about:blank"); blankTab.setUrl(ABOUT_BLANK);
blankTab.setPurpose(purpose); blankTab.setPurpose(purpose);
TABS.put(openTabHandle, blankTab); tabs.put(openTabHandle, blankTab);
return openTabHandle; return openTabHandle;
} }
} }
@ -68,12 +120,12 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor {
tab.setName(getTitle()); tab.setName(getTitle());
tab.setUrl(getCurrentUrl()); tab.setUrl(getCurrentUrl());
tab.setPurpose(purpose); tab.setPurpose(purpose);
TABS.put(handle, tab); tabs.put(handle, tab);
return handle; return handle;
} }
public synchronized void switchToTab(String handle) { public synchronized void switchToTab(String handle) {
for (Entry<String, Tab> entry : TABS.entrySet()) { for (Entry<String, Tab> entry : tabs.entrySet()) {
String tabHandle = entry.getKey(); String tabHandle = entry.getKey();
if (tabHandle.equals(handle)) { if (tabHandle.equals(handle)) {
switchTo().window(tabHandle); 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. * 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) { public synchronized void newTab(String purpose) {
String currentUrl = getCurrentUrl(); String currentUrl = getCurrentUrl(); // TODO this throws error, just get a new window
if (currentUrl.isEmpty() if (currentUrl.isEmpty()
|| currentUrl.equals("data:,") || currentUrl.equals("data:,")
|| currentUrl.equals("about:blank")) { || currentUrl.equals(ABOUT_BLANK)) {
registerExistingTab(purpose); registerExistingTab(purpose);
} else { } else {
executeScript("window.open(arguments[0])"); 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(); navigate().refresh();
} }
@Override
public synchronized void get(String url) { public synchronized void get(String url) {
super.get(url); chromeDriver.get(url);
} }
@Override
public synchronized WebElement findElement(By by) { public synchronized WebElement findElement(By by) {
return super.findElement(by); return chromeDriver.findElement(by);
} }
public synchronized void executeScript(String script) { public synchronized void executeScript(String script) {
@ -182,10 +233,16 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor {
return FRAME_ID_NONE_FOUND; return FRAME_ID_NONE_FOUND;
} }
// @Override @Override
// public boolean isJavascriptEnabled() { public Object executeScript(String script, Object... args) {
// return false; return null;
// } }
@Override
public Object executeAsyncScript(String script, Object... args) {
return null;
}
public enum CRITERIA { public enum CRITERIA {
CLASS, CLASS,
@ -236,10 +293,6 @@ public class TabDriver extends ChromeDriver implements JavascriptExecutor {
return filterElementListBy(elements, CRITERIA.NONE, Constants.EMPTY); return filterElementListBy(elements, CRITERIA.NONE, Constants.EMPTY);
} }
public synchronized List<WebElement> findElements(By by) {
return findElements(by);
}
public synchronized void followContainedLink(WebElement element) { public synchronized void followContainedLink(WebElement element) {
String link = element.getAttribute("href"); String link = element.getAttribute("href");
if (link != null) { navigate().to(link); } 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(); combo.findElement(By.cssSelector("li[data-value='" + dataValue + "']")).click();
} }
public synchronized Optional<WebElement> findByCss(String css) {
try {
return Optional.of(findElement(By.cssSelector(css)));
} catch (Exception e) {
return Optional.empty();
}
}
/** /**
* Any-Match. * Any-Match.
*/ */

@ -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<String, Object> 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;
}
}

@ -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();
}
Loading…
Cancel
Save