diff --git a/lightning-adapter/pom.xml b/lightning-adapter/pom.xml new file mode 100644 index 0000000..6ec4ac7 --- /dev/null +++ b/lightning-adapter/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + + com.aerokube.lightning + lightning-parent + 1.2.2-SNAPSHOT + + + lightning-adapter + + Lightning Adapter + Adapter classes to use Lightning with existing Selenium tests + + + 4.1.4 + + + + + com.aerokube.lightning + lightning + + + org.seleniumhq.selenium + selenium-api + ${selenium-api.version} + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.hamcrest + hamcrest + test + + + org.testcontainers + testcontainers + test + + + org.testcontainers + junit-jupiter + test + + + org.slf4j + slf4j-log4j12 + test + + + + diff --git a/lightning-adapter/src/main/java/com/aerokube/lightning/adapter/SeleniumWebDriver.java b/lightning-adapter/src/main/java/com/aerokube/lightning/adapter/SeleniumWebDriver.java new file mode 100644 index 0000000..72ab4f9 --- /dev/null +++ b/lightning-adapter/src/main/java/com/aerokube/lightning/adapter/SeleniumWebDriver.java @@ -0,0 +1,487 @@ +package com.aerokube.lightning.adapter; + +import com.aerokube.lightning.Position; +import com.aerokube.lightning.Size; +import com.aerokube.lightning.model.LocatorStrategy; +import org.openqa.selenium.*; +import org.openqa.selenium.interactions.MoveTargetOutOfBoundsException; +import org.openqa.selenium.logging.Logs; + +import javax.annotation.Nonnull; +import java.net.URL; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import static com.aerokube.lightning.By.cssSelector; + +public class SeleniumWebDriver implements WebDriver, WebDriver.Options, WebDriver.Navigation, WebDriver.TargetLocator, WebDriver.Timeouts, WebDriver.Window, Alert, JavascriptExecutor, TakesScreenshot, HasCapabilities { + + private final com.aerokube.lightning.WebDriver webDriver; + + public SeleniumWebDriver(com.aerokube.lightning.WebDriver webDriver) { + this.webDriver = webDriver; + } + + static T execute(@Nonnull Callable action) { + try { + return action.call(); + } catch (com.aerokube.lightning.WebDriverException e) { + throw processException(e); + } catch (Exception e) { + throw new WebDriverException(e); + } + } + + private static WebDriverException processException(com.aerokube.lightning.WebDriverException e) { + switch (e.getErrorCode()) { + case ELEMENT_CLICK_INTERCEPTED: + return new ElementClickInterceptedException(e.getMessage(), e); + case ELEMENT_NOT_INTERACTABLE: + return new ElementNotInteractableException(e.getMessage(), e); + case INSECURE_CERTIFICATE: + break; + case INVALID_ARGUMENT: + return new InvalidArgumentException(e.getMessage(), e); + case INVALID_COOKIE_DOMAIN: + return new InvalidCookieDomainException(e.getMessage(), e); + case INVALID_ELEMENT_STATE: + return new InvalidElementStateException(e.getMessage(), e); + case INVALID_SELECTOR: + return new InvalidSelectorException(e.getMessage(), e); + case INVALID_SESSION_ID: + return new NoSuchSessionException(e.getMessage(), e); + case JAVASCRIPT_ERROR: + return new JavascriptException(e.getMessage(), e); + case MOVE_TARGET_OUT_OF_BOUNDS: + return new MoveTargetOutOfBoundsException(e.getMessage(), e); + case NO_SUCH_ALERT: + return new NoAlertPresentException(e.getMessage(), e); + case NO_SUCH_COOKIE: + return new NoSuchCookieException(e.getMessage()); + case NO_SUCH_ELEMENT: + return new NoSuchElementException(e.getMessage(), e); + case NO_SUCH_FRAME: + return new NoSuchFrameException(e.getMessage(), e); + case NO_SUCH_WINDOW: + return new NoSuchWindowException(e.getMessage(), e); + case SCRIPT_TIMEOUT: + return new ScriptTimeoutException(e.getMessage(), e); + case SESSION_NOT_CREATED: + return new SessionNotCreatedException(e.getMessage(), e); + case STALE_ELEMENT_REFERENCE: + return new StaleElementReferenceException(e.getMessage(), e); + case TIMEOUT: + return new TimeoutException(e.getMessage(), e); + case UNABLE_TO_SET_COOKIE: + return new UnableToSetCookieException(e.getMessage(), e); + case UNEXPECTED_ALERT_OPEN: + return new UnhandledAlertException(e.getMessage()); + case UNSUPPORTED_OPERATION: + return new UnsupportedCommandException(e.getMessage(), e); + } + return new WebDriverException(e.getMessage(), e); + } + + static com.aerokube.lightning.WebDriver.Locator byToLocator(By by) { + if (by instanceof By.Remotable) { + By.Remotable.Parameters remoteParameters = ((By.Remotable) by).getRemoteParameters(); + LocatorStrategy locatorStrategy = LocatorStrategy.fromValue(remoteParameters.using()); + String expression = String.valueOf(remoteParameters.value()); + return new com.aerokube.lightning.By(expression, locatorStrategy); + } + throw new WebDriverException(String.format("Unsupported locator type: %s", by.getClass().getCanonicalName())); + } + + @Nonnull + private static com.aerokube.lightning.Cookie convertSeleniumCookie(Cookie cookie) { + com.aerokube.lightning.Cookie.CookieBuilder cookieBuilder = com.aerokube.lightning.Cookie.create(cookie.getName(), cookie.getValue()) + .path(cookie.getPath()) + .domain(cookie.getDomain()) + .expires(cookie.getExpiry().toInstant()) + .sameSitePolicy(com.aerokube.lightning.model.Cookie.SameSiteEnum.valueOf(cookie.getSameSite())); + if (cookie.isHttpOnly()) { + cookieBuilder = cookieBuilder.httpOnly(); + } + if (cookie.isSecure()) { + cookieBuilder = cookieBuilder.secureOnly(); + } + return cookieBuilder.build(); + } + + @Nonnull + private static Cookie convertLightningCookie(com.aerokube.lightning.Cookie cookie) { + Optional expires = cookie.getExpires(); + Date date = null; + if (expires.isPresent()) { + date = Date.from(expires.get()); + } + return new Cookie(cookie.getName(), cookie.getValue(), cookie.getDomain(), cookie.getPath(), date, cookie.isSecureOnly(), cookie.isHttpOnly(), cookie.getSameSitePolicy().getValue()); + } + + @Override + public void get(String url) { + execute(() -> webDriver.navigation().navigate(url)); + } + + @Override + public String getCurrentUrl() { + return execute(() -> webDriver.navigation().getUrl()); + } + + @Override + public String getTitle() { + return execute(() -> webDriver.navigation().getTitle()); + } + + @Override + public List findElements(By by) { + return execute(() -> webDriver.elements().findAll(byToLocator(by)) + .stream().map(SeleniumWebElement::new) + .collect(Collectors.toList())); + } + + @Override + public WebElement findElement(By by) { + com.aerokube.lightning.WebElement webElement = execute(() -> webDriver.elements().findFirst(byToLocator(by))); + return new SeleniumWebElement(webElement); + } + + @Override + public String getPageSource() { + return execute(() -> webDriver.document().getPageSource()); + } + + @Override + public void close() { + execute(() -> webDriver.windows().current().close()); + } + + @Override + public void quit() { + execute(() -> { + webDriver.session().delete(); + return null; + }); + } + + @Override + public Set getWindowHandles() { + return execute(() -> webDriver.windows().list() + .stream().map(com.aerokube.lightning.Window::getHandle) + .collect(Collectors.toSet())); + } + + @Override + public String getWindowHandle() { + return execute(() -> webDriver.windows().current().getHandle()); + } + + @Override + public TargetLocator switchTo() { + return this; + } + + @Override + public Navigation navigate() { + return this; + } + + @Override + public Options manage() { + return this; + } + + @Override + public void back() { + execute(() -> webDriver.navigation().back()); + } + + @Override + public void forward() { + execute(() -> webDriver.navigation().forward()); + } + + @Override + public void to(String url) { + execute(() -> webDriver.navigation().navigate(url)); + } + + @Override + public void to(URL url) { + execute(() -> webDriver.navigation().navigate(url.toString())); + } + + @Override + public void refresh() { + execute(() -> webDriver.navigation().refresh()); + } + + @Override + public WebDriver frame(int index) { + execute(() -> { + webDriver.frames().switchTo(index); + return null; + }); + return this; + } + + @Override + public WebDriver frame(String nameOrId) { + com.aerokube.lightning.WebDriver.Locator byNameLocator = cssSelector(String.format("frame[name='%s'],iframe[name='%s']", nameOrId, nameOrId)); + List byName = execute(() -> webDriver.elements().findAll(byNameLocator)); + if (byName.size() > 0) { + frame(new SeleniumWebElement(byName.get(0))); + return this; + } + + com.aerokube.lightning.WebDriver.Locator byIdLocator = cssSelector(String.format("frame#%s,iframe#%s", nameOrId, nameOrId)); + List byId = execute(() -> webDriver.elements().findAll(byIdLocator)); + if (byId.size() > 0) { + frame(new SeleniumWebElement(byId.get(0))); + return this; + } + + throw new NoSuchFrameException("No frame element found by name or id " + nameOrId); + } + + @Override + public WebDriver frame(WebElement frameElement) { + if (frameElement instanceof SeleniumWebElement) { + execute(() -> { + webDriver.frames().switchTo(((SeleniumWebElement) frameElement).raw()); + return null; + }); + return this; + } + throw new IllegalArgumentException("This operation is not supported on third-party WebElement instances"); + } + + @Override + public WebDriver parentFrame() { + execute(() -> { + webDriver.frames().switchToParent(); + return null; + }); + return this; + } + + @Override + public WebDriver window(String nameOrHandle) { + List windows = execute(() -> webDriver.windows().list()); + windows.stream().filter( + w -> getWindowHandles().contains(nameOrHandle) + ) + .findFirst() + .orElseThrow(() -> new NoSuchWindowException(String.format("Window %s not found", nameOrHandle))) + .switchTo(); + return this; + } + + @Override + public WebDriver newWindow(WindowType typeHint) { + switch (typeHint) { + case WINDOW: + execute(() -> webDriver.windows().createWindow()); + break; + case TAB: + execute(() -> webDriver.windows().createTab()); + break; + } + return this; + } + + @Override + public WebDriver defaultContent() { + execute(() -> { + webDriver.frames().switchToDefault(); + return null; + }); + return this; + } + + @Override + public WebElement activeElement() { + com.aerokube.lightning.WebElement webElement = execute(() -> webDriver.elements().current()); + return new SeleniumWebElement(webElement); + } + + @Override + public Alert alert() { + return this; + } + + @Override + public void dismiss() { + execute(() -> webDriver.prompts().dismiss()); + } + + @Override + public void accept() { + execute(() -> webDriver.prompts().accept()); + } + + @Override + public String getText() { + return execute(() -> webDriver.prompts().getText()); + } + + @Override + public void sendKeys(String keysToSend) { + execute(() -> webDriver.prompts().sendText(keysToSend)); + } + + @Override + public Object executeScript(String script, Object... args) { + return execute(() -> webDriver.document().executeScript(script, args)); + } + + @Override + public Object executeAsyncScript(String script, Object... args) { + return execute(() -> webDriver.document().executeAsyncScript(script, args)); + } + + @Override + public X getScreenshotAs(OutputType target) throws WebDriverException { + return target.convertFromPngBytes(execute(() -> webDriver.screenshot().take())); + } + + @Override + public void addCookie(Cookie cookie) { + execute(() -> webDriver.cookies().add(convertSeleniumCookie(cookie))); + } + + @Override + public void deleteCookieNamed(String name) { + execute(() -> webDriver.cookies().delete(name)); + } + + @Override + public void deleteCookie(Cookie cookie) { + execute(() -> webDriver.cookies().delete(cookie.getName())); + } + + @Override + public void deleteAllCookies() { + execute(() -> webDriver.cookies().deleteAll()); + } + + @Override + public Set getCookies() { + return execute(() -> webDriver.cookies().getAll()) + .stream().map(SeleniumWebDriver::convertLightningCookie) + .collect(Collectors.toSet()); + } + + @Override + public Cookie getCookieNamed(String name) { + com.aerokube.lightning.Cookie cookie = execute(() -> webDriver.cookies().get(name)); + return convertLightningCookie(cookie); + } + + @Override + public Timeouts timeouts() { + return this; + } + + @Override + public ImeHandler ime() { + throw new UnsupportedOperationException("IME is not supported"); + } + + @Override + public Window window() { + return this; + } + + @Override + public Logs logs() { + //TODO: need to implement this in Lightning first + throw new UnsupportedOperationException("Logs is not yet supported"); + } + + @Override + public Duration getImplicitWaitTimeout() { + return execute(() -> webDriver.timeouts().getImplicitWaitTimeout()); + } + + @Override + public Duration getScriptTimeout() { + Optional scriptTimeout = execute(() -> webDriver.timeouts().getScriptTimeout()); + if (scriptTimeout.isEmpty()) { + throw new WebDriverException("Script timeout is empty"); + } + return scriptTimeout.get(); + } + + @Override + public Duration getPageLoadTimeout() { + return execute(() -> webDriver.timeouts().getPageLoadTimeout()); + } + + @Override + public Timeouts implicitlyWait(long time, TimeUnit unit) { + execute(() -> webDriver.timeouts().setImplicitWaitTimeout(Duration.of(time, unit.toChronoUnit()))); + return this; + } + + @Override + public Timeouts setScriptTimeout(long time, TimeUnit unit) { + execute(() -> webDriver.timeouts().setScriptTimeout(Duration.of(time, unit.toChronoUnit()))); + return this; + } + + @Override + public Timeouts pageLoadTimeout(long time, TimeUnit unit) { + execute(() -> webDriver.timeouts().setPageLoadTimeout(Duration.of(time, unit.toChronoUnit()))); + return this; + } + + @Override + public Dimension getSize() { + Size size = execute(() -> webDriver.windows().current().getSize()); + return new Dimension(size.getWidth(), size.getHeight()); + } + + @Override + public void setSize(Dimension targetSize) { + execute(() -> webDriver.windows().current().setSize(targetSize.getWidth(), targetSize.getHeight())); + } + + @Override + public Point getPosition() { + Position position = execute(() -> webDriver.windows().current().getPosition()); + return new Point(position.getX(), position.getY()); + } + + @Override + public void setPosition(Point targetPosition) { + execute(() -> webDriver.windows().current().setPosition(targetPosition.getX(), targetPosition.getY())); + } + + @Override + public void maximize() { + execute(() -> webDriver.windows().current().maximize()); + } + + @Override + public void minimize() { + execute(() -> webDriver.windows().current().minimize()); + } + + @Override + public void fullscreen() { + execute(() -> webDriver.windows().current().fullscreen()); + } + + @Override + public Capabilities getCapabilities() { + return new ImmutableCapabilities(webDriver.getCapabilities().raw()); + } +} diff --git a/lightning-adapter/src/main/java/com/aerokube/lightning/adapter/SeleniumWebElement.java b/lightning-adapter/src/main/java/com/aerokube/lightning/adapter/SeleniumWebElement.java new file mode 100644 index 0000000..243a519 --- /dev/null +++ b/lightning-adapter/src/main/java/com/aerokube/lightning/adapter/SeleniumWebElement.java @@ -0,0 +1,117 @@ +package com.aerokube.lightning.adapter; + +import com.aerokube.lightning.Position; +import com.aerokube.lightning.Size; +import org.openqa.selenium.*; + +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static com.aerokube.lightning.adapter.SeleniumWebDriver.byToLocator; +import static com.aerokube.lightning.adapter.SeleniumWebDriver.execute; + +public class SeleniumWebElement implements WebElement { + + private final com.aerokube.lightning.WebElement webElement; + + public SeleniumWebElement(com.aerokube.lightning.WebElement webElement) { + this.webElement = webElement; + } + + @Nonnull + com.aerokube.lightning.WebElement raw() { + return webElement; + } + + @Override + public void click() { + execute(webElement::click); + } + + @Override + public void submit() { + throw new UnsupportedOperationException("This command is not supported in W3C Webdriver standard"); + } + + @Override + public void sendKeys(CharSequence... keysToSend) { + execute(() -> webElement.sendKeys(Arrays.toString(keysToSend))); + } + + @Override + public void clear() { + execute(webElement::clear); + } + + @Override + public String getTagName() { + return execute(webElement::getTagName); + } + + @Override + public String getAttribute(String name) { + return execute(() -> webElement.getAttribute(name).orElse(null)); + } + + @Override + public boolean isSelected() { + return execute(webElement::isSelected); + } + + @Override + public boolean isEnabled() { + return execute(webElement::isEnabled); + } + + @Override + public String getText() { + return execute(webElement::getText); + } + + @Override + public List findElements(By by) { + return execute(() -> webElement.findAll(byToLocator(by))) + .stream().map(SeleniumWebElement::new) + .collect(Collectors.toList()); + } + + @Override + public WebElement findElement(By by) { + com.aerokube.lightning.WebElement found = execute(() -> webElement.findFirst(byToLocator(by))); + return new SeleniumWebElement(found); + } + + @Override + public boolean isDisplayed() { + return execute(webElement::isDisplayed); + } + + @Override + public Point getLocation() { + Position position = execute(webElement::getPosition); + return new Point(position.getX(), position.getY()); + } + + @Override + public Dimension getSize() { + Size size = execute(webElement::getSize); + return new Dimension(size.getWidth(), size.getHeight()); + } + + @Override + public Rectangle getRect() { + return new Rectangle(getLocation(), getSize()); + } + + @Override + public String getCssValue(String propertyName) { + return execute(() -> webElement.getCssProperty(propertyName)); + } + + @Override + public X getScreenshotAs(OutputType target) throws WebDriverException { + return target.convertFromPngBytes(execute(webElement::takeScreenshot)); + } +} diff --git a/lightning-adapter/src/test/java/com/aerokube/lightning/adapter/BaseTest.java b/lightning-adapter/src/test/java/com/aerokube/lightning/adapter/BaseTest.java new file mode 100644 index 0000000..c0bc87b --- /dev/null +++ b/lightning-adapter/src/test/java/com/aerokube/lightning/adapter/BaseTest.java @@ -0,0 +1,55 @@ +package com.aerokube.lightning.adapter; + +import com.aerokube.lightning.Capabilities; +import org.openqa.selenium.WebDriver; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +import static com.aerokube.lightning.WebDriver.create; + +@Testcontainers +public class BaseTest { + + @Container + protected final GenericContainer browserContainer = getBrowserContainer(); + + protected WebDriver driver; + + private static final String IMAGE = "browsers/chrome:101.0"; + + protected GenericContainer getBrowserContainer() { + return new GenericContainer<>(DockerImageName.parse(IMAGE)) + .withPrivilegedMode(true) + .withExposedPorts(4444) + .withSharedMemorySize(268435456L) + .waitingFor(new HttpWaitStrategy().forPort(4444).forPath("/status")); + } + + protected String getUri(int port) { + return String.format("http://localhost:%s/", port); + } + + protected void test(Supplier caps, Consumer steps) { + WebDriver driver = null; + try { + Integer port = browserContainer.getMappedPort(4444); + driver = new SeleniumWebDriver(create(getUri(port), caps.get())); + steps.accept(driver); + } finally { + if (driver != null) { + driver.quit(); + } + } + } + + protected void test(Consumer steps) { + test(() -> Capabilities.create().browserName("chrome"), steps); + } + +} diff --git a/lightning-adapter/src/test/java/com/aerokube/lightning/adapter/ScreenshotTest.java b/lightning-adapter/src/test/java/com/aerokube/lightning/adapter/ScreenshotTest.java new file mode 100644 index 0000000..e01966f --- /dev/null +++ b/lightning-adapter/src/test/java/com/aerokube/lightning/adapter/ScreenshotTest.java @@ -0,0 +1,35 @@ +package com.aerokube.lightning.adapter; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.TakesScreenshot; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.instanceOf; + +public class ScreenshotTest extends BaseTest { + + @Test + void testPageScreenshot() { + test(driver -> { + driver.get("https://example.com"); + assertThat(driver, instanceOf(TakesScreenshot.class)); + byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES); + assertThat(screenshot.length, greaterThan(0)); + }); + } + + @Test + void testElementScreenshot() { + test(driver -> { + driver.get("https://example.com"); + WebElement body = driver.findElement(By.tagName("body")); + byte[] screenshot = body.getScreenshotAs(OutputType.BYTES); + assertThat(screenshot.length, greaterThan(0)); + }); + } + +} diff --git a/src/test/resources/log4j.properties b/lightning-adapter/src/test/resources/log4j.properties similarity index 100% rename from src/test/resources/log4j.properties rename to lightning-adapter/src/test/resources/log4j.properties diff --git a/lightning/pom.xml b/lightning/pom.xml new file mode 100644 index 0000000..08cd27f --- /dev/null +++ b/lightning/pom.xml @@ -0,0 +1,125 @@ + + + 4.0.0 + + + com.aerokube.lightning + lightning-parent + 1.2.2-SNAPSHOT + + + lightning + + Lightning + Lightweight and lightning fast WebDriver client library + + + 1.6.6 + 1.1.2 + 5.1.0 + 2.13.3 + 2.13.3 + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-datatype.version} + + + org.openapitools + jackson-databind-nullable + 0.2.2 + + + javax.ws.rs + javax.ws.rs-api + 2.1.1 + + + io.swagger + swagger-annotations + ${swagger.version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.hamcrest + hamcrest + test + + + org.testcontainers + testcontainers + test + + + org.testcontainers + junit-jupiter + test + + + net.lightbody.bmp + browsermob-core + 2.1.5 + test + + + org.slf4j + slf4j-log4j12 + test + + + + + + + + + + + org.openapitools + openapi-generator-maven-plugin + ${openapi-plugin.version} + + + + generate + + + com.aerokube.lightning.model + com.aerokube.lightning.api + https://github.com/aerokube/selenium-openapi/releases/download/${openapi-spec.version}/selenium.yaml + java + false + false + true + true + native + + java8 + + + + + + + + + diff --git a/src/main/java/com/aerokube/lightning/By.java b/lightning/src/main/java/com/aerokube/lightning/By.java similarity index 100% rename from src/main/java/com/aerokube/lightning/By.java rename to lightning/src/main/java/com/aerokube/lightning/By.java diff --git a/src/main/java/com/aerokube/lightning/Capabilities.java b/lightning/src/main/java/com/aerokube/lightning/Capabilities.java similarity index 100% rename from src/main/java/com/aerokube/lightning/Capabilities.java rename to lightning/src/main/java/com/aerokube/lightning/Capabilities.java diff --git a/src/main/java/com/aerokube/lightning/Cookie.java b/lightning/src/main/java/com/aerokube/lightning/Cookie.java similarity index 100% rename from src/main/java/com/aerokube/lightning/Cookie.java rename to lightning/src/main/java/com/aerokube/lightning/Cookie.java diff --git a/src/main/java/com/aerokube/lightning/ExtensionCapabilities.java b/lightning/src/main/java/com/aerokube/lightning/ExtensionCapabilities.java similarity index 100% rename from src/main/java/com/aerokube/lightning/ExtensionCapabilities.java rename to lightning/src/main/java/com/aerokube/lightning/ExtensionCapabilities.java diff --git a/src/main/java/com/aerokube/lightning/FileUtils.java b/lightning/src/main/java/com/aerokube/lightning/FileUtils.java similarity index 100% rename from src/main/java/com/aerokube/lightning/FileUtils.java rename to lightning/src/main/java/com/aerokube/lightning/FileUtils.java diff --git a/src/main/java/com/aerokube/lightning/Position.java b/lightning/src/main/java/com/aerokube/lightning/Position.java similarity index 100% rename from src/main/java/com/aerokube/lightning/Position.java rename to lightning/src/main/java/com/aerokube/lightning/Position.java diff --git a/src/main/java/com/aerokube/lightning/Size.java b/lightning/src/main/java/com/aerokube/lightning/Size.java similarity index 100% rename from src/main/java/com/aerokube/lightning/Size.java rename to lightning/src/main/java/com/aerokube/lightning/Size.java diff --git a/src/main/java/com/aerokube/lightning/StdCapabilities.java b/lightning/src/main/java/com/aerokube/lightning/StdCapabilities.java similarity index 100% rename from src/main/java/com/aerokube/lightning/StdCapabilities.java rename to lightning/src/main/java/com/aerokube/lightning/StdCapabilities.java diff --git a/src/main/java/com/aerokube/lightning/StdCookie.java b/lightning/src/main/java/com/aerokube/lightning/StdCookie.java similarity index 100% rename from src/main/java/com/aerokube/lightning/StdCookie.java rename to lightning/src/main/java/com/aerokube/lightning/StdCookie.java diff --git a/src/main/java/com/aerokube/lightning/StdWebDriver.java b/lightning/src/main/java/com/aerokube/lightning/StdWebDriver.java similarity index 99% rename from src/main/java/com/aerokube/lightning/StdWebDriver.java rename to lightning/src/main/java/com/aerokube/lightning/StdWebDriver.java index c70119e..29a254f 100644 --- a/src/main/java/com/aerokube/lightning/StdWebDriver.java +++ b/lightning/src/main/java/com/aerokube/lightning/StdWebDriver.java @@ -744,6 +744,12 @@ public Window switchTo() { execute(() -> contextsApi.switchToWindow(sessionId, switchToWindowRequest)); return this; } + + @Nonnull + @Override + public String getHandle() { + return handle; + } } } @@ -933,6 +939,12 @@ public WebElement sendKeys(@Nonnull String text) { return this; } + @Nonnull + @Override + public byte[] takeScreenshot() { + return screenshot.take(this); + } + @Nonnull @Override public Accessibility accessibility() { diff --git a/src/main/java/com/aerokube/lightning/WebDriver.java b/lightning/src/main/java/com/aerokube/lightning/WebDriver.java similarity index 100% rename from src/main/java/com/aerokube/lightning/WebDriver.java rename to lightning/src/main/java/com/aerokube/lightning/WebDriver.java diff --git a/src/main/java/com/aerokube/lightning/WebDriverException.java b/lightning/src/main/java/com/aerokube/lightning/WebDriverException.java similarity index 100% rename from src/main/java/com/aerokube/lightning/WebDriverException.java rename to lightning/src/main/java/com/aerokube/lightning/WebDriverException.java diff --git a/src/main/java/com/aerokube/lightning/WebDriverExtension.java b/lightning/src/main/java/com/aerokube/lightning/WebDriverExtension.java similarity index 100% rename from src/main/java/com/aerokube/lightning/WebDriverExtension.java rename to lightning/src/main/java/com/aerokube/lightning/WebDriverExtension.java diff --git a/src/main/java/com/aerokube/lightning/WebElement.java b/lightning/src/main/java/com/aerokube/lightning/WebElement.java similarity index 96% rename from src/main/java/com/aerokube/lightning/WebElement.java rename to lightning/src/main/java/com/aerokube/lightning/WebElement.java index 8ad008b..4ae9ce3 100644 --- a/src/main/java/com/aerokube/lightning/WebElement.java +++ b/lightning/src/main/java/com/aerokube/lightning/WebElement.java @@ -51,6 +51,9 @@ public interface WebElement { @Nonnull WebElement sendKeys(@Nonnull String text); + @Nonnull + byte[] takeScreenshot(); + @Nonnull Accessibility accessibility(); diff --git a/src/main/java/com/aerokube/lightning/Window.java b/lightning/src/main/java/com/aerokube/lightning/Window.java similarity index 92% rename from src/main/java/com/aerokube/lightning/Window.java rename to lightning/src/main/java/com/aerokube/lightning/Window.java index 4605690..5e4c125 100644 --- a/src/main/java/com/aerokube/lightning/Window.java +++ b/lightning/src/main/java/com/aerokube/lightning/Window.java @@ -31,4 +31,6 @@ public interface Window { @Nonnull Window switchTo(); + @Nonnull + String getHandle(); } diff --git a/src/main/java/com/aerokube/lightning/extensions/FirefoxCommands.java b/lightning/src/main/java/com/aerokube/lightning/extensions/FirefoxCommands.java similarity index 100% rename from src/main/java/com/aerokube/lightning/extensions/FirefoxCommands.java rename to lightning/src/main/java/com/aerokube/lightning/extensions/FirefoxCommands.java diff --git a/src/main/java/com/aerokube/lightning/extensions/MobileDevice.java b/lightning/src/main/java/com/aerokube/lightning/extensions/MobileDevice.java similarity index 100% rename from src/main/java/com/aerokube/lightning/extensions/MobileDevice.java rename to lightning/src/main/java/com/aerokube/lightning/extensions/MobileDevice.java diff --git a/src/main/java/com/aerokube/lightning/extensions/MoonCapabilities.java b/lightning/src/main/java/com/aerokube/lightning/extensions/MoonCapabilities.java similarity index 100% rename from src/main/java/com/aerokube/lightning/extensions/MoonCapabilities.java rename to lightning/src/main/java/com/aerokube/lightning/extensions/MoonCapabilities.java diff --git a/src/main/java/com/aerokube/lightning/extensions/MoonCommands.java b/lightning/src/main/java/com/aerokube/lightning/extensions/MoonCommands.java similarity index 100% rename from src/main/java/com/aerokube/lightning/extensions/MoonCommands.java rename to lightning/src/main/java/com/aerokube/lightning/extensions/MoonCommands.java diff --git a/src/main/java/com/aerokube/lightning/extensions/SelenoidCapabilities.java b/lightning/src/main/java/com/aerokube/lightning/extensions/SelenoidCapabilities.java similarity index 100% rename from src/main/java/com/aerokube/lightning/extensions/SelenoidCapabilities.java rename to lightning/src/main/java/com/aerokube/lightning/extensions/SelenoidCapabilities.java diff --git a/src/test/java/com/aerokube/lightning/BaseTest.java b/lightning/src/test/java/com/aerokube/lightning/BaseTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/BaseTest.java rename to lightning/src/test/java/com/aerokube/lightning/BaseTest.java diff --git a/src/test/java/com/aerokube/lightning/ChromeCapabilitiesTest.java b/lightning/src/test/java/com/aerokube/lightning/ChromeCapabilitiesTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/ChromeCapabilitiesTest.java rename to lightning/src/test/java/com/aerokube/lightning/ChromeCapabilitiesTest.java diff --git a/src/test/java/com/aerokube/lightning/CookiesTest.java b/lightning/src/test/java/com/aerokube/lightning/CookiesTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/CookiesTest.java rename to lightning/src/test/java/com/aerokube/lightning/CookiesTest.java diff --git a/src/test/java/com/aerokube/lightning/DocumentTest.java b/lightning/src/test/java/com/aerokube/lightning/DocumentTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/DocumentTest.java rename to lightning/src/test/java/com/aerokube/lightning/DocumentTest.java diff --git a/src/test/java/com/aerokube/lightning/EdgeCapabilitiesTest.java b/lightning/src/test/java/com/aerokube/lightning/EdgeCapabilitiesTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/EdgeCapabilitiesTest.java rename to lightning/src/test/java/com/aerokube/lightning/EdgeCapabilitiesTest.java diff --git a/src/test/java/com/aerokube/lightning/ElementsTest.java b/lightning/src/test/java/com/aerokube/lightning/ElementsTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/ElementsTest.java rename to lightning/src/test/java/com/aerokube/lightning/ElementsTest.java diff --git a/src/test/java/com/aerokube/lightning/FirefoxCapabilitiesTest.java b/lightning/src/test/java/com/aerokube/lightning/FirefoxCapabilitiesTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/FirefoxCapabilitiesTest.java rename to lightning/src/test/java/com/aerokube/lightning/FirefoxCapabilitiesTest.java diff --git a/src/test/java/com/aerokube/lightning/FramesTest.java b/lightning/src/test/java/com/aerokube/lightning/FramesTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/FramesTest.java rename to lightning/src/test/java/com/aerokube/lightning/FramesTest.java diff --git a/src/test/java/com/aerokube/lightning/Image.java b/lightning/src/test/java/com/aerokube/lightning/Image.java similarity index 100% rename from src/test/java/com/aerokube/lightning/Image.java rename to lightning/src/test/java/com/aerokube/lightning/Image.java diff --git a/src/test/java/com/aerokube/lightning/NavigationTest.java b/lightning/src/test/java/com/aerokube/lightning/NavigationTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/NavigationTest.java rename to lightning/src/test/java/com/aerokube/lightning/NavigationTest.java diff --git a/src/test/java/com/aerokube/lightning/OperaCapabilitiesTest.java b/lightning/src/test/java/com/aerokube/lightning/OperaCapabilitiesTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/OperaCapabilitiesTest.java rename to lightning/src/test/java/com/aerokube/lightning/OperaCapabilitiesTest.java diff --git a/src/test/java/com/aerokube/lightning/PrintTest.java b/lightning/src/test/java/com/aerokube/lightning/PrintTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/PrintTest.java rename to lightning/src/test/java/com/aerokube/lightning/PrintTest.java diff --git a/src/test/java/com/aerokube/lightning/PromptsTest.java b/lightning/src/test/java/com/aerokube/lightning/PromptsTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/PromptsTest.java rename to lightning/src/test/java/com/aerokube/lightning/PromptsTest.java diff --git a/src/test/java/com/aerokube/lightning/SafariCapabilitiesTest.java b/lightning/src/test/java/com/aerokube/lightning/SafariCapabilitiesTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/SafariCapabilitiesTest.java rename to lightning/src/test/java/com/aerokube/lightning/SafariCapabilitiesTest.java diff --git a/src/test/java/com/aerokube/lightning/ScreenshotTest.java b/lightning/src/test/java/com/aerokube/lightning/ScreenshotTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/ScreenshotTest.java rename to lightning/src/test/java/com/aerokube/lightning/ScreenshotTest.java diff --git a/src/test/java/com/aerokube/lightning/SelenoidCapabilitiesTest.java b/lightning/src/test/java/com/aerokube/lightning/SelenoidCapabilitiesTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/SelenoidCapabilitiesTest.java rename to lightning/src/test/java/com/aerokube/lightning/SelenoidCapabilitiesTest.java diff --git a/src/test/java/com/aerokube/lightning/SessionTest.java b/lightning/src/test/java/com/aerokube/lightning/SessionTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/SessionTest.java rename to lightning/src/test/java/com/aerokube/lightning/SessionTest.java diff --git a/src/test/java/com/aerokube/lightning/TimeoutsTest.java b/lightning/src/test/java/com/aerokube/lightning/TimeoutsTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/TimeoutsTest.java rename to lightning/src/test/java/com/aerokube/lightning/TimeoutsTest.java diff --git a/src/test/java/com/aerokube/lightning/WindowsTest.java b/lightning/src/test/java/com/aerokube/lightning/WindowsTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/WindowsTest.java rename to lightning/src/test/java/com/aerokube/lightning/WindowsTest.java diff --git a/src/test/java/com/aerokube/lightning/extensions/FirefoxCommandsTest.java b/lightning/src/test/java/com/aerokube/lightning/extensions/FirefoxCommandsTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/extensions/FirefoxCommandsTest.java rename to lightning/src/test/java/com/aerokube/lightning/extensions/FirefoxCommandsTest.java diff --git a/src/test/java/com/aerokube/lightning/extensions/SelenoidTest.java b/lightning/src/test/java/com/aerokube/lightning/extensions/SelenoidTest.java similarity index 100% rename from src/test/java/com/aerokube/lightning/extensions/SelenoidTest.java rename to lightning/src/test/java/com/aerokube/lightning/extensions/SelenoidTest.java diff --git a/src/test/resources/crx/content-script.js b/lightning/src/test/resources/crx/content-script.js similarity index 100% rename from src/test/resources/crx/content-script.js rename to lightning/src/test/resources/crx/content-script.js diff --git a/src/test/resources/crx/manifest.json b/lightning/src/test/resources/crx/manifest.json similarity index 100% rename from src/test/resources/crx/manifest.json rename to lightning/src/test/resources/crx/manifest.json diff --git a/lightning/src/test/resources/log4j.properties b/lightning/src/test/resources/log4j.properties new file mode 100644 index 0000000..daa066a --- /dev/null +++ b/lightning/src/test/resources/log4j.properties @@ -0,0 +1,10 @@ +# suppress inspection "UnusedProperty" for whole file +log4j.rootLogger=INFO, out + +# CONSOLE appender not used by default +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.ConversionPattern=%d %-5p %c{1} - %m%n +log4j.throwableRenderer=org.apache.log4j.EnhancedThrowableRenderer + +log4j.logger.org.testcontainers = ERROR \ No newline at end of file diff --git a/src/test/resources/self-signed-root-ca.crt b/lightning/src/test/resources/self-signed-root-ca.crt similarity index 100% rename from src/test/resources/self-signed-root-ca.crt rename to lightning/src/test/resources/self-signed-root-ca.crt diff --git a/src/test/resources/test.crx b/lightning/src/test/resources/test.crx similarity index 100% rename from src/test/resources/test.crx rename to lightning/src/test/resources/test.crx diff --git a/src/test/resources/test.xpi b/lightning/src/test/resources/test.xpi similarity index 100% rename from src/test/resources/test.xpi rename to lightning/src/test/resources/test.xpi diff --git a/src/test/resources/xpi/content-script.js b/lightning/src/test/resources/xpi/content-script.js similarity index 100% rename from src/test/resources/xpi/content-script.js rename to lightning/src/test/resources/xpi/content-script.js diff --git a/src/test/resources/xpi/manifest.json b/lightning/src/test/resources/xpi/manifest.json similarity index 100% rename from src/test/resources/xpi/manifest.json rename to lightning/src/test/resources/xpi/manifest.json diff --git a/pom.xml b/pom.xml index 816c742..c99dd6a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,135 +5,76 @@ 4.0.0 com.aerokube.lightning - lightning + lightning-parent 1.2.2-SNAPSHOT + pom - Lightning - Lightweight and lightning fast WebDriver client library + Lightning Parent + Lightweight and lightning fast WebDriver client library for Java and related components https://github.com/aerokube/lightning-java 11 11 UTF-8 - 1.6.6 - 1.1.2 - 5.1.0 - 2.13.3 - 2.13.3 - 5.8.2 - 2.2 - 1.17.1 - 1.7.36 2.22.2 3.2.1 3.3.1 3.0.1 1.6.8 + 5.8.2 + 2.2 + 1.17.1 + 1.7.36 - - - com.fasterxml.jackson.core - jackson-databind - ${jackson-databind.version} - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-datatype.version} - - - org.openapitools - jackson-databind-nullable - 0.2.2 - - - javax.ws.rs - javax.ws.rs-api - 2.1.1 - - - io.swagger - swagger-annotations - ${swagger.version} - - - com.google.code.findbugs - jsr305 - 3.0.2 - - - javax.annotation - javax.annotation-api - 1.3.2 - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - - - org.hamcrest - hamcrest - ${hamcrest.version} - test - - - org.testcontainers - testcontainers - ${testcontainers.version} - test - - - org.testcontainers - junit-jupiter - ${testcontainers.version} - test - - - net.lightbody.bmp - browsermob-core - 2.1.5 - test - - - org.slf4j - slf4j-log4j12 - ${slf4j-log4j12.version} - test - - + + lightning + lightning-adapter + + + + + + com.aerokube.lightning + lightning + ${project.version} + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + org.hamcrest + hamcrest + ${hamcrest.version} + test + + + org.testcontainers + testcontainers + ${testcontainers.version} + test + + + org.testcontainers + junit-jupiter + ${testcontainers.version} + test + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + test + + + - - org.openapitools - openapi-generator-maven-plugin - ${openapi-plugin.version} - - - - generate - - - com.aerokube.lightning.model - com.aerokube.lightning.api - https://github.com/aerokube/selenium-openapi/releases/download/${openapi-spec.version}/selenium.yaml - java - false - false - true - true - native - - java8 - - - - - org.apache.maven.plugins maven-surefire-plugin