From 253cf6d657f8ddbcbd15d2aeb648ad4d1b161cc7 Mon Sep 17 00:00:00 2001 From: "N. Dimer" Date: Mon, 2 Feb 2026 16:37:23 +0100 Subject: [PATCH 1/4] Add CbLink and related annotations + upgrade Selenium version. --- .../common/annotation/CbFailure.java | 17 +++++++++++ .../common/annotation/CbFailures.java | 12 ++++++++ .../cloudbeat/common/annotation/CbJira.java | 14 +++++++++ .../common/annotation/CbJiraLinks.java | 11 +++++++ .../cloudbeat/common/annotation/CbLink.java | 29 +++++++++++++++++++ .../cloudbeat/common/annotation/CbLinks.java | 12 ++++++++ .../cloudbeat/common/annotation/CbXray.java | 14 +++++++++ .../common/annotation/CbXrayLinks.java | 11 +++++++ .../common/annotation/FailurePolicy.java | 17 ----------- cb-kit-selenium4/pom.xml | 4 +-- .../io/cloudbeat/selenium/DevToolsHelper.java | 4 +-- .../selenium/Selenium4WebDriver.java | 14 +++++---- pom.xml | 2 +- 13 files changed, 133 insertions(+), 28 deletions(-) create mode 100755 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbFailure.java create mode 100755 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbFailures.java create mode 100644 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbJira.java create mode 100644 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbJiraLinks.java create mode 100755 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbLink.java create mode 100755 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbLinks.java create mode 100644 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbXray.java create mode 100644 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbXrayLinks.java delete mode 100755 cb-kit-common/src/main/java/io/cloudbeat/common/annotation/FailurePolicy.java diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbFailure.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbFailure.java new file mode 100755 index 0000000..2f03746 --- /dev/null +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbFailure.java @@ -0,0 +1,17 @@ +package io.cloudbeat.common.annotation; + +import io.cloudbeat.common.reporter.model.TestStatus; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +@Documented +@Inherited +@Repeatable(CbFailures.class) +public @interface CbFailure { + Class value(); + String reason() default ""; + String status() default ""; +} + diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbFailures.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbFailures.java new file mode 100755 index 0000000..a119114 --- /dev/null +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbFailures.java @@ -0,0 +1,12 @@ +package io.cloudbeat.common.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface CbFailures { + CbFailure[] value(); +} + diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbJira.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbJira.java new file mode 100644 index 0000000..442edba --- /dev/null +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbJira.java @@ -0,0 +1,14 @@ +package io.cloudbeat.common.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Repeatable(CbJiraLinks.class) +public @interface CbJira { + String value(); + String source() default CbLink.SRC_JIRA; + String type() default ""; +} diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbJiraLinks.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbJiraLinks.java new file mode 100644 index 0000000..11c9289 --- /dev/null +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbJiraLinks.java @@ -0,0 +1,11 @@ +package io.cloudbeat.common.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface CbJiraLinks { + CbJira[] value(); +} diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbLink.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbLink.java new file mode 100755 index 0000000..f882f68 --- /dev/null +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbLink.java @@ -0,0 +1,29 @@ +package io.cloudbeat.common.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Repeatable(CbLinks.class) +public @interface CbLink { + String value(); + String source() default ""; // e.g. Jira, XRay, ADO, etc. + String type() default ""; // e.g. Story, Task, Test Plan, Test Case, etc. + // Possible "source" values + public static final String SRC_URL = "url"; + public static final String SRC_JIRA = "jira"; + public static final String SRC_XRAY = "xray"; + public static final String SRC_AZURE_DEVOPS = "ado"; + public static final String SRC_TESTRAIL = "testrail"; + + // Possible "type" values + public static final String TYPE_EPIC = "epic"; + public static final String TYPE_STORY = "story"; + public static final String TYPE_TASK = "task"; + public static final String TYPE_TEST_PLAN = "plan"; + public static final String TYPE_TEST_CASE = "case"; + public static final String TYPE_TEST_BUG = "bug"; +} + diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbLinks.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbLinks.java new file mode 100755 index 0000000..83aed70 --- /dev/null +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbLinks.java @@ -0,0 +1,12 @@ +package io.cloudbeat.common.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface CbLinks { + CbLink[] value(); +} + diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbXray.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbXray.java new file mode 100644 index 0000000..367c585 --- /dev/null +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbXray.java @@ -0,0 +1,14 @@ +package io.cloudbeat.common.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Repeatable(CbXrayLinks.class) +public @interface CbXray { + String value(); + String source() default CbLink.SRC_XRAY; + String type() default ""; +} diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbXrayLinks.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbXrayLinks.java new file mode 100644 index 0000000..ad873ac --- /dev/null +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/CbXrayLinks.java @@ -0,0 +1,11 @@ +package io.cloudbeat.common.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface CbXrayLinks { + CbXray[] value(); +} diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/FailurePolicy.java b/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/FailurePolicy.java deleted file mode 100755 index 91e1526..0000000 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/annotation/FailurePolicy.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.cloudbeat.common.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Type; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.PARAMETER, ElementType.FIELD}) -public @interface FailurePolicy { - //Type exception() default Exception; - String action() default ""; - String value() default ""; - String reason() default ""; -} - diff --git a/cb-kit-selenium4/pom.xml b/cb-kit-selenium4/pom.xml index 22c6ba6..50a2e6f 100755 --- a/cb-kit-selenium4/pom.xml +++ b/cb-kit-selenium4/pom.xml @@ -19,8 +19,8 @@ - 4.27.0 - v131 + 4.39.0 + v143 9.2.2 diff --git a/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/DevToolsHelper.java b/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/DevToolsHelper.java index 3c274a6..6b059bd 100644 --- a/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/DevToolsHelper.java +++ b/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/DevToolsHelper.java @@ -2,8 +2,8 @@ import io.cloudbeat.common.reporter.model.LogLevel; import org.openqa.selenium.devtools.events.ConsoleEvent; -import org.openqa.selenium.devtools.v131.runtime.model.PropertyPreview; -import org.openqa.selenium.devtools.v131.runtime.model.RemoteObject; +import org.openqa.selenium.devtools.v143.runtime.model.PropertyPreview; +import org.openqa.selenium.devtools.v143.runtime.model.RemoteObject; import java.util.List; import java.util.logging.Level; diff --git a/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/Selenium4WebDriver.java b/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/Selenium4WebDriver.java index 5cc1c30..eba7d63 100755 --- a/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/Selenium4WebDriver.java +++ b/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/Selenium4WebDriver.java @@ -12,12 +12,12 @@ import org.openqa.selenium.devtools.Command; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.HasDevTools; -import org.openqa.selenium.devtools.v131.network.Network; -import org.openqa.selenium.devtools.v131.network.model.RequestId; -import org.openqa.selenium.devtools.v131.network.model.ResourceTiming; -import org.openqa.selenium.devtools.v131.performance.Performance; -import org.openqa.selenium.devtools.v131.performance.model.Metric; -import org.openqa.selenium.devtools.v131.runtime.Runtime; +import org.openqa.selenium.devtools.v143.network.Network; +import org.openqa.selenium.devtools.v143.network.model.RequestId; +import org.openqa.selenium.devtools.v143.network.model.ResourceTiming; +import org.openqa.selenium.devtools.v143.performance.Performance; +import org.openqa.selenium.devtools.v143.performance.model.Metric; +import org.openqa.selenium.devtools.v143.runtime.Runtime; import org.openqa.selenium.logging.LogEntries; import org.openqa.selenium.logging.LogType; @@ -238,6 +238,8 @@ public void enableDevToolsNetworkCapturing() { try { devTools.createSessionIfThereIsNotOne(); devTools.send(Network.enable( + Optional.empty(), + Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty())); diff --git a/pom.xml b/pom.xml index 6a0c437..9c02eee 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 - 1.0.15 + 1.0.17 UTF-8 1.9.7 From 8c7fcca03cb84ffce6594186058e7115bc12daa6 Mon Sep 17 00:00:00 2001 From: "N. Dimer" Date: Tue, 24 Feb 2026 15:16:50 +0200 Subject: [PATCH 2/4] Bump kit version to 1.0.18. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9c02eee..e7b53a6 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 - 1.0.17 + 1.0.18 UTF-8 1.9.7 From c73dd1b50e3c09a172d88573de99936a7f42f4f2 Mon Sep 17 00:00:00 2001 From: "N. Dimer" Date: Wed, 11 Mar 2026 11:58:37 +0100 Subject: [PATCH 3/4] Add page source auto-save support + Selenium exceptions classification + bump version to 1.0.19. --- .../common/helper/AttachmentHelper.java | 15 ++++++++++ .../common/reporter/CbTestReporter.java | 25 +++++++++++++++- .../reporter/model/AttachmentSubType.java | 6 +++- .../common/reporter/model/AttachmentType.java | 3 +- .../common/reporter/model/FailureResult.java | 22 ++++++++++++-- .../wrapper/webdriver/AbstractWebDriver.java | 1 + .../webdriver/WebDriverEventHandler.java | 29 ++++++++++++++----- .../wrapper/webdriver/WrapperOptions.java | 18 ++++++++++++ .../io/cloudbeat/junit/CbJunitExtension.java | 4 +++ .../selenium/CbWebDriverListener.java | 2 +- .../selenium/Selenium4WebDriver.java | 19 +++++++++++- pom.xml | 2 +- 12 files changed, 130 insertions(+), 16 deletions(-) diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/helper/AttachmentHelper.java b/cb-kit-common/src/main/java/io/cloudbeat/common/helper/AttachmentHelper.java index 915d663..454dae3 100644 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/helper/AttachmentHelper.java +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/helper/AttachmentHelper.java @@ -10,6 +10,7 @@ import io.cloudbeat.common.reporter.model.AttachmentType; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -55,6 +56,20 @@ public static Attachment prepareScreenshotAttachment(final byte[] data) { } return attachment; } + public static Attachment preparePageSourceAttachment(final String pageSource) { + if (pageSource == null) return null; + Attachment attachment = new Attachment(AttachmentType.SNAPSHOT); + attachment.setSubtype(AttachmentSubType.SNAPSHOT_HTML); + final String fileExtension = "htm"; + Path htmlFilePath = getAttachmentFilePath(attachment, fileExtension); + if (htmlFilePath == null) return null; + try { + Files.write(htmlFilePath, pageSource.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + return null; + } + return attachment; + } public static Attachment prepareHarAttachment(final HarLog harLog) { Attachment attachment = new Attachment(AttachmentType.HAR); final String fileExtension = "har"; diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/CbTestReporter.java b/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/CbTestReporter.java index f169c86..5bd0340 100755 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/CbTestReporter.java +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/CbTestReporter.java @@ -671,6 +671,7 @@ else if (lastSuiteResult.get() != null) Attachment attachment = AttachmentHelper.prepareScreencastAttachment(videoFilePath); resultWithAttachment.addAttachment(attachment); } + public void addScreencastAttachment(final byte[] videoData, final boolean addToStep) { final IResultWithAttachment resultWithAttachment; if (addToStep && startedStepsQueue.get() != null && !startedStepsQueue.get().isEmpty()) { @@ -709,7 +710,29 @@ else if (lastSuiteResult.get() != null) resultWithAttachment.addAttachment(attachment); } - + public void addPageSourceAttachment(final String pageSource, final boolean addToStep) { + final IResultWithAttachment resultWithAttachment; + if (addToStep && startedStepsQueue.get() != null && !startedStepsQueue.get().isEmpty()) { + resultWithAttachment = startedStepsQueue.get().peek(); + } + else if (!addToStep) { + if (lastCaseResult.get() != null) + resultWithAttachment = lastCaseResult.get(); + else if (lastSuiteResult.get() != null) + resultWithAttachment = lastSuiteResult.get(); + else + return; + } + else + return; + Attachment attachment = AttachmentHelper.preparePageSourceAttachment(pageSource); + resultWithAttachment.addAttachment(attachment); + } + public void addPageSourceAttachment(final String pageSource, final IResultWithAttachment result) { + if (result == null) return; + Attachment attachment = AttachmentHelper.preparePageSourceAttachment(pageSource); + result.addAttachment(attachment); + } private static String getHostName() { try { diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/AttachmentSubType.java b/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/AttachmentSubType.java index 773aad4..4b03eef 100755 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/AttachmentSubType.java +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/AttachmentSubType.java @@ -5,7 +5,11 @@ public enum AttachmentSubType { IMAGE_SCREENSHOT("screenshot"), VIDEO_SCREENCAST("screencast"), - NETWORK_HAR("har"); + NETWORK_HAR("har"), + SNAPSHOT_PLAYWRIGHT("playwrightTrace"), + SNAPSHOT_XML("xml"), + SNAPSHOT_HTML("html"), + SNAPSHOT_TEXT("text"); private final String value; diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/AttachmentType.java b/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/AttachmentType.java index 759920e..ef59dff 100755 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/AttachmentType.java +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/AttachmentType.java @@ -8,7 +8,8 @@ public enum AttachmentType { TEXT("text"), LOG("log"), HAR("har"), - OTHER("other"); + OTHER("other"), + SNAPSHOT("snapshot"); private final String value; diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/FailureResult.java b/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/FailureResult.java index f1dfdd2..c753e47 100755 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/FailureResult.java +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/reporter/model/FailureResult.java @@ -3,7 +3,6 @@ import io.cloudbeat.common.CbTestContext; import io.cloudbeat.common.helper.StackTraceHelper; import io.cloudbeat.common.helper.WebDriverHelper; - import java.io.PrintWriter; import java.io.StringWriter; @@ -32,12 +31,12 @@ public FailureResult(Throwable throwable) { StackTraceElement[] filteredStackTrace = StackTraceHelper.getStackTraceStartingFromPackage(throwable.getStackTrace(), testPackageName); this.subtype = throwable.getClass().getSimpleName(); - this.type = throwable.getClass().getSimpleName(); + this.type = getFailureType(throwable); this.data = stackTrace; this.stacktrace = StackTraceHelper.stackTraceToStringArray(filteredStackTrace); this.message = throwable.getMessage(); if(this.message == null) { - this.message = "UNKNOWN_ERROR "; + this.message = "UNKNOWN_ERROR"; } // set location attribute if (filteredStackTrace.length > 0) { @@ -52,6 +51,23 @@ private static String getTestPackageName() { return ctx.getCurrentTestClass().getPackage().getName(); return null; } + private static String getFailureType(Throwable throwable) { + String className = throwable.getClass().getName(); + if (className.startsWith("org.openqa.selenium")) { + String simpleName = throwable.getClass().getSimpleName(); + if (simpleName.equals("NoSuchElementException")) + return "ELEMENT_NOT_FOUND"; + if (simpleName.equals("TimeoutException")) + return "TIMEOUT"; + if (simpleName.equals("ElementNotVisibleException") + || simpleName.equals("ElementNotInteractableException")) + return "ELEMENT_NOT_VISIBLE"; + return "SELENIUM_ERROR"; + } + if (throwable instanceof AssertionError) + return "ASSERT_ERROR"; + return FAILURE_TYPE; + } public String getType() { return type; diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/AbstractWebDriver.java b/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/AbstractWebDriver.java index b072369..64e011b 100755 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/AbstractWebDriver.java +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/AbstractWebDriver.java @@ -26,4 +26,5 @@ public interface AbstractWebDriver { public void disableDevToolsNetworkCapturing(); public HarLog getHarLog(); public String getScreenshot(); + public String getPageSource(); } diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/WebDriverEventHandler.java b/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/WebDriverEventHandler.java index cfb1719..1227349 100755 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/WebDriverEventHandler.java +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/WebDriverEventHandler.java @@ -295,16 +295,31 @@ public void afterSwitchToWindow(final String windowName) { } - public void onException(final Throwable throwable) { + public void onException(final Throwable throwable, boolean takeScreenshot, boolean savePageSource) { + String screenshot = null; + String pageSource = null; + // try to take a screenshot try { - // try to take a screenshot - String screenshot = wrapper.getScreenshot(); - if (lastStepId != null) - reporter.failStep(lastStepId, throwable, screenshot); - else - reporter.setScreenshotOnException(screenshot); + if (takeScreenshot) + screenshot = wrapper.getScreenshot(); } catch (Throwable e) {} + // try to take a page source + try { + if (savePageSource) + pageSource = wrapper.getPageSource(); + } + catch (Throwable e) {} + if (lastStepId != null) { + StepResult stepResult = reporter.failStep(lastStepId, throwable, screenshot); + if (stepResult != null && pageSource != null) + reporter.addPageSourceAttachment(pageSource, stepResult); + } + else { + reporter.setScreenshotOnException(screenshot); + if (pageSource != null) + reporter.addPageSourceAttachment(pageSource, true); + } } public void beforeGetText(final AbstractWebElement elm) { diff --git a/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/WrapperOptions.java b/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/WrapperOptions.java index b12e25d..debcdf3 100644 --- a/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/WrapperOptions.java +++ b/cb-kit-common/src/main/java/io/cloudbeat/common/wrapper/webdriver/WrapperOptions.java @@ -4,6 +4,8 @@ public final class WrapperOptions { private boolean ignoreFindElement = true; private boolean ignoreFindElements = false; private boolean fullPageScreenshot = true; + private boolean takeScreenshotOnError = true; + private boolean savePageSourceOnError = false; public WrapperOptions() {} @@ -11,6 +13,10 @@ public WrapperOptions(boolean ignoreFindElement, boolean fullPageScreenshot) { this.ignoreFindElement = ignoreFindElement; this.fullPageScreenshot = fullPageScreenshot; } + public WrapperOptions(boolean ignoreFindElement, boolean fullPageScreenshot, boolean takeScreenshotOnError, boolean savePageSourceOnError) { + this.ignoreFindElement = ignoreFindElement; + this.fullPageScreenshot = fullPageScreenshot; + } public boolean isIgnoreFindElement() { return ignoreFindElement; @@ -23,6 +29,12 @@ public boolean isIgnoreFindElements() { public boolean isFullPageScreenshot() { return fullPageScreenshot; } + public boolean isTakeScreenshotOnError() { + return takeScreenshotOnError; + } + public boolean isSavePageSourceOnError() { + return savePageSourceOnError; + } public void setIgnoreFindElement(boolean ignoreFindElement) { this.ignoreFindElement = ignoreFindElement; @@ -35,4 +47,10 @@ public void setIgnoreFindElements(boolean ignoreFindElements) { public void setFullPageScreenshot(boolean fullPageScreenshot) { this.fullPageScreenshot = fullPageScreenshot; } + public void setTakeScreenshotOnError(boolean takeScreenshotOnError) { + this.takeScreenshotOnError = takeScreenshotOnError; + } + public void setSavePageSourceOnError(boolean savePageSourceOnError) { + this.savePageSourceOnError = savePageSourceOnError; + } } diff --git a/cb-kit-junit5/src/main/java/io/cloudbeat/junit/CbJunitExtension.java b/cb-kit-junit5/src/main/java/io/cloudbeat/junit/CbJunitExtension.java index a51c388..fa021ca 100644 --- a/cb-kit-junit5/src/main/java/io/cloudbeat/junit/CbJunitExtension.java +++ b/cb-kit-junit5/src/main/java/io/cloudbeat/junit/CbJunitExtension.java @@ -11,6 +11,7 @@ import io.cloudbeat.common.reporter.model.StepResult; import io.cloudbeat.common.wrapper.webdriver.WebDriverWrapper; +import io.cloudbeat.common.wrapper.webdriver.WrapperOptions; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.*; @@ -99,6 +100,9 @@ public static Map getCapabilities() { public static D wrapWebDriver(D driver) { return ctx.wrapWebDriver(driver); } + public static D wrapWebDriver(D driver, WrapperOptions options) { + return ctx.wrapWebDriver(driver, options); + } public static L getWebDriverListener(D driver) { return ctx.getWebDriverListener(driver); diff --git a/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/CbWebDriverListener.java b/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/CbWebDriverListener.java index bc3f352..c3c94bb 100755 --- a/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/CbWebDriverListener.java +++ b/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/CbWebDriverListener.java @@ -31,7 +31,7 @@ public CbWebDriverListener(WebDriverEventHandler eventHandler, WrapperOptions op @Override public void onError(Object target, Method method, Object[] args, InvocationTargetException e) { if (e.getTargetException() != null) - eventHandler.onException(e.getTargetException()); + eventHandler.onException(e.getTargetException(), options.isTakeScreenshotOnError(), options.isSavePageSourceOnError()); WebDriverListener.super.onError(target, method, args, e); } diff --git a/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/Selenium4WebDriver.java b/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/Selenium4WebDriver.java index eba7d63..5fce3f5 100755 --- a/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/Selenium4WebDriver.java +++ b/cb-kit-selenium4/src/main/java/io/cloudbeat/selenium/Selenium4WebDriver.java @@ -169,6 +169,8 @@ public void addNavigationTimingStats(Map stats) { @Override public void addBrowserLogs(List logs) { + if (isSessionClosed(driver)) + return; if (logs == null) return; // if we are collecting browser logs through DevTools if (isDevToolsConsoleLogsEnabled) { @@ -207,6 +209,8 @@ private static String extractLogMessageText(String message) { @Override public void addLogcatLogs(List logs) { + if (isSessionClosed(driver)) + return; if (logs == null) return; LogEntries logcatLogs = driver.manage().logs().get("logcat"); if (logcatLogs == null) @@ -224,10 +228,12 @@ public void addLogcatLogs(List logs) { @Override public String getScreenshot() { try { + if (isSessionClosed(driver)) + return null; String screenshotBase64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64); return screenshotBase64; } - catch (Exception e) { + catch (Throwable e) { System.err.println("Selenium4WebDriver - failed to take a screenshot: " + e.toString()); } return null; @@ -410,6 +416,8 @@ public void disableDevToolsNetworkCapturing() { } public HarLog getHarLog() { try { + if (isSessionClosed(driver)) + return null; if (!driver.manage().logs().getAvailableLogTypes().contains("performance")) return null; LogEntries perfLogs = driver.manage().logs().get("performance"); @@ -429,4 +437,13 @@ public HarLog getHarLog() { networkLogsLock.unlock(); return harEntriesCopy;*/ } + public String getPageSource() { + if (isSessionClosed(driver)) + return null; + return driver.getPageSource(); + } + private static boolean isSessionClosed(WebDriver driver) { + return driver instanceof org.openqa.selenium.remote.RemoteWebDriver && + ((org.openqa.selenium.remote.RemoteWebDriver) driver).getSessionId() == null; + } } diff --git a/pom.xml b/pom.xml index e7b53a6..baa73c2 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 - 1.0.18 + 1.0.19 UTF-8 1.9.7 From b00ffec8aef53a68e40c28046e7a509691c1573f Mon Sep 17 00:00:00 2001 From: "N. Dimer" Date: Thu, 12 Mar 2026 14:57:06 +0100 Subject: [PATCH 4/4] Add attachPageSource methods in CbJunitExtension class. --- .../java/io/cloudbeat/junit/CbJunitExtension.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cb-kit-junit5/src/main/java/io/cloudbeat/junit/CbJunitExtension.java b/cb-kit-junit5/src/main/java/io/cloudbeat/junit/CbJunitExtension.java index fa021ca..0202ea5 100644 --- a/cb-kit-junit5/src/main/java/io/cloudbeat/junit/CbJunitExtension.java +++ b/cb-kit-junit5/src/main/java/io/cloudbeat/junit/CbJunitExtension.java @@ -184,6 +184,18 @@ public static boolean attachScreenRecording(final TestInfo testInfo) { return true; } + public static void attachPageSource(final String pageSource) { + CbTestReporter reporter = getReporter(); + if (reporter != null) + reporter.addPageSourceAttachment(pageSource, true); + } + + public static void attachPageSource(final String pageSource, boolean addToStep) { + CbTestReporter reporter = getReporter(); + if (reporter != null) + reporter.addPageSourceAttachment(pageSource, addToStep); + } + private static String getVideoName(final TestInfo testInfo) { if (testInfo.getTestMethod().isPresent()) { return Math.abs(testInfo.getTestMethod().get().hashCode()) + "";