removePicsCmd = ImmutableMap.of("command", "rm", "args", removePicsArgs);
+ ((AndroidDriver) MobileUtils.getMobileDriver(driver))
+ .executeScript("mobile: shell", removePicsCmd);
+ } catch (Exception e) {
+ logger.info(e.getMessage());
+ logger.info(
+ "\n\nTo run any shell commands, we need to set the 'relaxed security' flag. Please start your Appium server with [appium --relaxed-security]\n");
+ }
+ }
+
+ /**
+ * Camera image injection or camera mocking Inject any image and then use device Camera with that
+ * image in front
+ *
+ * Need to use this caps to Enable image-injection on RDC ->
+ * desiredCapabilities.setCapability("sauceLabsImageInjectionEnabled", true);
+ *
+ *
Link - https://docs.saucelabs.com/mobile-apps/features/camera-image-injection/
+ *
+ * @param driver
+ * @param fileLocation
+ */
+ public static void injectImageToSauce(WebDriver driver, String fileLocation) {
+ try {
+ logger.info("Injecting [{}] file to Sauce device.", fileLocation);
+ FileInputStream in = new FileInputStream(fileLocation);
+ String qrCodeImage = Base64.getEncoder().encodeToString(IOUtils.toByteArray(in));
+
+ // Provide the transformed image to the device
+ ((JavascriptExecutor) driver).executeScript("sauce:inject-image=" + qrCodeImage);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new TestException("Image injection error.");
+ }
+ }
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/testdata/TestDataProvider.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/testdata/TestDataProvider.java
new file mode 100644
index 0000000..843aeb5
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/testdata/TestDataProvider.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.testdata;
+
+import java.util.Collection;
+
+public interface TestDataProvider {
+
+ /**
+ * read single value from test data file
+ *
+ * @param dataPathSyntax
+ * @param
+ * @return
+ */
+ T readSingleValueFromTestDataFile(String dataPathSyntax);
+
+ /**
+ * read collection of values from test data file
+ *
+ * @param dataPathSyntax
+ * @param
+ * @return
+ */
+ > C readValuesFromTestDataFile(String dataPathSyntax);
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/testdata/yaml/YamlTestDataProvider.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/testdata/yaml/YamlTestDataProvider.java
new file mode 100644
index 0000000..7fb27ed
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/testdata/yaml/YamlTestDataProvider.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.testdata.yaml;
+
+import com.applause.auto.helpers.testdata.TestDataProvider;
+import io.github.yamlpath.YamlExpressionParser;
+import io.github.yamlpath.YamlPath;
+import java.io.FileInputStream;
+import java.util.Set;
+import lombok.Getter;
+import lombok.SneakyThrows;
+
+/** Yaml test data reader based on https://github.com/yaml-path/YamlPath */
+public class YamlTestDataProvider implements TestDataProvider {
+
+ @Getter private final String yamlTestDataFilePath;
+
+ private YamlExpressionParser yamlExpressionParser;
+
+ @SneakyThrows
+ public YamlTestDataProvider(String yamlTestDataFilePath) {
+ this.yamlTestDataFilePath = yamlTestDataFilePath;
+ this.yamlExpressionParser = YamlPath.from(new FileInputStream(yamlTestDataFilePath));
+ }
+
+ @Override
+ public T readSingleValueFromTestDataFile(String yamlPathSyntax) {
+ return yamlExpressionParser.readSingle(yamlPathSyntax);
+ }
+
+ @Override
+ public Set readValuesFromTestDataFile(String yamlPathSyntax) {
+ return yamlExpressionParser.read(yamlPathSyntax);
+ }
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/AwaitilityWaitUtils.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/AwaitilityWaitUtils.java
new file mode 100644
index 0000000..80dc8e1
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/AwaitilityWaitUtils.java
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.util;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
+import org.awaitility.Awaitility;
+
+/** Awaitility Wait Utils */
+public class AwaitilityWaitUtils {
+
+ /**
+ * Wait for callable state with predicate and return it's value
+ *
+ * @param - callable actions type parameter
+ * @param callable - actions to call during wait
+ * @param predicate - predicate to match for actions that will be called during wait
+ * @param waitInterval - wait interval in seconds
+ * @param pollingInterval - polling timeout for wait interval in seconds
+ * @param alias - text alias for this wait
+ * @return T - object instance that will be returned from callable actions during wait
+ */
+ public static T waitForCondition(
+ Callable callable,
+ Predicate predicate,
+ int waitInterval,
+ int pollingInterval,
+ String alias) {
+ return Awaitility.with()
+ .pollInterval(pollingInterval, TimeUnit.SECONDS)
+ .pollInSameThread()
+ .atMost(waitInterval, TimeUnit.SECONDS)
+ .ignoreExceptions()
+ .alias(alias)
+ .until(callable, predicate);
+ }
+
+ /**
+ * Wait for callable state with predicate and return it's value
+ *
+ * @param callable - boolean callable actions state that will be checked during wait
+ * @param waitInterval - wait interval in seconds
+ * @param pollingInterval - polling timeout for wait interval in seconds
+ * @param alias - text alias for this wait
+ */
+ public static void waitForCondition(
+ Callable callable, int waitInterval, int pollingInterval, String alias) {
+ Awaitility.with()
+ .pollInterval(pollingInterval, TimeUnit.SECONDS)
+ .pollInSameThread()
+ .atMost(waitInterval, TimeUnit.SECONDS)
+ .ignoreExceptions()
+ .alias(alias)
+ .until(callable);
+ }
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/GenericObjectMapper.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/GenericObjectMapper.java
new file mode 100644
index 0000000..4407ee9
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/GenericObjectMapper.java
@@ -0,0 +1,25 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.util;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Getter;
+
+public class GenericObjectMapper {
+ @Getter private static final ObjectMapper objectMapper = new ObjectMapper();
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/RandomUtils.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/RandomUtils.java
new file mode 100644
index 0000000..9efecf0
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/RandomUtils.java
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.util;
+
+import com.github.javafaker.Faker;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/** Random dat utils */
+public class RandomUtils {
+
+ private static final Logger logger = LogManager.getLogger(RandomUtils.class);
+
+ /**
+ * Get Faker object for further fake data generation * /
+ *
+ * @return Faker - faker object from Faker library https://github.com/DiUS/java-faker
+ */
+ public static Faker getFaker() {
+ return new Faker();
+ }
+
+ /**
+ * Get random password
+ *
+ * @param upperCaseSymbolsCount - count of upper case symbols
+ * @param lowCaseSymbolsCount - count of lower case symbols
+ * @param numericSymbolsCount - numeric symbols count
+ * @param withSpecialCharacter - should include special character or not
+ * @return generated password
+ */
+ public static String getRandomValidUserAccountPassword(
+ int upperCaseSymbolsCount,
+ int lowCaseSymbolsCount,
+ int numericSymbolsCount,
+ boolean withSpecialCharacter) {
+ StringBuilder randomPasswordStringBuilder =
+ new StringBuilder()
+ .append(RandomStringUtils.randomAlphabetic(upperCaseSymbolsCount).toUpperCase())
+ .append(RandomStringUtils.randomAlphabetic(lowCaseSymbolsCount).toLowerCase())
+ .append(RandomStringUtils.randomNumeric(numericSymbolsCount));
+ if (withSpecialCharacter) {
+ randomPasswordStringBuilder.append("$");
+ }
+ String randomPassword = randomPasswordStringBuilder.toString();
+ logger.info("Newly generated random password is: " + randomPassword);
+ return randomPassword;
+ }
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/ThreadHelper.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/ThreadHelper.java
new file mode 100644
index 0000000..d2cfb45
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/util/ThreadHelper.java
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.util;
+
+/** Utility helper class that provides common actions needed to control the current Thread. */
+public class ThreadHelper {
+
+ private ThreadHelper() {}
+
+ /**
+ * Suspends the current thread for a specified period of milliseconds.
+ *
+ * @param milliseconds A long value that represents the milliseconds.
+ */
+ public static void sleep(long milliseconds) {
+ try {
+ Thread.sleep(milliseconds);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/HtmlUtils.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/HtmlUtils.java
new file mode 100644
index 0000000..4568e6a
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/HtmlUtils.java
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.web;
+
+import com.applause.auto.helpers.util.AwaitilityWaitUtils;
+import java.util.List;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.openqa.selenium.WebDriver;
+import us.codecraft.xsoup.Xsoup;
+
+/** Common methods for HTML-based content. */
+public class HtmlUtils {
+
+ private static final Logger logger = LogManager.getLogger(HtmlUtils.class);
+
+ /**
+ * Wait for page viewport to be not empty
+ *
+ * @param driver - automation driver
+ * @param xpathRootLocator - root Xpath locator for viewport DOM element
+ * @param waitInterval - wait interval to wait for viewport
+ * @param pollingInterval - polling interval for wait of viewport
+ */
+ public static void waitForPageViewPortNotEmpty(
+ WebDriver driver, String xpathRootLocator, int waitInterval, int pollingInterval) {
+ AwaitilityWaitUtils.waitForCondition(
+ () -> {
+ String currentPageSource = driver.getPageSource();
+ boolean gsdHtmlInViewportLoaded =
+ wasHtmlInViewportLoadedByRootElementXpathLocator(currentPageSource, xpathRootLocator);
+ logger.info("Page viewport was loaded correctly: " + gsdHtmlInViewportLoaded);
+ return gsdHtmlInViewportLoaded;
+ },
+ waitInterval,
+ pollingInterval,
+ "Wait for html viewport to be loaded");
+ }
+
+ private static boolean wasHtmlInViewportLoadedByRootElementXpathLocator(
+ String currentHtml, String xpathRootLocator) {
+ Document doc = Jsoup.parse(currentHtml);
+ List list = Xsoup.compile(xpathRootLocator).evaluate(doc).list();
+ return !list.isEmpty();
+ }
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/WebElementUtils.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/WebElementUtils.java
new file mode 100644
index 0000000..559a21e
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/WebElementUtils.java
@@ -0,0 +1,305 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.web;
+
+import com.applause.auto.helpers.util.ThreadHelper;
+import io.appium.java_client.AppiumDriver;
+import io.appium.java_client.PerformsTouchActions;
+import io.appium.java_client.TouchAction;
+import io.appium.java_client.android.AndroidDriver;
+import io.appium.java_client.ios.IOSDriver;
+import io.appium.java_client.touch.offset.PointOption;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.openqa.selenium.*;
+
+/** Common utils for web elements */
+public class WebElementUtils {
+
+ private static final Logger logger = LogManager.getLogger(WebElementUtils.class);
+
+ /**
+ * Get element Y offset
+ *
+ * @param driver - automation driver
+ * @param element - web element
+ * @return element Y offset value
+ */
+ public static int getElementYOffset(WebDriver driver, WebElement element) {
+ int offsetY =
+ Integer.parseInt(
+ ((JavascriptExecutor) driver)
+ .executeScript("return arguments[0].offsetTop", element)
+ .toString());
+ logger.info("Current element" + element + " offset y = " + offsetY);
+ return offsetY;
+ }
+
+ /**
+ * Get element text content with js
+ *
+ * @param driver - automation driver
+ * @param webElementWithTextContent - web element
+ * @return element text content
+ */
+ public static String getElementTextContentWithJS(
+ WebDriver driver, WebElement webElementWithTextContent) {
+ JavascriptExecutor js = (JavascriptExecutor) driver;
+ try {
+ String textContent =
+ (String) js.executeScript("return arguments[0].textContent", webElementWithTextContent);
+ logger.info("Text content is: " + textContent);
+ return textContent;
+ } catch (Exception e) {
+ return StringUtils.EMPTY;
+ }
+ }
+
+ /**
+ * Custom sendkeys by symbol with delay
+ *
+ * @param textBoxElement - web element
+ * @param text - text to input
+ * @param waitBetweenEachInput - wait between input in millis
+ */
+ public static void customSendKeysBySymbolWithDelay(
+ WebElement textBoxElement, String text, int waitBetweenEachInput) {
+ for (int symbolIndex = 0; symbolIndex < text.length(); symbolIndex++) {
+ textBoxElement.sendKeys(Character.toString(text.charAt(symbolIndex)));
+ ThreadHelper.sleep(waitBetweenEachInput);
+ }
+ }
+
+ /**
+ * Clear input field value with backspace with delay
+ *
+ * @param inputWebElement - web element
+ * @param waitBetweenEachDelete - wait between each backspace deletion
+ */
+ public static void clearFieldValueWithBackspaceWithDelay(
+ WebElement inputWebElement, int waitBetweenEachDelete) {
+ int valueCharacters = inputWebElement.getAttribute("value").length();
+ for (int i = 0; i < valueCharacters + 1; i++) {
+ inputWebElement.sendKeys(Keys.BACK_SPACE);
+ ThreadHelper.sleep(waitBetweenEachDelete);
+ }
+ }
+
+ /**
+ * Check whether mobile web execution is being performed
+ *
+ * @param driver - automation driver
+ * @return boolean state whether this kind of driver is mobile one of not
+ */
+ public static boolean isMobileWebExecutionDriver(WebDriver driver) {
+ return driver instanceof AppiumDriver;
+ }
+
+ /**
+ * Clicks an element at an accurate point on devices, with native tap. This method is to mitigate
+ * issues where the different device sizes cause the element locations to differ.
+ *
+ * @param element
+ */
+ public static void clickElementWithNativeTapWithOffset(
+ WebDriver driver, WebElement element, int xOffset, int yOffset, boolean isTablet) {
+ int x = getAccuratePointX(driver, element) + xOffset;
+ int y = getAccuratePointY(driver, element, isTablet) + yOffset;
+ logger.info("Clicking element with native tap at (" + x + ", " + y + ").");
+ new TouchAction((PerformsTouchActions) driver).tap(PointOption.point(x, y)).release().perform();
+ }
+
+ /**
+ * Gets accurate X point for element
+ *
+ * @param element
+ * @return Accurate X point for element
+ */
+ public static int getAccuratePointX(WebDriver driver, WebElement element) {
+ double widthRatio =
+ (double) driver.manage().window().getSize().width
+ / (double) getJavascriptWindowWidth(driver);
+ return (int) (getLocation(driver, element).getX() * widthRatio)
+ + (element.getSize().getWidth() / 2);
+ }
+
+ /**
+ * @return JavaScript window width
+ */
+ public static int getJavascriptWindowWidth(WebDriver driver) {
+ int windowWidth =
+ ((Long)
+ ((JavascriptExecutor) driver)
+ .executeScript("return window.innerWidth || document.body.clientWidth"))
+ .intValue();
+ logger.info("Current window width is: " + windowWidth);
+ return windowWidth;
+ }
+
+ /**
+ * Gets the element location on the screen using JS. TODO: We are currently using this as a
+ * workaround as the default getLocation is not working in W3C mode
+ *
+ * @param element The element to retrieve the location from.
+ * @return A point representing the location
+ */
+ public static Point getLocation(WebDriver driver, WebElement element) {
+ return getElementRect(driver, element).getPoint();
+ }
+
+ /**
+ * Gets element rect. TODO: remove this when getLocation & getDimension work again in W3C mode.
+ *
+ * @param element the element
+ * @return the element rect
+ */
+ public static Rectangle getElementRect(WebDriver driver, WebElement element) {
+ Map, ?> result =
+ (Map, ?>)
+ ((JavascriptExecutor) driver)
+ .executeScript("return arguments[0].getBoundingClientRect()", element);
+ logger.info(result.toString());
+ return new Rectangle(
+ (int) Double.parseDouble(result.get("x").toString()),
+ (int) Double.parseDouble(result.get("y").toString()),
+ (int) Double.parseDouble(result.get("height").toString()),
+ (int) Double.parseDouble(result.get("width").toString()));
+ }
+
+ /**
+ * Gets accurate Y point for element
+ *
+ * @param element
+ * @param isTablet -
+ * @return Accurate Y point for element
+ */
+ public static int getAccuratePointY(WebDriver driver, WebElement element, boolean isTablet) {
+ int windowDiff =
+ isTablet
+ ? getWindowHeightDiffBetweenAppiumAndSelenium(driver)
+ : (int) (getWindowHeightDiffBetweenAppiumAndSelenium(driver) / 1.5);
+ int seleniumWindowHeight = driver.manage().window().getSize().getHeight();
+ double heightRatio = ((double) seleniumWindowHeight / getJavascriptWindowHeight(driver));
+ return (int) ((heightRatio * getLocation(driver, element).getY()) + windowDiff)
+ + element.getSize().getHeight() / 2;
+ }
+
+ /**
+ * @return the window height difference between Appium and Selenium
+ */
+ public static int getWindowHeightDiffBetweenAppiumAndSelenium(WebDriver driver) {
+ int seleniumWindowHeight = driver.manage().window().getSize().getHeight();
+ int appiumHeight = getAppiumWindowHeight(driver);
+ return appiumHeight - seleniumWindowHeight;
+ }
+
+ /**
+ * @return JavaScript window height
+ */
+ public static int getJavascriptWindowHeight(WebDriver driver) {
+ return ((Long)
+ ((JavascriptExecutor) driver)
+ .executeScript("return window.innerHeight || document.body.clientHeight"))
+ .intValue();
+ }
+
+ public static int getAppiumWindowHeight(WebDriver driver) {
+ String currentContext = getContext(driver);
+ changeContext(driver, "NATIVE_APP");
+ int appiumHeight =
+ isAndroid(driver)
+ ? getAndroidDriver(driver).manage().window().getSize().getHeight()
+ : getIOSDriver(driver).manage().window().getSize().getHeight();
+ changeContext(driver, currentContext);
+ return appiumHeight;
+ }
+
+ public static boolean changeContext(WebDriver driver, String desiredContext) {
+ return isAndroid(driver)
+ ? changeContextAndroid(driver, desiredContext)
+ : changeContextIos(driver, desiredContext);
+ }
+
+ private static boolean changeContextAndroid(WebDriver driver, String desiredContext) {
+ try {
+ Set contextNames = getAndroidDriver(driver).getContextHandles();
+ Iterator contextNameIterator = contextNames.iterator();
+
+ String contextName;
+ do {
+ if (!contextNameIterator.hasNext()) {
+ return false;
+ }
+
+ contextName = (String) contextNameIterator.next();
+ } while (!contextName.contains(desiredContext));
+
+ logger.debug(String.format("Switching to context [%s].", contextName));
+ getAndroidDriver(driver).context(contextName);
+ return true;
+ } catch (Exception var6) {
+ logger.error(String.format("Unable to switch to context [%s].", desiredContext), var6);
+ return false;
+ }
+ }
+
+ private static boolean changeContextIos(WebDriver driver, String desiredContext) {
+ try {
+ Set contextNames = getIOSDriver(driver).getContextHandles();
+ Iterator contextNameIterator = contextNames.iterator();
+
+ String contextName;
+ do {
+ if (!contextNameIterator.hasNext()) {
+ return false;
+ }
+
+ contextName = (String) contextNameIterator.next();
+ } while (!contextName.contains(desiredContext));
+
+ logger.debug(String.format("Switching to context [%s].", contextName));
+ getIOSDriver(driver).context(contextName);
+ return true;
+ } catch (Exception var6) {
+ logger.error(String.format("Unable to switch to context [%s].", desiredContext), var6);
+ return false;
+ }
+ }
+
+ public static String getContext(WebDriver driver) {
+ return isAndroid(driver)
+ ? getAndroidDriver(driver).getContext()
+ : getIOSDriver(driver).getContext();
+ }
+
+ private static boolean isAndroid(WebDriver driver) {
+ return driver instanceof AndroidDriver;
+ }
+
+ private static AndroidDriver getAndroidDriver(WebDriver driver) {
+ return (AndroidDriver) driver;
+ }
+
+ private static IOSDriver getIOSDriver(WebDriver driver) {
+ return (IOSDriver) driver;
+ }
+}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/WebUtils.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/WebUtils.java
new file mode 100644
index 0000000..176c723
--- /dev/null
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/web/WebUtils.java
@@ -0,0 +1,48 @@
+/*
+ *
+ * Copyright © 2025 Applause App Quality, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.applause.auto.helpers.web;
+
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebDriver;
+
+/** Web common utils */
+public class WebUtils {
+
+ /**
+ * JS scroll down
+ *
+ * @param driver - automation driver
+ * @param yValue - y value scroll to
+ */
+ public static void jsScrollDown(WebDriver driver, final int yValue) {
+ ((JavascriptExecutor) driver).executeScript("window.scrollBy(0, " + yValue + ");");
+ }
+
+ /**
+ * Get page Y position
+ *
+ * @param driver - automation driver
+ * @return Y page position value
+ */
+ public static int getPagePositionY(WebDriver driver) {
+ String javascript = "return window.scrollY;";
+ return (int)
+ Float.parseFloat(
+ String.valueOf(((JavascriptExecutor) driver).executeScript("return window.scrollY;")));
+ }
+}
diff --git a/pom.xml b/pom.xml
index 3b39690..7a515f9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,18 @@
6.0.0
4.4
+ 5.5.0
+ 4.2.2
+ 1.18.3
+ 0.3.7
+ 1.0.2
+ 2.29.1
+ 20250107
+ 0.0.12
+ 2.7.2
+ v4-rev612-1.25.0
+ 2.1.3
+
5.13.0
5.2.0
@@ -248,6 +260,61 @@
freemarker
${freemarker.version}
+
+ io.rest-assured
+ rest-assured
+ ${rest-assured.version}
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+
+
+ org.jsoup
+ jsoup
+ ${jsoup.version}
+
+
+ us.codecraft
+ xsoup
+ ${xsoup.version}
+
+
+ com.github.javafaker
+ javafaker
+ ${faker.version}
+
+
+ io.qameta.allure
+ allure-testng
+ ${allure.version}
+
+
+ org.json
+ json
+ ${json.version}
+
+
+ io.github.yaml-path
+ yaml-path
+ ${yaml-path.version}
+
+
+ com.google.api-client
+ google-api-client
+ ${google-api-client.version}
+
+
+ com.google.apis
+ google-api-services-sheets
+ ${google-api-services-sheets.version}
+
+
+ jakarta.mail
+ jakarta.mail-api
+ ${jakarta.mail-api.version}
+
From c0846eec08a122f0c8ebe8b7979ff89de8ea72cb Mon Sep 17 00:00:00 2001
From: Mark Gunlogson <31893232+noobgramming@users.noreply.github.com>
Date: Tue, 4 Feb 2025 16:44:56 -0600
Subject: [PATCH 2/2] AUT-6940 refactors for docs, java 21, deprecated calls,
fixed 1000+ linter warnings :-|
---
.gitignore | 4 +
.../auto/helpers/AnalyticsHelper.java | 5 +
.../auto/helpers/EnvironmentHelper.java | 13 +-
.../helpers/allure/AllureDriverUtils.java | 78 +++----
.../auto/helpers/allure/AllureUtils.java | 44 ++--
.../appenders/AllureLogsToStepAppender.java | 75 ++++---
.../helpers/analytics/AnalyticsEntry.java | 22 ++
.../analytics/AnalyticsInterceptor.java | 13 +-
.../auto/helpers/control/BrowserControl.java | 11 +-
.../auto/helpers/control/DeviceControl.java | 11 +-
.../auto/helpers/email/CommonMailClient.java | 146 +++++++-----
.../auto/helpers/email/GmailHelper.java | 96 ++++----
.../auto/helpers/email/SearchCriteria.java | 20 +-
.../helpers/google/GoogleSheetParser.java | 210 ++++++++----------
.../google/GoogleSheetParserException.java | 4 +-
.../mapping/JacksonJSONRestObjectMapping.java | 12 +-
.../RestApiDefaultRestAssuredApiHelper.java | 4 +-
.../RestApiDefaultRestAssuredApiClient.java | 14 +-
.../client/RestAssuredApiClient.java | 23 +-
.../scanner/JiraAnnotationsScanner.java | 44 ++--
.../helpers/jira/clients/JiraXrayClient.java | 9 +-
.../clients/modules/jira/JiraProjectAPI.java | 198 ++++++++---------
.../jira/clients/modules/jira/SearchAPI.java | 39 ++--
.../clients/modules/xray/ExecutionsAPI.java | 76 +++----
.../clients/modules/xray/IterationsAPI.java | 39 ++--
.../jira/clients/modules/xray/StepsAPI.java | 174 +++++++--------
.../jira/clients/modules/xray/TestrunAPI.java | 172 +++++++-------
.../auto/helpers/jira/constants/Statuses.java | 2 +-
.../helpers/jira/constants/XrayEndpoints.java | 8 +-
.../auto/helpers/jira/dto/jql/Fields.java | 11 +-
.../auto/helpers/jira/dto/jql/Issues.java | 10 +-
.../jira/dto/jql/JqlFilteredResults.java | 10 +-
.../jira/dto/requestmappers/Fields.java | 12 +-
.../JiraCreateTicketRequest.java | 7 +-
.../jira/dto/requestmappers/JiraFields.java | 18 +-
.../dto/requestmappers/StepFieldsUpdate.java | 9 +-
.../StepIterationAttachment.java | 9 +-
.../jira/dto/requestmappers/XrayAddTo.java | 6 +-
.../responsemappers/AvailableIssueTypes.java | 11 +-
.../responsemappers/AvailableProjects.java | 17 +-
.../JiraCreateTicketResponse.java | 9 +-
.../responsemappers/XrayTestRunDetails.java | 40 ++--
.../responsemappers/iteration/Iteration.java | 8 +-
.../iteration/IterationParameters.java | 7 +-
.../iteration/TestRunIteration.java | 16 +-
.../dto/responsemappers/steps/Action.java | 11 +-
.../responsemappers/steps/Attachments.java | 17 +-
.../dto/responsemappers/steps/Comment.java | 11 +-
.../jira/dto/responsemappers/steps/Data.java | 12 +-
.../dto/responsemappers/steps/Fields.java | 11 +-
.../jira/dto/responsemappers/steps/Step.java | 21 +-
.../jira/dto/responsemappers/steps/Steps.java | 8 +-
.../jira/dto/responsemappers/steps/Value.java | 6 +-
.../helpers/jira/dto/shared/Issuetype.java | 7 +-
.../auto/helpers/jira/dto/shared/Project.java | 7 +-
.../exceptions/JiraAnnotationException.java | 5 +-
.../JiraPropertiesFileException.java | 2 +-
.../UnidentifiedExecutionStatusException.java | 2 +-
.../auto/helpers/jira/helper/FilesHelper.java | 39 +++-
.../jira/helper/ResponseValidator.java | 11 +-
.../restclient/XrayRestAssuredClient.java | 22 +-
.../helpers/mobile/MobileContextsUtils.java | 31 ++-
.../helpers/mobile/MobileElementUtils.java | 21 +-
.../auto/helpers/mobile/MobileUtils.java | 75 ++++---
.../deeplinks/MobileDeepLinksUtils.java | 32 +--
.../NativeMobileAppCommonDeeplink.java | 46 ++--
.../saucelabs}/FileUploadingHelper.java | 84 ++++---
.../helpers/sync/all/AllMatchCondition.java | 16 +-
.../sync/all/AllMatchConditionBuilder.java | 11 +-
.../helpers/testdata/TestDataProvider.java | 12 +-
.../testdata/yaml/YamlTestDataProvider.java | 21 +-
.../helpers/util/AwaitilityWaitUtils.java | 22 +-
.../auto/helpers/util/RandomUtils.java | 34 ++-
.../auto/helpers/util/ThreadHelper.java | 8 +-
.../XrayRequestHeaders.java | 9 +-
.../applause/auto/helpers/web/HtmlUtils.java | 16 +-
.../auto/helpers/web/WebElementUtils.java | 195 +++++++++++-----
.../applause/auto/helpers/web/WebUtils.java | 12 +-
auto-sdk-java-integrations/pom.xml | 8 +-
.../auto/testng/TestNgContextUtils.java | 2 +-
.../auto/testng}/listeners/XrayListener.java | 68 +++---
build-tools/checkstyle.xml | 6 +-
pom.xml | 21 +-
83 files changed, 1457 insertions(+), 1251 deletions(-)
rename auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/mobile/{file_uploading/SauceLabs => fileuploading/saucelabs}/FileUploadingHelper.java (61%)
rename auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/{jira/requestData => util}/XrayRequestHeaders.java (85%)
rename {auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira => auto-sdk-java-testng/src/main/java/com/applause/auto/testng}/listeners/XrayListener.java (68%)
diff --git a/.gitignore b/.gitignore
index 24a4cb4..fa71811 100644
--- a/.gitignore
+++ b/.gitignore
@@ -163,3 +163,7 @@ Temporary Items
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
+
+
+# =============================== Allure reporting ===============================
+allure-results/
\ No newline at end of file
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/AnalyticsHelper.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/AnalyticsHelper.java
index 00b6282..a60ca7f 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/AnalyticsHelper.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/AnalyticsHelper.java
@@ -781,6 +781,11 @@ public List getRequestsWithMultipleFilt
return filtered;
}
+ /**
+ * Returns a new instance of {@link AnalyticsInterceptor} associated with this object.
+ *
+ * @return A new {@link AnalyticsInterceptor} instance.
+ */
public AnalyticsInterceptor getInterceptor() {
return new AnalyticsInterceptor(this);
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/EnvironmentHelper.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/EnvironmentHelper.java
index d5e3f19..1a5e8f8 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/EnvironmentHelper.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/EnvironmentHelper.java
@@ -21,7 +21,6 @@
import com.applause.auto.context.IPageObjectExtension;
import com.applause.auto.data.enums.DriverType;
import java.util.Locale;
-import lombok.AllArgsConstructor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.remote.RemoteWebDriver;
@@ -31,10 +30,18 @@
* driver type, which browser, which version.
*/
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
-@AllArgsConstructor
public class EnvironmentHelper implements IPageObjectExtension {
private static final Logger logger = LogManager.getLogger(EnvironmentHelper.class);
- private IPageObjectContext pageObjectContext;
+ private final IPageObjectContext pageObjectContext;
+
+ /**
+ * Constructor for EnvironmentHelper.
+ *
+ * @param pageObjectContext The {@link IPageObjectContext} to use.
+ */
+ public EnvironmentHelper(final IPageObjectContext pageObjectContext) {
+ this.pageObjectContext = pageObjectContext;
+ }
/**
* determine the cast class type of the created driver object and set the DriverType into the
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/AllureDriverUtils.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/AllureDriverUtils.java
index 87e5465..388eb63 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/AllureDriverUtils.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/AllureDriverUtils.java
@@ -19,67 +19,69 @@
import io.qameta.allure.Allure;
import java.io.ByteArrayInputStream;
-import java.util.Objects;
+import lombok.NonNull;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
-/** Some common allure utils (with attachments) */
-public class AllureDriverUtils {
+/** Provides utility methods for attaching information to Allure reports. */
+public final class AllureDriverUtils {
- private static final Logger logger = LogManager.getLogger(AllureDriverUtils.class);
+ private static final Logger LOGGER = LogManager.getLogger(AllureDriverUtils.class);
+ private static final String SCREENSHOT_ATTACHMENT = "Screenshot attachment";
+ private static final String IMAGE_PNG = "image/png";
+ private static final String CURRENT_URL = "Current URL";
+ private static final String TEXT_PLAIN = "text/plain";
+ private static final String CURRENT_PAGE_SOURCE = "Current page source";
+ private static final String LOG_EXTENSION = ".log";
+
+ private AllureDriverUtils() {
+ // Utility class - no public constructor
+ }
/**
- * Attach driver screenshot
+ * Attaches a screenshot to the Allure report.
*
- * @param driver - automation driver
+ * @param driver The WebDriver instance to capture the screenshot from.
*/
- public static void attachScreenshot(WebDriver driver) {
- if (Objects.nonNull(driver)) {
- logger.info("Taking screenshot on test failure");
- try {
- Allure.addAttachment(
- "Screenshot attachment",
- "image/png",
- new ByteArrayInputStream(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES)),
- "png");
- } catch (Exception e) {
- logger.error("Error taking screenshot: " + e.getMessage());
- }
+ public static void attachScreenshot(@NonNull final WebDriver driver) {
+ LOGGER.info("Taking screenshot on test failure");
+ try {
+ var screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
+ Allure.addAttachment(
+ SCREENSHOT_ATTACHMENT, IMAGE_PNG, new ByteArrayInputStream(screenshot), "png");
+ } catch (Exception e) {
+ LOGGER.error("Error taking screenshot: {}", e.getMessage());
}
}
/**
- * Attach driver url
+ * Attaches the current URL to the Allure report.
*
- * @param driver - automation driver
+ * @param driver The WebDriver instance to get the current URL from.
*/
- public static void attachCurrentURL(WebDriver driver) {
- if (Objects.nonNull(driver)) {
- logger.info("Taking current URL");
- try {
- Allure.addAttachment("Current URL", "text/plain", driver.getCurrentUrl(), ".log");
- } catch (Exception e) {
- logger.error("Error taking current URL: " + e.getMessage());
- }
+ public static void attachCurrentURL(@NonNull final WebDriver driver) {
+ LOGGER.info("Attaching current URL");
+ try {
+ Allure.addAttachment(CURRENT_URL, TEXT_PLAIN, driver.getCurrentUrl(), LOG_EXTENSION);
+ } catch (Exception e) {
+ LOGGER.error("Error taking current URL: {}", e.getMessage());
}
}
/**
- * Attach driver page source
+ * Attaches the current page source to the Allure report.
*
- * @param driver - automation driver
+ * @param driver The WebDriver instance to get the page source from.
*/
- public static void attachCurrentPageSourceOnFailure(WebDriver driver) {
- if (Objects.nonNull(driver)) {
- logger.info("Taking page source");
- try {
- Allure.addAttachment("Current page source", "text/plain", driver.getPageSource(), ".log");
- } catch (Exception e) {
- logger.error("Error taking current page source: " + e.getMessage());
- }
+ public static void attachCurrentPageSourceOnFailure(@NonNull final WebDriver driver) {
+ LOGGER.info("Attaching page source");
+ try {
+ Allure.addAttachment(CURRENT_PAGE_SOURCE, TEXT_PLAIN, driver.getPageSource(), LOG_EXTENSION);
+ } catch (Exception e) {
+ LOGGER.error("Error taking current page source: {}", e.getMessage());
}
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/AllureUtils.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/AllureUtils.java
index 3aff49d..0b9bf50 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/AllureUtils.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/AllureUtils.java
@@ -17,36 +17,42 @@
*/
package com.applause.auto.helpers.allure;
-import java.io.File;
import java.io.IOException;
-import org.apache.commons.io.FileUtils;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import lombok.NonNull;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-public class AllureUtils {
+/** Utility class for Allure reporting. */
+public final class AllureUtils {
private static final Logger logger = LogManager.getLogger(AllureUtils.class);
+ private static final String CATEGORIES_JSON = "categories.json";
+
+ private AllureUtils() {}
/**
- * Copy Allure categorisation .json file to report directory
- * https://docs.qameta.io/allure/#_categories_2
+ * Copies the Allure defects categorization JSON file to the Allure report directory.
*
- * @throws IOException
+ * @param allureReportPath The path to the Allure report directory.
+ * @param allureDefectsCategorisationFilePath The path to the Allure defects categorization JSON
+ * file.
+ * @throws IOException If an I/O error occurs.
*/
public static void addAllureDefectsCategoriesConfiguration(
- String allureReportPath, String allureDefectsCategorisationFilePath) {
- try {
- logger.info("Copy defects configs to categories.json file for Allure");
- File categoriesAllureFile = new File(allureReportPath + "/categories.json");
- if (!categoriesAllureFile.exists()) {
- categoriesAllureFile.createNewFile();
- }
- categoriesAllureFile.setReadable(true);
- categoriesAllureFile.setWritable(true);
- FileUtils.copyFile(new File(allureDefectsCategorisationFilePath), categoriesAllureFile);
-
- } catch (Exception e) {
- logger.error("Error creating allure categories.json file " + e.getMessage());
+ @NonNull final String allureReportPath,
+ @NonNull final String allureDefectsCategorisationFilePath)
+ throws IOException {
+
+ logger.info("Copying defects configs to {} file for Allure", CATEGORIES_JSON);
+
+ final Path categoriesAllureFile = Path.of(allureReportPath, CATEGORIES_JSON);
+
+ if (!Files.exists(categoriesAllureFile)) {
+ Files.createFile(categoriesAllureFile);
}
+
+ Files.copy(Path.of(allureDefectsCategorisationFilePath), categoriesAllureFile);
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/appenders/AllureLogsToStepAppender.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/appenders/AllureLogsToStepAppender.java
index 518c1c5..57cec38 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/appenders/AllureLogsToStepAppender.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/allure/appenders/AllureLogsToStepAppender.java
@@ -25,78 +25,79 @@
import java.util.concurrent.ConcurrentSkipListSet;
import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
-/** Log4j2 logs to Allure step definition appender */
+/** Appender for logging to Allure steps. */
@Plugin(
name = "AllureLogsToStepAppender",
- category = Core.CATEGORY_NAME,
+ category = Node.CATEGORY,
elementType = Appender.ELEMENT_TYPE)
-public class AllureLogsToStepAppender extends AbstractAppender {
+public final class AllureLogsToStepAppender extends AbstractAppender {
- /** storage for filtered packages */
- private static Set filteredPackagesToAppendSet;
+ private static final String COMMA = ",";
+ private static final Set FILTERED_PACKAGES_TO_APPEND_SET = new ConcurrentSkipListSet<>();
- protected AllureLogsToStepAppender(
- String name, Filter filter, Layout extends Serializable> layout, boolean ignoreExceptions) {
+ private AllureLogsToStepAppender(
+ final String name,
+ final Filter filter,
+ final Layout extends Serializable> layout,
+ final boolean ignoreExceptions) {
super(name, filter, layout, ignoreExceptions, null);
}
/**
- * Create log4j2 AllureLogsToStepAppender appender method
+ * Creates an AllureLogsToStepAppender.
*
- * @param name appender name
- * @param layout appender layout
- * @param filter appender filter
- * @param filteredPackagesToAppend filter packages to append appender, should be provided as comma
- * separated list
- * @return
+ * @param name The name of the appender.
+ * @param layout The layout to use for the appender.
+ * @param filter The filter to use for the appender.
+ * @param filteredPackagesToAppend A comma-separated list of packages to filter.
+ * @return A new AllureLogsToStepAppender instance, or null if the name is null.
*/
@PluginFactory
public static AllureLogsToStepAppender createAppender(
- @PluginAttribute("name") String name,
- @PluginElement("Layout") Layout extends Serializable> layout,
+ @PluginAttribute("name") final String name,
+ @PluginElement("Layout") final Layout extends Serializable> layout,
@PluginElement("Filter") final Filter filter,
- @PluginAttribute("filteredPackagesToAppend") String filteredPackagesToAppend) {
- if (Objects.isNull(name)) {
+ @PluginAttribute("filteredPackagesToAppend") final String filteredPackagesToAppend) {
+
+ if (name == null) {
return null;
}
- if (Objects.isNull(layout)) {
- layout = PatternLayout.createDefaultLayout();
- }
- if (Objects.nonNull(filteredPackagesToAppend)) {
- filteredPackagesToAppendSet =
- new ConcurrentSkipListSet<>(Arrays.asList(filteredPackagesToAppend.split(",")));
+
+ final var usedLayout = Objects.requireNonNullElse(layout, PatternLayout.createDefaultLayout());
+
+ if (filteredPackagesToAppend != null) {
+ FILTERED_PACKAGES_TO_APPEND_SET.addAll(Arrays.asList(filteredPackagesToAppend.split(COMMA)));
}
- return new AllureLogsToStepAppender(name, filter, layout, true);
+
+ return new AllureLogsToStepAppender(name, filter, usedLayout, true);
}
/**
- * log4j2 append method for Allure step appender
+ * Appends a log event to Allure step.
*
- * @param event logging log4j2 intercepted event
+ * @param event The log event to append.
*/
@Override
- public void append(LogEvent event) {
+ public void append(final LogEvent event) {
if (isSourcePackageValidForAppender(event)) {
Allure.step(event.getMessage().getFormattedMessage());
}
}
- private boolean isSourcePackageValidForAppender(LogEvent event) {
- if (filteredPackagesToAppendSet.isEmpty()) {
+ private boolean isSourcePackageValidForAppender(final LogEvent event) {
+ if (FILTERED_PACKAGES_TO_APPEND_SET.isEmpty()) {
return true;
}
- String sourceClassName = event.getSource().getClassName();
- return filteredPackagesToAppendSet.stream()
- .filter(
- filteredPackagesToAppendSetItem ->
- sourceClassName.contains(filteredPackagesToAppendSetItem))
- .findAny()
- .isPresent();
+
+ final var sourceClassName = event.getSource().getClassName();
+
+ return FILTERED_PACKAGES_TO_APPEND_SET.stream().anyMatch(sourceClassName::contains);
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/analytics/AnalyticsEntry.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/analytics/AnalyticsEntry.java
index 6b7e86e..b161753 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/analytics/AnalyticsEntry.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/analytics/AnalyticsEntry.java
@@ -36,11 +36,23 @@
public class AnalyticsEntry extends LogEntry {
private final JsonObject parsedMessage;
+ /**
+ * Constructor for AnalyticsEntry.
+ *
+ * @param level The log level.
+ * @param timestamp The timestamp of the log entry.
+ * @param message The log message.
+ */
public AnalyticsEntry(final Level level, final long timestamp, final String message) {
super(level, timestamp, message);
this.parsedMessage = new Gson().fromJson(message, JsonObject.class);
}
+ /**
+ * Gets the webview GUID.
+ *
+ * @return The webview GUID, or null if not found.
+ */
public String getWebView() {
return Optional.ofNullable(parsedMessage)
.map(body -> body.get("webview"))
@@ -48,6 +60,11 @@ public String getWebView() {
.orElse(null);
}
+ /**
+ * Gets the method of the analytics call.
+ *
+ * @return The method, or null if not found.
+ */
public String getMethod() {
return Optional.ofNullable(parsedMessage)
.map(body -> body.getAsJsonObject("message"))
@@ -56,6 +73,11 @@ public String getMethod() {
.orElse(null);
}
+ /**
+ * Gets the parameters of the analytics call.
+ *
+ * @return The parameters as a JsonObject, or null if not found.
+ */
public JsonObject getParams() {
return Optional.ofNullable(parsedMessage)
.map(body -> body.getAsJsonObject("message"))
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/analytics/AnalyticsInterceptor.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/analytics/AnalyticsInterceptor.java
index 2faf3b2..6ed2b50 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/analytics/AnalyticsInterceptor.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/analytics/AnalyticsInterceptor.java
@@ -21,7 +21,6 @@
import com.applause.auto.pageobjectmodel.base.ComponentInterceptor;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
-import lombok.AllArgsConstructor;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
@@ -34,10 +33,18 @@
* This interceptor is added to classes in the PageObjectFactory to facilitate running code before
* and after methods. Currently, the only use case is for the @AnalyticsCall annotation.
*/
-@AllArgsConstructor
@SuppressWarnings("PMD.SignatureDeclareThrowsException") // since we're intercepting this is okay
public class AnalyticsInterceptor extends ComponentInterceptor {
- private AnalyticsHelper analyticsHelper;
+ private final AnalyticsHelper analyticsHelper;
+
+ /**
+ * Constructs a new AnalyticsInterceptor.
+ *
+ * @param analyticsHelper The AnalyticsHelper instance to use for analytics reporting.
+ */
+ public AnalyticsInterceptor(final AnalyticsHelper analyticsHelper) {
+ this.analyticsHelper = analyticsHelper;
+ }
/**
* Methods in a page object class that meet the criteria in match() are subject to the extra logic
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/control/BrowserControl.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/control/BrowserControl.java
index 611745d..7552af4 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/control/BrowserControl.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/control/BrowserControl.java
@@ -24,7 +24,6 @@
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import lombok.AllArgsConstructor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.Dimension;
@@ -35,11 +34,19 @@
* mouse-downs.
*/
@SuppressWarnings({"checkstyle:ParameterName", "checkstyle:AbbreviationAsWordInName"})
-@AllArgsConstructor
public class BrowserControl implements IPageObjectExtension {
private static final Logger logger = LogManager.getLogger();
private final IPageObjectContext context;
+ /**
+ * Constructor for BrowserControl.
+ *
+ * @param context The {@link IPageObjectContext} to use.
+ */
+ public BrowserControl(final IPageObjectContext context) {
+ this.context = context;
+ }
+
/**
* Gets the current driver as a JavascriptExecutor.
*
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/control/DeviceControl.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/control/DeviceControl.java
index 06891e4..2866139 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/control/DeviceControl.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/control/DeviceControl.java
@@ -32,7 +32,6 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
-import lombok.AllArgsConstructor;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -53,11 +52,19 @@
"checkstyle:MultipleStringLiterals",
"checkstyle:LocalVariableName"
})
-@AllArgsConstructor
public class DeviceControl implements IPageObjectExtension {
private static final Logger logger = LogManager.getLogger();
private final IPageObjectContext context;
+ /**
+ * Constructor for DeviceControl.
+ *
+ * @param context The {@link IPageObjectContext} to use.
+ */
+ public DeviceControl(final IPageObjectContext context) {
+ this.context = context;
+ }
+
/**
* Checks if the current driver is an Android driver.
*
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/CommonMailClient.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/CommonMailClient.java
index d373a9f..33e27c7 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/CommonMailClient.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/CommonMailClient.java
@@ -24,27 +24,37 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
+import java.util.Locale;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import lombok.NonNull;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/** Provides some common methods between most email clients. */
-public abstract class CommonMailClient {
+public class CommonMailClient {
private String host;
- private Properties props = new Properties();
- private Store store;
+ private final Properties props = new Properties();
+ private final Store store;
private String protocol;
private String userName;
private String password;
private static final Logger logger = LogManager.getLogger(CommonMailClient.class);
/**
- * Default constructor with params Example: username = some@email.com password = xxxx protocol =
- * imaps host = imap.gmail.com
+ * Constructs a new CommonMailClient with the specified username, password, protocol, and host.
+ * Example: username = some@email.com, password = xxxx, protocol = imaps, host = imap.gmail.com
+ *
+ * @param userName The username for the mail account.
+ * @param password The password for the mail account.
+ * @param protocol The protocol to use for connecting to the mail server.
+ * @param host The hostname of the mail server.
+ * @throws MessagingException If an error occurs during the setup of mail credentials.
*/
- public CommonMailClient(String userName, String password, Protocol protocol, String host) {
+ public CommonMailClient(
+ final String userName, final String password, final Protocol protocol, final String host)
+ throws MessagingException {
this.userName = userName.trim();
this.password = password;
this.protocol = protocol.getValue();
@@ -59,17 +69,17 @@ public CommonMailClient(String userName, String password, Protocol protocol, Str
* @param regex The regular expression to use
* @return The extracted text after applying the regex
*/
- public String extractWithRegexFromString(String text, String regex) {
+ public String extractWithRegexFromString(final String text, @NonNull final String regex) {
if (text.isEmpty()) {
logger.info("Text is empty");
return null;
}
- logger.info("Extracting with regex = [" + regex + "...");
+ logger.info("Extracting with regex = [{}...", regex);
Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
- logger.info("Extracted text is:: " + matcher.group(1).trim());
+ logger.info("Extracted text is:: {}", matcher.group(1).trim());
return matcher.group(1).trim();
}
throw new RuntimeException("No matches were found in the text.");
@@ -82,33 +92,18 @@ public String extractWithRegexFromString(String text, String regex) {
*
* @param resourceFile an InputStream that represents a .properties files that includes all the
* above-mentioned properties.
+ * @throws MessagingException If an error occurs during mail session setup.
*/
- public CommonMailClient(InputStream resourceFile) {
+ public CommonMailClient(@NonNull final InputStream resourceFile) throws MessagingException {
store = setMailCredentials(resourceFile);
}
- /**
- * Initialize properties for current mailbox example setMailCredentials(new
- * InputStream("/xxx/xxx/propertyFile"))
- *
- * @param resourceStream an InputStream that represents a .properties files that includes all the
- * above-mentioned properties.
- * @return
- */
- private Store setMailCredentials(InputStream resourceStream) {
- if (props.isEmpty()) {
- setProperties(resourceStream);
- }
- Session session = Session.getDefaultInstance(props, null);
- return getStore(session);
- }
-
/**
* Deletes all the read emails from the mentioned folder of the email account.
*
* @param emailFolder The email folder to use.
*/
- public void emptyAllReadEmailsFromInbox(Folder emailFolder) {
+ public void emptyAllReadEmailsFromInbox(@NonNull final Folder emailFolder) {
deleteReadEmails(emailFolder);
}
@@ -141,35 +136,38 @@ public Folder markAllEmailsAsRead() {
* @throws MessagingException Thrown in case an error happens when getting any details from the
* email.
*/
- protected boolean doesEmailMatchCriteria(Message email, SearchCriteria criteria)
+ protected boolean doesEmailMatchCriteria(
+ @NonNull final Message email, @NonNull final SearchCriteria criteria)
throws MessagingException {
- if (criteria.getEmailSubject() != null && !criteria.getEmailSubject().isEmpty()) {
+ if (criteria.emailSubject() != null && !criteria.emailSubject().isEmpty()) {
// check email subject
- boolean subjectMatch = email.getSubject().matches(criteria.getEmailSubject());
+ boolean subjectMatch = email.getSubject().matches(criteria.emailSubject());
// return if false, otherwise continue
if (!subjectMatch) {
return false;
}
}
- if (criteria.getSentFrom() != null && !criteria.getSentFrom().isEmpty()) {
+ if (criteria.sentFrom() != null && !criteria.sentFrom().isEmpty()) {
// check sentFrom
boolean sentFromMatch =
Arrays.stream(email.getFrom())
.sequential()
- .anyMatch(from -> from.toString().contains(criteria.getSentFrom().toLowerCase()));
+ .anyMatch(
+ from ->
+ from.toString().contains(criteria.sentFrom().toLowerCase(Locale.ENGLISH)));
// return if false, otherwise continue
if (!sentFromMatch) {
return false;
}
}
- if (criteria.getSentTo() != null && !criteria.getSentTo().isEmpty()) {
+ if (criteria.sentTo() != null && !criteria.sentTo().isEmpty()) {
// check sentTo
// return if false, otherwise continue
return Arrays.stream(email.getAllRecipients())
.sequential()
- .anyMatch(to -> to.toString().contains(criteria.getSentTo().toLowerCase()));
+ .anyMatch(to -> to.toString().contains(criteria.sentTo().toLowerCase(Locale.ENGLISH)));
}
// email matches the whole criteria
@@ -185,7 +183,7 @@ protected boolean doesEmailMatchCriteria(Message email, SearchCriteria criteria)
* above-mentioned properties.
* @return mailProperties
*/
- private Properties setProperties(InputStream resourceStream) {
+ private Properties setProperties(@NonNull final InputStream resourceStream) {
try {
props.load(resourceStream);
this.userName = props.getProperty("username");
@@ -201,51 +199,79 @@ private Properties setProperties(InputStream resourceStream) {
}
/**
- * @param folderName mail folder name example INBOX
- * @param accessMode check Folder.to get which mode exists
- * @return required Folder
+ * Opens a specified mail folder with the given access rights.
+ *
+ * @param folderName The name of the mail folder to open (e.g., "INBOX").
+ * @param accessMode The access mode to use when opening the folder. See {@link
+ * jakarta.mail.Folder} for available modes.
+ * @return The opened {@link jakarta.mail.Folder} object, or null if an error occurred.
+ * @throws MessagingException If an error occurs while opening the folder.
*/
- public Folder openSelectedFolderWithRights(String folderName, int accessMode) {
+ public Folder openSelectedFolderWithRights(@NonNull final String folderName, final int accessMode)
+ throws MessagingException {
Folder inbox = null;
try {
inbox = store.getFolder(folderName);
+ inbox.open(accessMode); // Open the folder immediately after retrieving it
+
} catch (MessagingException e1) {
- e1.printStackTrace();
- }
- try {
- inbox.open(accessMode);
- } catch (MessagingException e1) {
- e1.printStackTrace();
+ logger.error(e1);
+ throw e1; // Re-throw the exception after logging it. This is crucial for proper error
+ // handling.
}
return inbox;
}
/**
* Initialize properties for current mailbox. Username, password, protocol, and host should be set
- * in advance
+ * in advance.
+ *
+ * @return The initialized Store object.
*/
- private Store setMailCredentials() {
+ private Store setMailCredentials() throws MessagingException {
Session session = Session.getDefaultInstance(getProperties(), null);
return getStore(session);
}
- private Store getStore(Session session) {
- Store store = null;
+ /**
+ * Initialize properties for current mailbox example setMailCredentials(new
+ * InputStream("/xxx/xxx/propertyFile"))
+ *
+ * @param resourceStream an InputStream that represents a .properties files that includes all the
+ * above-mentioned properties.
+ * @return mail credential store
+ */
+ private Store setMailCredentials(@NonNull final InputStream resourceStream)
+ throws MessagingException {
+ if (props.isEmpty()) {
+ setProperties(resourceStream);
+ }
+ Session session = Session.getDefaultInstance(props, null);
+ return getStore(session);
+ }
+
+ private Store getStore(@NonNull final Session session) throws MessagingException {
+ Store storeLocal = null;
try {
- store = session.getStore(protocol);
+ storeLocal = session.getStore(protocol);
} catch (NoSuchProviderException e1) {
- e1.printStackTrace();
+ logger.error(e1);
+ throw e1;
}
try {
- store.connect(host, userName, password);
+ storeLocal.connect(host, userName, password);
} catch (MessagingException e1) {
- e1.printStackTrace();
+ logger.error(e1);
+ throw e1;
}
- return store;
+ return storeLocal;
}
/**
- * Creating properties instance Username, password, protocol, and host should be set in advance
+ * Creates a Properties instance with pre-set username, password, protocol, and host. Username,
+ * password, protocol, and host should be set in advance.
+ *
+ * @return A Properties instance containing the username, password, protocol, and host.
*/
private Properties getProperties() {
Properties properties = new Properties();
@@ -264,14 +290,14 @@ private Properties getProperties() {
* @param folder The email folder to check.
* @return unread emails for selected folder
*/
- public Message[] getUnreadEmails(Folder folder) {
+ public Message[] getUnreadEmails(@NonNull final Folder folder) {
Message[] emails = new Message[0];
try {
Flags seen = new Flags(Flags.Flag.SEEN);
FlagTerm unseenFlagTerm = new FlagTerm(seen, false);
emails = folder.search(unseenFlagTerm);
} catch (MessagingException e1) {
- e1.printStackTrace();
+ logger.error(e1);
}
return emails;
@@ -282,7 +308,7 @@ public Message[] getUnreadEmails(Folder folder) {
*
* @param folder The email folder to check.
*/
- public void deleteReadEmails(Folder folder) {
+ public void deleteReadEmails(@NonNull final Folder folder) {
Message[] emails;
try {
Flags seen = new Flags(Flags.Flag.SEEN);
@@ -290,7 +316,7 @@ public void deleteReadEmails(Folder folder) {
emails = folder.search(seenFlagTerm);
folder.setFlags(emails, new Flags(Flags.Flag.DELETED), true);
} catch (MessagingException e1) {
- e1.printStackTrace();
+ logger.error(e1);
}
}
@@ -300,7 +326,7 @@ public void closeConnection() {
store.close();
} catch (MessagingException e) {
logger.error("Error occurred when closing connection.");
- e.printStackTrace();
+ logger.error(e);
}
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/GmailHelper.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/GmailHelper.java
index 24135ff..5fd9bd1 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/GmailHelper.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/GmailHelper.java
@@ -25,7 +25,11 @@
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMultipart;
import java.io.IOException;
+import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.Nullable;
+import lombok.NonNull;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.WebDriver;
@@ -43,18 +47,23 @@ public class GmailHelper extends CommonMailClient {
*
* PLEASE NOTE:
*
- *
To make this work you should use gmail appPassword.
+ *
To make this work you should use a Gmail app password.
*
- *
For more information how to set it, please check
+ *
For more information on how to set it, please check
* https://support.google.com/accounts/answer/185833?hl=en
*
*
Example: username = some@email.com password = xxxx
+ *
+ * @param username The Gmail username (email address). Must not be null.
+ * @param appPassword The Gmail app password.
*/
- public GmailHelper(String username, String appPassword) {
+ public GmailHelper(final String username, final String appPassword) throws MessagingException {
super(username.trim(), appPassword, Protocol.IMAP, "imap.gmail.com");
}
- public GmailHelper(String username, String appPassword, Protocol protocol, String host) {
+ public GmailHelper(
+ final String username, final String appPassword, final Protocol protocol, final String host)
+ throws MessagingException {
super(username, appPassword, protocol, host);
}
@@ -76,11 +85,11 @@ public void emptyEmailBox() {
* @param markEmailAsSeen If true, the email would be marked as seen after checking it.
* @return A message array that contains all the emails that match the mentioned criteria.
*/
- public Message[] waitForEmailToArrive(
- WebDriver driver,
- SearchCriteria criteria,
- boolean checkOnlyUnreadEmails,
- boolean markEmailAsSeen) {
+ public List waitForEmailToArrive(
+ @NonNull final WebDriver driver,
+ @NonNull final SearchCriteria criteria,
+ final boolean checkOnlyUnreadEmails,
+ final boolean markEmailAsSeen) {
return waitForEmailToArrive(
driver, criteria, checkOnlyUnreadEmails, markEmailAsSeen, TEN_MINUTES_TIMEOUT_WAIT_MILLI);
}
@@ -98,27 +107,25 @@ public Message[] waitForEmailToArrive(
* find the email.
* @return A message array that contains all the emails that match the mentioned criteria.
*/
- public Message[] waitForEmailToArrive(
- WebDriver driver,
- SearchCriteria criteria,
- boolean checkOnlyUnreadEmails,
- boolean markEmailAsSeen,
- long timeOutInMillis) {
+ public List waitForEmailToArrive(
+ @Nullable final WebDriver driver,
+ @NonNull final SearchCriteria criteria,
+ final boolean checkOnlyUnreadEmails,
+ final boolean markEmailAsSeen,
+ final long timeOutInMillis) {
logger.info("Waiting for email to arrive...");
int timeElapsed = 0;
- Message[] foundEmails = null;
+ List foundEmails = null;
while (timeElapsed < timeOutInMillis) {
foundEmails = isEmailReceived(criteria, checkOnlyUnreadEmails, markEmailAsSeen);
- if (foundEmails.length == 0) {
+ if (foundEmails.isEmpty()) {
logger.info(
- "Email not received after "
- + timeElapsed / 1000
- + " seconds. Retrying after 5 seconds...");
+ "Email not received after {} seconds. Retrying after 5 seconds...", timeElapsed / 1000);
ThreadHelper.sleep(FIVE_SECOND_WAIT_MILLI);
timeElapsed += FIVE_SECOND_WAIT_MILLI;
- /**
+ /*
* Get the session ID to prevent remote Cloud provider from closing the connection for being
* idle (Usually timeouts after 90 seconds).
*/
@@ -132,7 +139,7 @@ public Message[] waitForEmailToArrive(
}
}
- /**
+ /*
* Shutdown hook to make sure the email server connection is terminated correctly before the
* application terminates.
*/
@@ -155,7 +162,7 @@ public Message[] waitForEmailToArrive(
* @param email The email object to check
* @return A string representing the content of the concatenated parts of the email object.
*/
- public String parseEmailParts(Message email) {
+ public String parseEmailParts(@NonNull final Message email) {
String result = "";
try {
if (email.isMimeType("text/plain")) {
@@ -179,40 +186,40 @@ public String parseEmailParts(Message email) {
* @param email The email object to check
* @return A string representation to the email's input stream.
*/
- public String parseEmailFromInputStream(Message email) {
+ public String parseEmailFromInputStream(@NonNull final Message email) {
try {
- return new String(email.getInputStream().readAllBytes());
+ return new String(email.getInputStream().readAllBytes(), Charset.defaultCharset());
} catch (Exception e) {
- e.printStackTrace();
+ logger.error(e);
}
return null;
}
/**
- * Extracts the text from multipart emails
+ * Extracts the text from multipart emails.
*
* @param mimeMultipart The multipart email to get the content from.
- * @return A string representing the email content
- * @throws MessagingException
- * @throws IOException
+ * @return A string representing the email content.
+ * @throws MessagingException If a messaging exception occurs.
+ * @throws IOException If an I/O exception occurs.
*/
- private String getTextFromMimeMultipart(MimeMultipart mimeMultipart)
+ private String getTextFromMimeMultipart(@NonNull final MimeMultipart mimeMultipart)
throws MessagingException, IOException {
- String result = "";
+ StringBuilder result = new StringBuilder();
int count = mimeMultipart.getCount();
for (int i = 0; i < count; i++) {
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
if (bodyPart.isMimeType("text/plain")) {
- result += "\n" + bodyPart.getContent();
+ result.append('\n').append(bodyPart.getContent());
break; // without break same text appears twice in my tests
} else if (bodyPart.isMimeType("text/html")) {
String html = (String) bodyPart.getContent();
- result += "\n" + org.jsoup.Jsoup.parse(html).text();
+ result.append('\n').append(org.jsoup.Jsoup.parse(html).text());
} else if (bodyPart.getContent() instanceof MimeMultipart) {
- result += getTextFromMimeMultipart((MimeMultipart) bodyPart.getContent());
+ result.append(getTextFromMimeMultipart((MimeMultipart) bodyPart.getContent()));
}
}
- return result;
+ return result.toString();
}
/**
@@ -225,9 +232,11 @@ private String getTextFromMimeMultipart(MimeMultipart mimeMultipart)
* @param markEmailAsSeen If true, the email would be marked as seen after checking it.
* @return A message array that contains all the emails that match the mentioned criteria.
*/
- public Message[] isEmailReceived(
- SearchCriteria criteria, boolean checkOnlyUnreadEmails, boolean markEmailAsSeen) {
- ArrayList matchedEmails = new ArrayList<>();
+ public List isEmailReceived(
+ @NonNull final SearchCriteria criteria,
+ final boolean checkOnlyUnreadEmails,
+ final boolean markEmailAsSeen) {
+ final var matchedEmails = new ArrayList();
try {
Message[] emails;
if (checkOnlyUnreadEmails) {
@@ -238,7 +247,7 @@ public Message[] isEmailReceived(
if (emails.length == 0) {
logger.info("No emails found, moving on...");
- return null;
+ return List.of();
}
logger.info("Found emails: " + emails.length);
@@ -247,7 +256,7 @@ public Message[] isEmailReceived(
logger.info("---------------------------------");
logger.info("Email Number: [{}]", i + 1);
logger.info("Subject: [{}]", email.getSubject());
- logger.info("From: [{}]", email.getFrom());
+ logger.info("From: [{}]", (Object) email.getFrom());
// check if the email matches the criteria
if (doesEmailMatchCriteria(email, criteria)) {
@@ -258,10 +267,11 @@ public Message[] isEmailReceived(
email.setFlag(Flag.SEEN, true);
}
}
+ return matchedEmails;
} catch (Exception e) {
- logger.info("An exception was thrown. Message = " + e.getMessage());
+ logger.info("An exception was thrown.", e);
}
- return matchedEmails.toArray(new Message[matchedEmails.size()]);
+ return List.of(new Message[0]);
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/SearchCriteria.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/SearchCriteria.java
index 8fbb33f..8e69861 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/SearchCriteria.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/email/SearchCriteria.java
@@ -17,15 +17,11 @@
*/
package com.applause.auto.helpers.email;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-/** Simple POJO that represents the search criteria when searching for emails. */
-@AllArgsConstructor
-@Data
-public class SearchCriteria {
-
- private String emailSubject;
- private String sentFrom;
- private String sentTo;
-}
+/**
+ * Simple record that represents the search criteria when searching for emails.
+ *
+ * @param emailSubject The subject of the email to search for.
+ * @param sentFrom The sender of the email to search for.
+ * @param sentTo The recipient of the email to search for.
+ */
+public record SearchCriteria(String emailSubject, String sentFrom, String sentTo) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/google/GoogleSheetParser.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/google/GoogleSheetParser.java
index 66a8937..171f96f 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/google/GoogleSheetParser.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/google/GoogleSheetParser.java
@@ -28,180 +28,156 @@
import com.google.api.services.sheets.v4.model.*;
import java.io.IOException;
import java.io.InputStream;
-import java.security.GeneralSecurityException;
-import java.util.*;
-import java.util.stream.Collectors;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
import lombok.Getter;
+import lombok.NonNull;
import lombok.SneakyThrows;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
- * Google Sheet parser (from Google Drive) [Requires some configuration management from Google Cloud
- * side] Some common tutorials:
+ * Utility class for parsing Google Sheets. Requires configuration management on the Google Cloud
+ * side.
*/
-public class GoogleSheetParser {
+@SuppressWarnings("PMD.LooseCoupling")
+public final class GoogleSheetParser {
private static final Logger logger = LogManager.getLogger(GoogleSheetParser.class);
+ private static final String KEY_PARAMETER = "key";
- @Getter private String sheetId;
-
- @Getter private String googleSheetParsingCloudConfiguredApplicationName;
-
- private Sheets service;
+ @Getter private final String sheetId;
+ @Getter private final String applicationName;
+ private final Sheets service;
/**
- * Create sheet parser using API key access That will work once Google sheet document is available
- * for sharing with "Everyone with a link" option
+ * Constructs a GoogleSheetParser using an API key.
*
- * @param apiKey
- * @param sheetId
+ * @param apiKey The API key.
+ * @param sheetId The Google Sheet ID.
+ * @param applicationName The application name.
*/
public GoogleSheetParser(
- String apiKey, String sheetId, String googleSheetParsingCloudConfiguredApplicationName) {
+ @NonNull final String apiKey,
+ @NonNull final String sheetId,
+ @NonNull final String applicationName) {
this.sheetId = sheetId;
- this.googleSheetParsingCloudConfiguredApplicationName =
- googleSheetParsingCloudConfiguredApplicationName;
- NetHttpTransport transport = new NetHttpTransport.Builder().build();
- HttpRequestInitializer httpRequestInitializer =
- request -> {
- request.setInterceptor(intercepted -> intercepted.getUrl().set("key", apiKey));
- };
+ this.applicationName = applicationName;
+
+ final HttpTransport transport = new NetHttpTransport.Builder().build();
+ final HttpRequestInitializer httpRequestInitializer =
+ request ->
+ request.setInterceptor(intercepted -> intercepted.getUrl().set(KEY_PARAMETER, apiKey));
+
this.service =
new Sheets.Builder(transport, GsonFactory.getDefaultInstance(), httpRequestInitializer)
- .setApplicationName(googleSheetParsingCloudConfiguredApplicationName)
+ .setApplicationName(applicationName)
.build();
}
/**
- * Create parser using service account .json file
+ * Constructs a GoogleSheetParser using a service account JSON file.
*
- * @param serviceAccountJsonFileInputStream input stream for .json file with configs
- * @param sheetId Google sheet id value (unique part of access link)
- * @throws IOException
- * @throws GeneralSecurityException
+ * @param serviceAccountJsonFileInputStream The input stream for the service account JSON file.
+ * @param sheetId The Google Sheet ID.
+ * @param applicationName The application name.
*/
+ @SuppressWarnings("deprecation")
@SneakyThrows
public GoogleSheetParser(
- InputStream serviceAccountJsonFileInputStream,
- String sheetId,
- String googleSheetParsingCloudConfiguredApplicationName) {
+ @NonNull final InputStream serviceAccountJsonFileInputStream,
+ @NonNull final String sheetId,
+ @NonNull final String applicationName) {
this.sheetId = sheetId;
- this.googleSheetParsingCloudConfiguredApplicationName =
- googleSheetParsingCloudConfiguredApplicationName;
- HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
- GoogleCredential googleCredentials =
+ this.applicationName = applicationName;
+
+ final HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
+ final GoogleCredential credentials =
GoogleCredential.fromStream(serviceAccountJsonFileInputStream)
.createScoped(Collections.singletonList(SheetsScopes.SPREADSHEETS));
this.service =
- new Sheets.Builder(httpTransport, GsonFactory.getDefaultInstance(), googleCredentials)
- .setApplicationName(googleSheetParsingCloudConfiguredApplicationName)
+ new Sheets.Builder(httpTransport, GsonFactory.getDefaultInstance(), credentials)
+ .setApplicationName(applicationName)
.build();
}
/**
- * Get all sheet cell records
+ * Retrieves all cell records from a sheet.
*
- * @param sheetTitle sheet title
- * @return kind of a matrix values from Google sheet file per sheet title from a document
- * @throws IOException
+ * @param sheetTitle The title of the sheet.
+ * @return A list of lists representing the cell values.
+ * @throws IOException If an I/O error occurs.
+ * @throws GoogleSheetParserException If the sheet is not found or no values are present.
*/
- public List> getAllSheetCellRecords(String sheetTitle) throws IOException {
- SheetProperties sheetProperties = getSheetObjectBySheetTitle(sheetTitle).getProperties();
- List dataFilters = new ArrayList<>();
- DataFilter dataFilterForWholeDocumentCells = getAllSheetCellsDataFilter(sheetProperties);
- dataFilters.add(dataFilterForWholeDocumentCells);
-
- BatchGetValuesByDataFilterRequest batchGetValuesByDataFilterRequest =
- getBatchFilterRequest(dataFilters);
- BatchGetValuesByDataFilterResponse batchGetValuesByDataFilterResponse =
- service
- .spreadsheets()
- .values()
- .batchGetByDataFilter(sheetId, batchGetValuesByDataFilterRequest)
- .execute();
- List matchedValueRanges =
- batchGetValuesByDataFilterResponse.getValueRanges();
- List> values = getCellMatrixFromValueRanges(dataFilters, matchedValueRanges);
- logger.info("Lines loaded from Sheet: " + values.size());
+ public List> getAllSheetCellRecords(@NonNull final String sheetTitle)
+ throws IOException {
+ final var sheetProperties = getSheetObjectBySheetTitle(sheetTitle).getProperties();
+ final var dataFilter = getAllSheetCellsDataFilter(sheetProperties);
+
+ final var request = new BatchGetValuesByDataFilterRequest();
+ request.setDataFilters(List.of(dataFilter));
+
+ final var response =
+ service.spreadsheets().values().batchGetByDataFilter(sheetId, request).execute();
+
+ final var valueRanges = response.getValueRanges();
+ final var values = getCellMatrixFromValueRanges(List.of(dataFilter), valueRanges);
+
+ logger.info("Lines loaded from Sheet: {}", values.size());
return values;
}
@SneakyThrows
- private Sheet getSheetObjectBySheetTitle(String sheetName) {
- Spreadsheet spreadsheetDocument = service.spreadsheets().get(sheetId).execute();
+ private Sheet getSheetObjectBySheetTitle(@NonNull final String sheetName) {
+ final var spreadsheetDocument = service.spreadsheets().get(sheetId).execute();
return spreadsheetDocument.getSheets().stream()
.filter(sheet -> sheet.getProperties().getTitle().equals(sheetName))
.findFirst()
.orElseThrow(
- () ->
- new GoogleSheetParserException(
- "Sheet with title: " + sheetName + " not " + "found"));
+ () -> new GoogleSheetParserException("Sheet with title: " + sheetName + " not found"));
}
- private DataFilter getAllSheetCellsDataFilter(SheetProperties sheetProperties) {
- DataFilter dataFilter = new DataFilter();
- GridRange gridRange = new GridRange();
- GridProperties gridProperties = sheetProperties.getGridProperties();
+ private DataFilter getAllSheetCellsDataFilter(@NonNull final SheetProperties sheetProperties) {
+ final var dataFilter = new DataFilter();
+ final var gridRange = new GridRange();
+ final var gridProperties = sheetProperties.getGridProperties();
+
gridRange.setSheetId(sheetProperties.getSheetId());
- int startIndex = 0;
- int endRowIndex = gridProperties.getRowCount() - 1;
- int startColumnIndex = 0;
- int endColumnIndex = gridProperties.getColumnCount() - 1;
+ gridRange.setStartRowIndex(0);
+ gridRange.setEndRowIndex(gridProperties.getRowCount() - 1);
+ gridRange.setStartColumnIndex(0);
+ gridRange.setEndColumnIndex(gridProperties.getColumnCount() - 1);
+
logger.info(
- "Creating data filter for sheet: {} with row range [{} , {}] and column range [{} , {}]",
+ "Creating data filter for sheet: {} with row range [{}, {}] and column range [{}, {}]",
sheetProperties.getTitle(),
- startIndex,
- endRowIndex,
- startColumnIndex,
- endColumnIndex);
- gridRange.setStartRowIndex(startIndex);
- gridRange.setEndRowIndex(endRowIndex);
- gridRange.setStartColumnIndex(startColumnIndex);
- gridRange.setEndColumnIndex(endColumnIndex);
+ gridRange.getStartRowIndex(),
+ gridRange.getEndRowIndex(),
+ gridRange.getStartColumnIndex(),
+ gridRange.getEndColumnIndex());
dataFilter.setGridRange(gridRange);
return dataFilter;
}
- private BatchGetValuesByDataFilterRequest getBatchFilterRequest(List dataFilters) {
- BatchGetValuesByDataFilterRequest batchGetValuesByDataFilterRequest =
- new BatchGetValuesByDataFilterRequest();
- batchGetValuesByDataFilterRequest.setDataFilters(dataFilters);
- return batchGetValuesByDataFilterRequest;
- }
-
private List> getCellMatrixFromValueRanges(
- List dataFilters, List matchedValueRanges) {
- int dataFiltersCount = dataFilters.size();
- if (matchedValueRanges.size() != dataFiltersCount) {
- throw new GoogleSheetParserException(
- "No value ranges data present for "
- + dataFilters.stream()
- .map(filter -> filter.getGridRange())
- .collect(Collectors.toList()));
- }
+ @NonNull final List dataFilters,
+ @NonNull final List matchedValueRanges) {
- List> values =
- (List>)
- matchedValueRanges
- // TODO Implement dynamic filtering approach with passing List as param
- .get(dataFiltersCount - 1)
- .getValueRange()
- .values()
- .stream()
- .filter(valueObject -> Collection.class.isAssignableFrom(valueObject.getClass()))
- .findFirst()
- .orElseThrow(
- () ->
- new GoogleSheetParserException(
- "No Collection value object found in value range result response"));
- if (Objects.nonNull(values) && !values.isEmpty()) {
- return values;
- } else {
- logger.error("No data 'matrix' found in range");
- return List.of(Collections.emptyList());
+ if (matchedValueRanges.size() != dataFilters.size()) {
+ final String filters = dataFilters.stream().map(DataFilter::getGridRange).toList().toString();
+ throw new GoogleSheetParserException("No value ranges data present for " + filters);
}
+
+ return Collections.singletonList(
+ matchedValueRanges.getFirst().getValueRange().getValues().stream()
+ .filter(Objects::nonNull)
+ .findFirst()
+ .orElseThrow(
+ () ->
+ new GoogleSheetParserException(
+ "No Collection value object found in value range result response")));
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/google/GoogleSheetParserException.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/google/GoogleSheetParserException.java
index b3e7df9..1de14e3 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/google/GoogleSheetParserException.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/google/GoogleSheetParserException.java
@@ -17,9 +17,11 @@
*/
package com.applause.auto.helpers.google;
+import lombok.NonNull;
+
public class GoogleSheetParserException extends RuntimeException {
- public GoogleSheetParserException(String message) {
+ public GoogleSheetParserException(@NonNull final String message) {
super(message);
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/mapping/JacksonJSONRestObjectMapping.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/mapping/JacksonJSONRestObjectMapping.java
index a41ac4c..a1dd762 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/mapping/JacksonJSONRestObjectMapping.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/mapping/JacksonJSONRestObjectMapping.java
@@ -22,19 +22,19 @@
/** Jackson library json REST API typical object mapper instance */
public class JacksonJSONRestObjectMapping implements IRestObjectMapper {
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper()
+ .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, false);
/**
* Object mapper for REST JSON Jackson mapping
*
- * @return
+ * @return shared ObjectMapper
*/
@Override
public ObjectMapper restJsonObjectMapper() {
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
- objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- objectMapper.configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, false);
-
return objectMapper;
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/RestApiDefaultRestAssuredApiHelper.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/RestApiDefaultRestAssuredApiHelper.java
index 87f615b..f7d2f8b 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/RestApiDefaultRestAssuredApiHelper.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/RestApiDefaultRestAssuredApiHelper.java
@@ -31,7 +31,7 @@
@Getter
public class RestApiDefaultRestAssuredApiHelper {
- private RestAssuredApiClient restAssuredApiClient;
+ private final RestAssuredApiClient restAssuredApiClient;
public RestApiDefaultRestAssuredApiHelper() {
restAssuredApiClient = new RestApiDefaultRestAssuredApiClient(Duration.ofSeconds(60));
@@ -40,7 +40,7 @@ public RestApiDefaultRestAssuredApiHelper() {
/**
* 'with' describing default RestAssuredConfig
*
- * @return
+ * @return request specification
*/
public RequestSpecification withDefaultRestHttpClientConfigsSpecification() {
return restAssuredApiClient.restAssuredRequestSpecification(new JacksonJSONRestObjectMapping());
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/client/RestApiDefaultRestAssuredApiClient.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/client/RestApiDefaultRestAssuredApiClient.java
index d9bcacc..8620aba 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/client/RestApiDefaultRestAssuredApiClient.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/client/RestApiDefaultRestAssuredApiClient.java
@@ -27,21 +27,23 @@
import io.restassured.specification.RequestSpecification;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
+import lombok.NonNull;
/** Default rest assured REST API client impl. */
public class RestApiDefaultRestAssuredApiClient extends RestAssuredApiClient {
- public RestApiDefaultRestAssuredApiClient(Duration apiRequestWaitTimeoutDuration) {
+ public RestApiDefaultRestAssuredApiClient(final Duration apiRequestWaitTimeoutDuration) {
super(apiRequestWaitTimeoutDuration);
}
/**
* get rest assured request specification object for default client
*
- * @return
+ * @return request specification
*/
@Override
- public RequestSpecification restAssuredRequestSpecification(IRestObjectMapper restObjectMapper) {
+ public RequestSpecification restAssuredRequestSpecification(
+ @NonNull final IRestObjectMapper restObjectMapper) {
return super.restAssuredRequestSpecification(restObjectMapper)
.filter(new RequestLoggingFilter(LogDetail.URI))
.response()
@@ -52,11 +54,11 @@ public RequestSpecification restAssuredRequestSpecification(IRestObjectMapper re
/**
* rest assured config with object mapper for default client
*
- * @param restObjectMapper
- * @return
+ * @param restObjectMapper the object mapper
+ * @return configured RestAssured client
*/
@Override
- protected RestAssuredConfig restAssuredConfig(IRestObjectMapper restObjectMapper) {
+ protected RestAssuredConfig restAssuredConfig(@NonNull final IRestObjectMapper restObjectMapper) {
RestAssuredConfig restAssuredConfig = new RestAssuredConfig();
restAssuredConfig =
restAssuredConfig
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/client/RestAssuredApiClient.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/client/RestAssuredApiClient.java
index 8fd2b84..8f0b94c 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/client/RestAssuredApiClient.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/http/restassured/client/RestAssuredApiClient.java
@@ -24,30 +24,39 @@
import io.restassured.specification.RequestSpecification;
import java.time.Duration;
import lombok.Getter;
+import lombok.NonNull;
/** Rest assured api client */
@Getter
public abstract class RestAssuredApiClient {
- private Duration apiRequestWaitTimeoutDuration;
+ private final Duration apiRequestWaitTimeoutDuration;
- public RestAssuredApiClient(Duration apiRequestWaitTimeoutDuration) {
+ /**
+ * Constructs a new RestAssuredApiClient.
+ *
+ * @param apiRequestWaitTimeoutDuration The timeout duration for API requests.
+ */
+ public RestAssuredApiClient(@NonNull final Duration apiRequestWaitTimeoutDuration) {
this.apiRequestWaitTimeoutDuration = apiRequestWaitTimeoutDuration;
}
/**
- * get rest assured request specification object
+ * Gets a Rest Assured request specification object.
*
- * @return
+ * @param restObjectMapper The REST object mapper to use.
+ * @return A Rest Assured request specification.
*/
- public RequestSpecification restAssuredRequestSpecification(IRestObjectMapper restObjectMapper) {
+ public RequestSpecification restAssuredRequestSpecification(
+ final IRestObjectMapper restObjectMapper) {
return given().when().request().config(restAssuredConfig(restObjectMapper));
}
/**
- * abstract rest assured config object
+ * Creates a Rest Assured config object.
*
- * @return
+ * @param restObjectMapper The REST object mapper to use.
+ * @return A Rest Assured config object.
*/
protected abstract RestAssuredConfig restAssuredConfig(IRestObjectMapper restObjectMapper);
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/annotations/scanner/JiraAnnotationsScanner.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/annotations/scanner/JiraAnnotationsScanner.java
index 1fc1dd6..7d8943a 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/annotations/scanner/JiraAnnotationsScanner.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/annotations/scanner/JiraAnnotationsScanner.java
@@ -21,50 +21,34 @@
import com.applause.auto.helpers.jira.annotations.JiraID;
import com.applause.auto.helpers.jira.exceptions.JiraAnnotationException;
import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Objects;
-import org.testng.ITestResult;
+import lombok.NonNull;
-public class JiraAnnotationsScanner {
+public final class JiraAnnotationsScanner {
+
+ private JiraAnnotationsScanner() {
+ // utility class
+ }
/**
* Scan test and get declared JiraId value Annotation is mandatory to be declared, otherwise
* exception is thrown
*
- * @param result
+ * @param result the test result
* @return JiraId identifier
- * @throws JiraAnnotationException
+ * @throws JiraAnnotationException JIRA library error
*/
- public static String getJiraIdentifier(ITestResult result) throws JiraAnnotationException {
- Method[] methods = result.getTestClass().getRealClass().getMethods();
- try {
- return Objects.requireNonNull(
- Arrays.stream(methods)
- .filter(method -> method.getName().equals(result.getMethod().getMethodName()))
- .findFirst()
- .get()
- .getAnnotation(JiraID.class)
- .identifier());
- } catch (NullPointerException nullPointerException) {
- throw new JiraAnnotationException(
- String.format("Missing JiraId annotation for test [%s]", result.getName()));
- }
+ public static String getJiraIdentifier(@NonNull final Method result)
+ throws JiraAnnotationException {
+ return result.getAnnotation(JiraID.class).identifier();
}
/**
* Scan test and get declared JiraDefect value
*
- * @param result
+ * @param result test result
* @return JiraDefect identifier
*/
- public static String getJiraDefect(ITestResult result) {
- Method[] methods = result.getTestClass().getRealClass().getMethods();
- return Objects.requireNonNull(
- Arrays.stream(methods)
- .filter(method -> method.getName().equals(result.getMethod().getMethodName()))
- .findFirst()
- .orElse(null))
- .getAnnotation(JiraDefect.class)
- .identifier();
+ public static String getJiraDefect(@NonNull final Method result) {
+ return result.getAnnotation(JiraDefect.class).identifier();
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/JiraXrayClient.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/JiraXrayClient.java
index fe1f9f3..3ec4783 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/JiraXrayClient.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/JiraXrayClient.java
@@ -24,19 +24,16 @@
import com.applause.auto.helpers.jira.clients.modules.xray.StepsAPI;
import com.applause.auto.helpers.jira.clients.modules.xray.TestrunAPI;
import java.util.Objects;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
/**
* Class for communicating with JIRA/X-Ray Server + DC instance API end-points.
*
* Cannot be used with Cloud instances, use GraphQL instead.
*
- *
X-Ray documentation: https://docs.getxray.app/display/XRAY/REST+API
+ *
X-Ray documentation: ...
*/
-public class JiraXrayClient {
-
- private static final Logger logger = LogManager.getLogger(JiraXrayClient.class);
+@SuppressWarnings("PMD.DataClass")
+public final class JiraXrayClient {
private JiraProjectAPI jiraProjectAPI;
private SearchAPI searchAPI;
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/jira/JiraProjectAPI.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/jira/JiraProjectAPI.java
index 482c096..a292a19 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/jira/JiraProjectAPI.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/jira/JiraProjectAPI.java
@@ -19,8 +19,6 @@
import static com.applause.auto.helpers.jira.constants.XrayEndpoints.*;
import static com.applause.auto.helpers.jira.helper.ResponseValidator.checkResponseInRange;
-import static com.applause.auto.helpers.jira.requestData.XrayRequestHeaders.getAtlassianNoCheckHeader;
-import static com.applause.auto.helpers.jira.requestData.XrayRequestHeaders.getContentTypeMultipartFormDataHeader;
import static com.applause.auto.helpers.jira.restclient.XrayRestAssuredClient.getRestClient;
import com.applause.auto.helpers.jira.dto.requestmappers.JiraCreateTicketRequest;
@@ -29,39 +27,42 @@
import com.applause.auto.helpers.jira.dto.responsemappers.JiraCreateTicketResponse;
import com.applause.auto.helpers.jira.dto.responsemappers.steps.Steps;
import com.applause.auto.helpers.jira.dto.shared.Issuetype;
+import com.applause.auto.helpers.util.GenericObjectMapper;
+import com.applause.auto.helpers.util.XrayRequestHeaders;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.response.Response;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;
+import lombok.NonNull;
import org.apache.commons.lang3.Range;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+@SuppressWarnings("checkstyle:MultipleStringLiterals")
public class JiraProjectAPI {
private static final Logger logger = LogManager.getLogger(JiraProjectAPI.class);
- private ObjectMapper mapper = new ObjectMapper();
/**
- * Creates a simple JIRA ticket, additional fields can be created as per project's needs. This
- * method can be used to create a new test case, test plan, test execution etc.
- * https://developer.atlassian.com/server/jira/platform/jira-rest-api-examples/
+ * Creates a simple JIRA ticket. Additional fields can be created as per project's needs. This
+ * method can be used to create a new test case, test plan, test execution, etc. ...
*
- * @param jiraCreateTicketRequestMapping, Object of JiraCreateTicketRequestMapping ticket's title
- * @return ticket key extracted from response: {"id":"", "key":"", "self":""}
- * @throws JsonProcessingException
+ * @param jiraCreateTicketRequest The request object containing the ticket details.
+ * @return The ticket key extracted from the response (e.g., "PROJECT-123").
+ * @throws JsonProcessingException If an error occurs during JSON processing.
*/
- public String createTicket(JiraCreateTicketRequest jiraCreateTicketRequestMapping)
+ public String createTicket(@NonNull final JiraCreateTicketRequest jiraCreateTicketRequest)
throws JsonProcessingException {
- logger.info("Creating Jira ticket: {}", jiraCreateTicketRequestMapping.toString());
- Response response = postTicket(jiraCreateTicketRequestMapping);
- checkResponseInRange(response, Range.between(200, 300), "Creating new Jira Ticket");
- JiraCreateTicketResponse jiraCreateTicketResponseMapping =
- mapper.readValue(response.asString(), JiraCreateTicketResponse.class);
- String createdJiraTicketId = jiraCreateTicketResponseMapping.getKey();
+ logger.info("Creating Jira ticket: {}", jiraCreateTicketRequest.toString());
+ Response response = postTicket(jiraCreateTicketRequest);
+ checkResponseInRange(response, Range.of(200, 300), "Creating new Jira Ticket");
+ JiraCreateTicketResponse jiraCreateTicketResponse =
+ GenericObjectMapper.getObjectMapper()
+ .readValue(response.asString(), JiraCreateTicketResponse.class);
+ String createdJiraTicketId = jiraCreateTicketResponse.key();
logger.info("Created Jira ticket: {}", createdJiraTicketId);
return createdJiraTicketId;
}
@@ -69,106 +70,121 @@ public String createTicket(JiraCreateTicketRequest jiraCreateTicketRequestMappin
/**
* Modify existing Jira Ticket by sending the short or full json data
*
- * @param jiraTicketID
- * @param jsonAsString
- * @example: { "fields" : { "labels": [ "my_new_label" ] } }
+ * @param jiraTicketID the Jira ticket ID
+ * @param jsonAsString JIRA ticket JSON contents {@code @example:} { "fields" : { "labels": [
+ * "my_new_label" ] } }
*/
- public void updateTicket(String jiraTicketID, String jsonAsString) {
+ public void updateTicket(@NonNull final String jiraTicketID, @NonNull final String jsonAsString) {
logger.info("Updating Jira ticket: {} with [ {} ]", jiraTicketID, jsonAsString);
Response response = putUpdateTicket(jiraTicketID, jsonAsString);
- checkResponseInRange(response, Range.between(200, 300), "Updating Jira Ticket");
+ checkResponseInRange(response, Range.of(200, 300), "Updating Jira Ticket");
}
/**
* Delete existing Jira Ticket
*
- * @param jiraTicketID
+ * @param jiraTicketID JIRA ticket ID
*/
- public void deleteTicket(String jiraTicketID) {
+ public void deleteTicket(@NonNull final String jiraTicketID) {
logger.info("Deleting Jira ticket: {}", jiraTicketID);
Response response = deleteExistingTicket(jiraTicketID);
- checkResponseInRange(response, Range.between(200, 300), "Deleting Jira Ticket");
+ checkResponseInRange(response, Range.of(200, 300), "Deleting Jira Ticket");
}
/**
* Get Test Case steps
*
- * @param jiraTicketID
+ * @param jiraTicketID JIRA ticket ID
* @return Steps object
*/
- public Steps getTestCaseSteps(String jiraTicketID) throws JsonProcessingException {
+ public Steps getTestCaseSteps(@NonNull final String jiraTicketID) throws JsonProcessingException {
Response response = getJiraTestCaseSteps(jiraTicketID);
- Steps steps = mapper.readValue(response.asString(), Steps.class);
- checkResponseInRange(response, Range.between(200, 300), "Get Test Case Steps");
+ Steps steps = GenericObjectMapper.getObjectMapper().readValue(response.asString(), Steps.class);
+ checkResponseInRange(response, Range.of(200, 300), "Get Test Case Steps");
return steps;
}
/**
- * Upload file to specific jira ticket (issue, testcase, execution, plan etc) Checks performed: 1.
- * If provided file exists 2. If response contains file name and if status code is in 200 range
+ * Upload file to specific jira ticket (issue, testcase, execution, plan etc). Checks performed:
+ *
+ *
+ * - If provided file exists
+ *
- If response contains file name and if status code is in 200 range
+ *
*
- * @param jiraTicketID, represents the jira ticket identifier
- * @param pathToFile, full path to file with its extension
- * @return void
+ * @param jiraTicketID represents the jira ticket identifier.
+ * @param pathToFile full path to file with its extension.
+ * @throws FileNotFoundException If the file specified by {@code pathToFile} does not exist.
*/
- public void uploadAttachment(String jiraTicketID, String pathToFile)
+ public void uploadAttachment(@NonNull final String jiraTicketID, @NonNull final String pathToFile)
throws FileNotFoundException {
Response response = postAttachment(jiraTicketID, pathToFile);
String fileName = new File(pathToFile).getName();
if (!response.getBody().asString().contains(fileName)) {
logger.error("Failed to upload attachment {}", fileName);
}
- checkResponseInRange(response, Range.between(200, 300), "Adding attachment");
+ checkResponseInRange(response, Range.of(200, 300), "Adding attachment");
}
/**
- * @param projectKey, represents the jira project identifier Example CARQA-1234, where CARQA is
- * the project identifier
- * @return projectId
+ * Retrieves the project ID associated with a given project key.
+ *
+ * @param projectKey The Jira project identifier (e.g., "CARQA-1234", where "CARQA" is the project
+ * identifier). Must not be null.
+ * @return The project ID as a String.
+ * @throws JsonProcessingException If there is an error processing the JSON response.
+ * @throws NullPointerException If the provided projectKey is null.
*/
- public String getProjectId(String projectKey) throws JsonProcessingException {
- StringBuilder apiEndpoint = new StringBuilder();
- apiEndpoint.append(LATEST_API).append("/").append(PROJECT);
+ public String getProjectId(@NonNull final String projectKey) throws JsonProcessingException {
Response response = getProjectCode(projectKey);
- checkResponseInRange(response, Range.between(200, 300), "Determine project Id");
+ checkResponseInRange(response, Range.of(200, 300), "Determine project Id");
AvailableProjects[] availableProjects =
- mapper.readValue(response.asString(), AvailableProjects[].class);
+ GenericObjectMapper.getObjectMapper()
+ .readValue(response.asString(), AvailableProjects[].class);
return Arrays.stream(availableProjects)
- .filter(project -> project.getKey().equalsIgnoreCase(projectKey))
+ .filter(project -> project.key().equalsIgnoreCase(projectKey))
.findFirst()
.get()
- .getId();
+ .id();
}
/**
- * @param projectId, represents the project identifier code
- * @return list of Issuetype objects
+ * Retrieves a list of available issue types for a given project.
+ *
+ * @param projectId the identifier of the project.
+ * @return a list of Issuetype objects representing the available issue types.
+ * @throws JsonProcessingException if there is an error processing the JSON response.
*/
- public List getAvailableIssueTypes(String projectId) throws JsonProcessingException {
+ public List getAvailableIssueTypes(@NonNull final String projectId)
+ throws JsonProcessingException {
Response response = getAvailableIssues(projectId);
- checkResponseInRange(response, Range.between(200, 300), "Get project issue types");
- return mapper.readValue(response.asString(), AvailableIssueTypes.class).getValues();
+ checkResponseInRange(response, Range.of(200, 300), "Get project issue types");
+ return GenericObjectMapper.getObjectMapper()
+ .readValue(response.asString(), AvailableIssueTypes.class)
+ .values();
}
/**
* Attach label to Jira ticket
*
- * @param jiraTicketID
- * @param labelName
+ * @param jiraTicketID JIRA ticket ID
+ * @param labelName Ticket label name
*/
- public void addLabel(String jiraTicketID, String labelName) {
+ public void addLabel(@NonNull final String jiraTicketID, @NonNull final String labelName) {
logger.info("Updating Jira ticket: {} with [ {} ] label", jiraTicketID, labelName);
Response response = putLabelToTicket(jiraTicketID, labelName);
- checkResponseInRange(response, Range.between(200, 300), "Adding Jira Ticket label");
+ checkResponseInRange(response, Range.of(200, 300), "Adding Jira Ticket label");
}
- private Response postTicket(JiraCreateTicketRequest jiraCreateTicketRequestMapping)
+ private Response postTicket(@NonNull final JiraCreateTicketRequest jiraCreateTicketRequestMapping)
throws JsonProcessingException {
logger.info("Creating Jira ticket: {}", jiraCreateTicketRequestMapping.toString());
return getRestClient()
.given()
.and()
- .body(mapper.writeValueAsString(jiraCreateTicketRequestMapping))
+ .body(
+ GenericObjectMapper.getObjectMapper()
+ .writeValueAsString(jiraCreateTicketRequestMapping))
.when()
.post(ISSUE_PATH)
.then()
@@ -176,93 +192,75 @@ private Response postTicket(JiraCreateTicketRequest jiraCreateTicketRequestMappi
.response();
}
- private Response putUpdateTicket(String jiraTicketID, String jsonAsString) {
+ private Response putUpdateTicket(
+ @NonNull final String jiraTicketID, @NonNull final String jsonAsString) {
logger.info("Updating Jira Ticket {} with [ {} ]", jiraTicketID, jsonAsString);
- StringBuilder apiEndpoint = new StringBuilder(ISSUE_PATH);
- apiEndpoint.append("/").append(jiraTicketID);
+ final var apiEndpoint = ISSUE_PATH + "/" + jiraTicketID;
return getRestClient()
.given()
.and()
.body(jsonAsString)
.when()
- .put(apiEndpoint.toString())
+ .put(apiEndpoint)
.then()
.extract()
.response();
}
- private Response getJiraTestCaseSteps(String jiraTicketID) {
+ private Response getJiraTestCaseSteps(@NonNull final String jiraTicketID) {
logger.info("Getting X-Ray Test Case Steps response for case: {}", jiraTicketID);
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint.append(TEST).append("/").append(jiraTicketID).append("/").append(STEPS);
- return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint = XRAY_PATH + TEST + "/" + jiraTicketID + "/" + STEPS;
+ return getRestClient().given().when().get(apiEndpoint).then().extract().response();
}
- private Response postAttachment(String jiraTicketID, String pathToFile)
+ private Response postAttachment(
+ @NonNull final String jiraTicketID, @NonNull final String pathToFile)
throws FileNotFoundException {
logger.info("Uploading attachment {} to Jira Ticket {}", pathToFile, jiraTicketID);
File attachment = new File(pathToFile);
if (!attachment.exists()) {
throw new FileNotFoundException(String.format("Unable to find file %s", pathToFile));
}
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint.append(ISSUE_PATH).append("/").append(jiraTicketID).append("/").append(ATTACHMENTS);
+ String apiEndpoint = XRAY_PATH + ISSUE_PATH + "/" + jiraTicketID + "/" + ATTACHMENTS;
return getRestClient()
.given()
- .header(getContentTypeMultipartFormDataHeader())
- .header(getAtlassianNoCheckHeader())
+ .header(XrayRequestHeaders.getContentTypeMultipartFormDataHeader())
+ .header(XrayRequestHeaders.getAtlassianNoCheckHeader())
.multiPart("file", attachment)
.and()
.when()
- .post(apiEndpoint.toString())
+ .post(apiEndpoint)
.then()
.extract()
.response();
}
- private Response getProjectCode(String projectKey) {
+ private Response getProjectCode(@NonNull final String projectKey) {
logger.info("Returning project code for project key {}", projectKey);
- StringBuilder apiEndpoint = new StringBuilder();
- apiEndpoint.append(LATEST_API).append("/").append(PROJECT);
- return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint = LATEST_API + "/" + PROJECT;
+ return getRestClient().given().when().get(apiEndpoint).then().extract().response();
}
- private Response getAvailableIssues(String projectId) {
+ private Response getAvailableIssues(@NonNull final String projectId) {
logger.info("Returning available issues for project {}", projectId);
- StringBuilder apiEndpoint = new StringBuilder();
- apiEndpoint
- .append(ISSUE_PATH)
- .append("/")
- .append(CREATEMETA)
- .append("/")
- .append(projectId)
- .append("/")
- .append(ISSUE_TYPES);
- return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint = ISSUE_PATH + "/" + CREATEMETA + "/" + projectId + "/" + ISSUE_TYPES;
+ return getRestClient().given().when().get(apiEndpoint).then().extract().response();
}
- private Response deleteExistingTicket(String jiraTicketID) {
+ private Response deleteExistingTicket(@NonNull final String jiraTicketID) {
logger.info("Deleting issue {}", jiraTicketID);
- StringBuilder apiEndpoint = new StringBuilder(ISSUE_PATH);
- apiEndpoint.append("/").append(jiraTicketID);
- return getRestClient()
- .given()
- .when()
- .delete(apiEndpoint.toString())
- .then()
- .extract()
- .response();
+ String apiEndpoint = ISSUE_PATH + "/" + jiraTicketID;
+ return getRestClient().given().when().delete(apiEndpoint).then().extract().response();
}
- private Response putLabelToTicket(String jiraTicketID, String labelName) {
- StringBuilder apiEndpoint = new StringBuilder(ISSUE_PATH);
- apiEndpoint.append("/").append(jiraTicketID);
+ private Response putLabelToTicket(@NonNull final String jiraTicketID, final String labelName) {
+ String apiEndpoint = ISSUE_PATH + "/" + jiraTicketID;
return getRestClient()
.given()
.and()
.body(String.format("{\"update\":{\"labels\":[{\"add\":\"%s\"}]}}", labelName))
.when()
- .put(apiEndpoint.toString())
+ .put(apiEndpoint)
.then()
.extract()
.response();
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/jira/SearchAPI.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/jira/SearchAPI.java
index 9d5e0e6..d08c1cb 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/jira/SearchAPI.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/jira/SearchAPI.java
@@ -22,10 +22,11 @@
import static com.applause.auto.helpers.jira.restclient.XrayRestAssuredClient.getRestClient;
import com.applause.auto.helpers.jira.dto.jql.JqlFilteredResults;
+import com.applause.auto.helpers.util.GenericObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.response.Response;
import java.util.Objects;
+import lombok.NonNull;
import org.apache.commons.lang3.Range;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -33,39 +34,45 @@
public class SearchAPI {
private static final Logger logger = LogManager.getLogger(SearchAPI.class);
- private ObjectMapper mapper = new ObjectMapper();
/**
- * @param jqlQuery, represents the JQL query used in Jira
- * @param maxResults, overrides default limited 50 results. Can be set to null for default.
- * @example : "labels IN ("xray_automation") AND issuetype=12106 AND summary~"Test Description""
- * @return JqlFilteredResults object containing number of findings and list of issues
+ * Filters Jira issues based on a provided JQL query.
+ *
+ * @param jqlQuery The JQL query used to filter issues. For example: \"labels IN
+ * (\"xray_automation\") AND issuetype=12106 AND summary~\"Test Description\""
+ * @param maxResults The maximum number of results to return. If null, the Jira default limit
+ * (usually 50) is used.
+ * @return A {@link JqlFilteredResults} object containing the total number of issues found and a
+ * list of the retrieved issues.
+ * @throws JsonProcessingException If an error occurs during JSON processing of the Jira response.
*/
- public JqlFilteredResults filterIssues(String jqlQuery, Integer maxResults)
+ public JqlFilteredResults filterIssues(@NonNull final String jqlQuery, final Integer maxResults)
throws JsonProcessingException {
Response response = getIssuesByJqlFiltering(jqlQuery, maxResults);
- checkResponseInRange(response, Range.between(200, 300), "Get issue by jql filter");
- JqlFilteredResults results = mapper.readValue(response.asString(), JqlFilteredResults.class);
- if (results.getTotal() == 0) {
+ checkResponseInRange(response, Range.of(200, 300), "Get issue by jql filter");
+ JqlFilteredResults results =
+ GenericObjectMapper.getObjectMapper()
+ .readValue(response.asString(), JqlFilteredResults.class);
+ if (results.total() == 0) {
logger.warn("JQL search returned 0 results");
}
return results;
}
- public Response getIssuesByJqlFiltering(String jqlQuery, Integer maxResults) {
+ public Response getIssuesByJqlFiltering(
+ @NonNull final String jqlQuery, final Integer maxResults) {
logger.info("Searching issues by JQL query [ {} ] ", jqlQuery);
StringBuilder apiEndpoint = new StringBuilder();
- apiEndpoint.append(LATEST_API).append("/").append(SEARCH).append("?jql=").append(jqlQuery);
+ apiEndpoint.append(LATEST_API).append('/').append(SEARCH).append("?jql=").append(jqlQuery);
if (Objects.nonNull(maxResults)) {
apiEndpoint.append("&maxResults=").append(maxResults);
}
return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
}
- public Response getIssueResponseObject(String jiraTicketID) {
+ public Response getIssueResponseObject(@NonNull final String jiraTicketID) {
logger.info("Returning issue response for {}", jiraTicketID);
- StringBuilder apiEndpoint = new StringBuilder();
- apiEndpoint.append(ISSUE_PATH).append("/").append(jiraTicketID);
- return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint = ISSUE_PATH + "/" + jiraTicketID;
+ return getRestClient().given().when().get(apiEndpoint).then().extract().response();
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/ExecutionsAPI.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/ExecutionsAPI.java
index 5eaafc5..41798c2 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/ExecutionsAPI.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/ExecutionsAPI.java
@@ -23,90 +23,90 @@
import com.applause.auto.helpers.jira.dto.requestmappers.XrayAddTo;
import com.applause.auto.helpers.jira.dto.responsemappers.JiraCreateTicketResponse;
+import com.applause.auto.helpers.util.GenericObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.response.Response;
+import lombok.NonNull;
import org.apache.commons.lang3.Range;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+@SuppressWarnings("checkstyle:MultipleStringLiterals")
public class ExecutionsAPI {
private static final Logger logger = LogManager.getLogger(ExecutionsAPI.class);
- private ObjectMapper mapper = new ObjectMapper();
/**
- * Adds Test Execution to existing Test Plan, request example: "{"add":["testExecKey"]}",
- * Response: 200 OK, if Test Execution was added successfully
+ * Adds Test Execution to existing Test Plan.
*
- * @param xrayAddToMapping, Test Execution you want to associate to a specific Test Plan
- * @return statusCode
- * @throws JsonProcessingException
+ * Request example: `{"add":["testExecKey"]}`
+ *
+ *
Response: 200 OK, if Test Execution was added successfully
+ *
+ * @param xrayAddToMapping The Test Execution to associate with the specified Test Plan.
+ * @param testPlanKey The key of the Test Plan to which the Test Execution should be added.
+ * @throws JsonProcessingException If an error occurs during JSON processing.
*/
- public void addExecutionToTestPlan(XrayAddTo xrayAddToMapping, String testPlanKey)
+ public void addExecutionToTestPlan(
+ @NonNull final XrayAddTo xrayAddToMapping, @NonNull final String testPlanKey)
throws JsonProcessingException {
Response response = postTestExecutionToTestPlan(xrayAddToMapping, testPlanKey);
- checkResponseInRange(response, Range.between(200, 300), "Add test execution to test plan");
+ checkResponseInRange(response, Range.of(200, 300), "Add test execution to test plan");
}
/**
- * Adds Test to an existing Test Execution, request example: "{"add":["testKey"]}". Response: 200
- * OK, if test was added successfully
+ * Adds Test to an existing Test Execution. Request example: "{"add":["testKey"]}". Response: 200
+ * OK, if test was added successfully.
*
- * @param jiraCreateTicketResponseMapping, to get Test Execution key from
- * @param xrayAddToMapping, Test key/s you want to associate to a specific Test Execution
- * @return statusCode
- * @throws JsonProcessingException
+ * @param jiraCreateTicketResponseMapping The response containing the Test Execution key.
+ * @param xrayAddToMapping The Test key(s) to associate with the Test Execution.
+ * @throws JsonProcessingException If a JSON processing error occurs.
*/
public void addTestToTestExecution(
- JiraCreateTicketResponse jiraCreateTicketResponseMapping, XrayAddTo xrayAddToMapping)
+ @NonNull final JiraCreateTicketResponse jiraCreateTicketResponseMapping,
+ @NonNull final XrayAddTo xrayAddToMapping)
throws JsonProcessingException {
Response response = postTestToTestExecution(jiraCreateTicketResponseMapping, xrayAddToMapping);
- checkResponseInRange(response, Range.between(200, 300), "Add test to test execution");
+ checkResponseInRange(response, Range.of(200, 300), "Add test to test execution");
}
- private Response postTestExecutionToTestPlan(XrayAddTo xrayAddToMapping, String testPlanKey)
+ private Response postTestExecutionToTestPlan(
+ @NonNull final XrayAddTo xrayAddToMapping, @NonNull final String testPlanKey)
throws JsonProcessingException {
logger.info(
"Adding X-Ray Test Execution {} to X-Ray Test Plan {}", xrayAddToMapping, testPlanKey);
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_PLAN)
- .append("/")
- .append(testPlanKey)
- .append("/")
- .append(TEST_EXECUTION);
+
+ String apiEndpoint = XRAY_PATH + TEST_PLAN + "/" + testPlanKey + "/" + TEST_EXECUTION;
+
return getRestClient()
.given()
.and()
- .body(mapper.writeValueAsString(xrayAddToMapping))
+ .body(GenericObjectMapper.getObjectMapper().writeValueAsString(xrayAddToMapping))
.when()
- .post(apiEndpoint.toString())
+ .post(apiEndpoint)
.then()
.extract()
.response();
}
private Response postTestToTestExecution(
- JiraCreateTicketResponse jiraCreateTicketResponseMapping, XrayAddTo xrayAddToMapping)
+ @NonNull final JiraCreateTicketResponse jiraCreateTicketResponseMapping,
+ @NonNull final XrayAddTo xrayAddToMapping)
throws JsonProcessingException {
logger.info(
"Adding X-Ray Test(s) [ {} ] to X-Ray Test Execution [ {} ]",
xrayAddToMapping.toString(),
- jiraCreateTicketResponseMapping.getKey());
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_EXEC)
- .append("/")
- .append(jiraCreateTicketResponseMapping.getKey())
- .append("/")
- .append(TEST);
+ jiraCreateTicketResponseMapping.key());
+
+ String apiEndpoint =
+ XRAY_PATH + TEST_EXEC + "/" + jiraCreateTicketResponseMapping.key() + "/" + TEST;
+
return getRestClient()
.given()
.and()
- .body(mapper.writeValueAsString(xrayAddToMapping))
+ .body(GenericObjectMapper.getObjectMapper().writeValueAsString(xrayAddToMapping))
.when()
- .post(apiEndpoint.toString())
+ .post(apiEndpoint)
.then()
.extract()
.response();
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/IterationsAPI.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/IterationsAPI.java
index 0b61bd1..1133d89 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/IterationsAPI.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/IterationsAPI.java
@@ -22,48 +22,41 @@
import static com.applause.auto.helpers.jira.restclient.XrayRestAssuredClient.getRestClient;
import com.applause.auto.helpers.jira.dto.responsemappers.steps.Step;
+import com.applause.auto.helpers.util.GenericObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.response.Response;
import org.apache.commons.lang3.Range;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+@SuppressWarnings("checkstyle:MultipleStringLiterals")
public class IterationsAPI {
private static final Logger logger = LogManager.getLogger(IterationsAPI.class);
- private ObjectMapper mapper = new ObjectMapper();
/**
- * Get Test Run Iteration Steps information Returned object will contain also each step ID which
- * is needed for further step update request
+ * Get Test Run Iteration Steps information. Returned object will contain also each step ID which
+ * is needed for further step update request.
*
- * @param testRunId
- * @param iterationId
- * @return Step array object
+ * @param testRunId The ID of the test run.
+ * @param iterationId The ID of the iteration.
+ * @return An array of Step objects.
+ * @throws JsonProcessingException If there is an error processing the JSON response.
*/
- public Step[] getTestRunIterationStepsData(int testRunId, int iterationId)
+ public Step[] getTestRunIterationStepsData(final int testRunId, final int iterationId)
throws JsonProcessingException {
Response response = getTestRunIterationSteps(testRunId, iterationId);
- Step[] steps = mapper.readValue(response.asString(), Step[].class);
- checkResponseInRange(response, Range.between(200, 300), "Get Test Run Iteration Steps Data");
+ Step[] steps =
+ GenericObjectMapper.getObjectMapper().readValue(response.asString(), Step[].class);
+ checkResponseInRange(response, Range.of(200, 300), "Get Test Run Iteration Steps Data");
return steps;
}
- private Response getTestRunIterationSteps(int testRunId, int iterationId) {
+ private Response getTestRunIterationSteps(final int testRunId, final int iterationId) {
logger.info(
"Getting X-Ray Test Run {} iteration steps response for ID: {}", testRunId, iterationId);
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_RUN)
- .append("/")
- .append(testRunId)
- .append("/")
- .append(ITERATION)
- .append("/")
- .append(iterationId)
- .append("/")
- .append(STEP);
- return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint =
+ XRAY_PATH + TEST_RUN + "/" + testRunId + "/" + ITERATION + "/" + iterationId + "/" + STEP;
+ return getRestClient().given().when().get(apiEndpoint).then().extract().response();
}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/StepsAPI.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/StepsAPI.java
index d5ed721..509bce3 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/StepsAPI.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/StepsAPI.java
@@ -24,174 +24,165 @@
import com.applause.auto.helpers.jira.dto.requestmappers.StepFieldsUpdate;
import com.applause.auto.helpers.jira.dto.requestmappers.StepIterationAttachment;
+import com.applause.auto.helpers.util.GenericObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.response.Response;
import java.io.IOException;
+import lombok.NonNull;
import org.apache.commons.lang3.Range;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+@SuppressWarnings("checkstyle:MultipleStringLiterals")
public class StepsAPI {
private static final Logger logger = LogManager.getLogger(StepsAPI.class);
- private ObjectMapper mapper = new ObjectMapper();
/**
* Modify Test Run Step by using PUT API This method is used to update: status, comment, actual
* result Should be used when test is NOT parametrised and dataset is NOT present
*
- * @param testRunId
- * @param stepId
+ * @param testRunId the test run ID
+ * @param stepId test step ID
* @param fields - fields which will be updated
*/
- public void updateTestRunStep(int testRunId, int stepId, StepFieldsUpdate fields)
+ public void updateTestRunStep(
+ final int testRunId, final int stepId, @NonNull final StepFieldsUpdate fields)
throws JsonProcessingException {
Response response = putTestRunStep(testRunId, stepId, fields);
- checkResponseInRange(response, Range.between(200, 300), "Update Test Run Step");
+ checkResponseInRange(response, Range.of(200, 300), "Update Test Run Step");
}
/**
* Modify Test Run Iteration Step by using PUT API This method is used to update: status, comment,
* actual result Should be used when test is parametrised and dataset is present
*
- * @param testRunId
- * @param iterationId
- * @param stepId
+ * @param testRunId the test run ID
+ * @param iterationId test run iteration step
+ * @param stepId test step ID
* @param fields - fields which will be updated
*/
public void updateTestRunIterationStep(
- int testRunId, int iterationId, int stepId, StepFieldsUpdate fields)
+ int testRunId, int iterationId, int stepId, @NonNull final StepFieldsUpdate fields)
throws JsonProcessingException {
Response response = putTestRunIterationStep(testRunId, iterationId, stepId, fields);
- checkResponseInRange(response, Range.between(200, 300), "Update Test Run Iteration Step");
+ checkResponseInRange(response, Range.of(200, 300), "Update Test Run Iteration Step");
}
/**
* Upload Test Run Step attachment
*
- * @param testRunId
- * @param stepId
+ * @param testRunId test run ID
+ * @param stepId test step ID
* @param filePath - path to file
*/
- public void uploadTestRunStepAttachment(int testRunId, int stepId, String filePath)
- throws IOException {
+ public void uploadTestRunStepAttachment(
+ final int testRunId, final int stepId, @NonNull final String filePath) throws IOException {
Response response = postTestRunStepAttachment(testRunId, stepId, filePath);
- checkResponseInRange(response, Range.between(200, 300), "Upload Test Run Step attachment");
+ checkResponseInRange(response, Range.of(200, 300), "Upload Test Run Step attachment");
}
/**
* Upload Test Run Iteration Step attachment
*
- * @param testRunId
- * @param iterationId
- * @param stepId
+ * @param testRunId test run ID
+ * @param iterationId test step iteration ID
+ * @param stepId test step ID
* @param filePath - path to file
*/
public void uploadTestRunIterationStepAttachment(
- int testRunId, int iterationId, int stepId, String filePath) throws IOException {
+ final int testRunId, final int iterationId, final int stepId, @NonNull final String filePath)
+ throws IOException {
Response response =
postTestRunIterationStepAttachment(testRunId, iterationId, stepId, filePath);
- checkResponseInRange(
- response, Range.between(200, 300), "Upload Test Run Iteration Step attachment");
+ checkResponseInRange(response, Range.of(200, 300), "Upload Test Run Iteration Step attachment");
}
- private Response postTestRunStepAttachment(int testRunId, int stepId, String filePath)
- throws IOException {
+ private Response postTestRunStepAttachment(
+ final int testRunId, final int stepId, @NonNull final String filePath) throws IOException {
logger.info("Attaching {} to X-Ray Test Run {} step {}", filePath, testRunId, stepId);
- StepIterationAttachment stepIterationAttachment = new StepIterationAttachment();
- stepIterationAttachment.setData(encodeBase64File(filePath));
- stepIterationAttachment.setFilename(getFileNameFromPath(filePath));
- stepIterationAttachment.setContentType(getFileType(filePath));
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_RUN)
- .append("/")
- .append(testRunId)
- .append("/")
- .append(STEP)
- .append("/")
- .append(stepId)
- .append("/")
- .append(ATTACHMENT);
+ StepIterationAttachment stepIterationAttachment =
+ new StepIterationAttachment(
+ encodeBase64File(filePath), getFileNameFromPath(filePath), getFileType(filePath));
+ final var apiEndpoint =
+ XRAY_PATH + TEST_RUN + "/" + testRunId + "/" + STEP + "/" + stepId + "/" + ATTACHMENT;
+
return getRestClient()
.given()
.and()
- .body(mapper.writeValueAsString(stepIterationAttachment))
+ .body(GenericObjectMapper.getObjectMapper().writeValueAsString(stepIterationAttachment))
.when()
- .post(apiEndpoint.toString())
+ .post(apiEndpoint)
.then()
.extract()
.response();
}
private Response postTestRunIterationStepAttachment(
- int testRunId, int iterationId, int stepId, String filePath) throws IOException {
+ final int testRunId, final int iterationId, final int stepId, @NonNull final String filePath)
+ throws IOException {
logger.info(
"Attaching {} to X-Ray Test Run {} iteration {} step {}",
filePath,
testRunId,
iterationId,
stepId);
- StepIterationAttachment stepIterationAttachment = new StepIterationAttachment();
- stepIterationAttachment.setData(encodeBase64File(filePath));
- stepIterationAttachment.setFilename(getFileNameFromPath(filePath));
- stepIterationAttachment.setContentType(getFileType(filePath));
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_RUN)
- .append("/")
- .append(testRunId)
- .append("/")
- .append(ITERATION)
- .append("/")
- .append(iterationId)
- .append("/")
- .append(STEP)
- .append("/")
- .append(stepId)
- .append("/")
- .append(ATTACHMENT);
+ StepIterationAttachment stepIterationAttachment =
+ new StepIterationAttachment(
+ encodeBase64File(filePath), getFileNameFromPath(filePath), getFileType(filePath));
+ String apiEndpoint =
+ XRAY_PATH
+ + TEST_RUN
+ + "/"
+ + testRunId
+ + "/"
+ + ITERATION
+ + "/"
+ + iterationId
+ + "/"
+ + STEP
+ + "/"
+ + stepId
+ + "/"
+ + ATTACHMENT;
+
return getRestClient()
.given()
.and()
- .body(mapper.writeValueAsString(stepIterationAttachment))
+ .body(GenericObjectMapper.getObjectMapper().writeValueAsString(stepIterationAttachment))
.when()
- .post(apiEndpoint.toString())
+ .post(apiEndpoint)
.then()
.extract()
.response();
}
- private Response putTestRunStep(int testRunId, int stepId, StepFieldsUpdate stepFieldsUpdate)
+ private Response putTestRunStep(
+ final int testRunId, final int stepId, @NonNull final StepFieldsUpdate stepFieldsUpdate)
throws JsonProcessingException {
logger.info(
"Updating X-Ray Test Run {} step {} with {}",
testRunId,
stepId,
stepFieldsUpdate.toString());
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_RUN)
- .append("/")
- .append(testRunId)
- .append("/")
- .append(STEP)
- .append("/")
- .append(stepId);
+ String apiEndpoint = XRAY_PATH + TEST_RUN + "/" + testRunId + "/" + STEP + "/" + stepId;
+
return getRestClient()
.given()
.and()
- .body(mapper.writeValueAsString(stepFieldsUpdate))
+ .body(GenericObjectMapper.getObjectMapper().writeValueAsString(stepFieldsUpdate))
.when()
- .put(apiEndpoint.toString())
+ .put(apiEndpoint)
.then()
.extract()
.response();
}
private Response putTestRunIterationStep(
- int testRunId, int iterationId, int stepId, StepFieldsUpdate stepFieldsUpdate)
+ final int testRunId,
+ final int iterationId,
+ final int stepId,
+ @NonNull final StepFieldsUpdate stepFieldsUpdate)
throws JsonProcessingException {
logger.info(
"Updating X-Ray Test Run {} iteration {} step {} with {}",
@@ -199,25 +190,26 @@ private Response putTestRunIterationStep(
iterationId,
stepId,
stepFieldsUpdate.toString());
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_RUN)
- .append("/")
- .append(testRunId)
- .append("/")
- .append(ITERATION)
- .append("/")
- .append(iterationId)
- .append("/")
- .append(STEP)
- .append("/")
- .append(stepId);
+ String apiEndpoint =
+ XRAY_PATH
+ + TEST_RUN
+ + "/"
+ + testRunId
+ + "/"
+ + ITERATION
+ + "/"
+ + iterationId
+ + "/"
+ + STEP
+ + "/"
+ + stepId;
+
return getRestClient()
.given()
.and()
- .body(mapper.writeValueAsString(stepFieldsUpdate))
+ .body(GenericObjectMapper.getObjectMapper().writeValueAsString(stepFieldsUpdate))
.when()
- .put(apiEndpoint.toString())
+ .put(apiEndpoint)
.then()
.extract()
.response();
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/TestrunAPI.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/TestrunAPI.java
index f2fed01..be41c5b 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/TestrunAPI.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/clients/modules/xray/TestrunAPI.java
@@ -26,184 +26,180 @@
import com.applause.auto.helpers.jira.dto.responsemappers.JiraCreateTicketResponse;
import com.applause.auto.helpers.jira.dto.responsemappers.XrayTestRunDetails;
import com.applause.auto.helpers.jira.dto.responsemappers.iteration.TestRunIteration;
+import com.applause.auto.helpers.util.GenericObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.response.Response;
import java.io.IOException;
+import lombok.NonNull;
import org.apache.commons.lang3.Range;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+@SuppressWarnings("checkstyle:MultipleStringLiterals")
public class TestrunAPI {
private static final Logger logger = LogManager.getLogger(TestrunAPI.class);
- private ObjectMapper mapper = new ObjectMapper();
/**
- * Get Test Run ID which can be used in updating Test status in a certain Test Execution
+ * Get Test Run ID which can be used in updating Test status in a certain Test Execution.
*
- * @param jiraCreateTicketResponseMapping, to get value of testExecKey,
- * @param testKey,
- * @return testRunID,
- * @throws JsonProcessingException
+ * @param jiraCreateTicketResponseMapping The Jira create ticket response mapping, used to get the
+ * testExecKey.
+ * @param testKey The test issue key.
+ * @return The testRunID.
+ * @throws JsonProcessingException If the JSON response is invalid.
*/
- public int getTestRunID(JiraCreateTicketResponse jiraCreateTicketResponseMapping, String testKey)
+ public int getTestRunID(
+ @NonNull final JiraCreateTicketResponse jiraCreateTicketResponseMapping,
+ @NonNull final String testKey)
throws JsonProcessingException {
Response response = getTestRunIdOfTestFromExecution(jiraCreateTicketResponseMapping, testKey);
XrayTestRunDetails xrayTestRunDetailsMapping =
- mapper.readValue(response.asString(), XrayTestRunDetails.class);
- checkResponseInRange(response, Range.between(200, 300), "Collecting Test Run ID");
- return xrayTestRunDetailsMapping.getId();
+ GenericObjectMapper.getObjectMapper()
+ .readValue(response.asString(), XrayTestRunDetails.class);
+ checkResponseInRange(response, Range.of(200, 300), "Collecting Test Run ID");
+ return xrayTestRunDetailsMapping.id();
}
/**
- * Updates Test Run status,
+ * Updates Test Run status.
*
- * @param testRunId,
- * @param statusToUpdate: Can be extracted after test execution from ITestResult using its
- * getStatus() and then converted into one of the following values accepted by X-Ray as per
- * project needs:
- *
EXECUTING – Test is being executed; this is a non-final status;
- *
FAIL – Test failed
- *
ABORTED – Test was aborted
- *
PASS – Test passed successfully
+ * @param testRunId the test run ID
+ * @param statusToUpdate the status to update. Can be extracted after test execution from
+ * ITestResult using its getStatus() and then converted into one of the following values
+ * accepted by X-Ray as per project needs:
+ *
+ * - EXECUTING – Test is being executed; this is a non-final status;
+ *
- FAIL – Test failed
+ *
- ABORTED – Test was aborted
+ *
- PASS – Test passed successfully
+ *
+ *
+ * @throws NullPointerException if statusToUpdate is null
*/
- public void updateTestRun(int testRunId, String statusToUpdate) {
+ public void updateTestRun(final int testRunId, @NonNull final String statusToUpdate) {
Response response = putTestRunStatus(testRunId, statusToUpdate);
- checkResponseInRange(response, Range.between(200, 300), "Update test run");
+ checkResponseInRange(response, Range.of(200, 300), "Update test run");
}
/**
* Get Test Run information
*
- * @param testRunId
+ * @param testRunId test run ID
* @return XrayTestRunDetails object
*/
- public XrayTestRunDetails getTestRunData(int testRunId) throws JsonProcessingException {
+ public XrayTestRunDetails getTestRunData(final int testRunId) throws JsonProcessingException {
Response response = getTestRunBasedOnID(testRunId);
XrayTestRunDetails xrayTestRunDetailsMapping =
- mapper.readValue(response.asString(), XrayTestRunDetails.class);
- checkResponseInRange(response, Range.between(200, 300), "Get Test Run Data");
+ GenericObjectMapper.getObjectMapper()
+ .readValue(response.asString(), XrayTestRunDetails.class);
+ checkResponseInRange(response, Range.of(200, 300), "Get Test Run Data");
return xrayTestRunDetailsMapping;
}
/**
* Get Test Run Iteration information
*
- * @param testRunId
- * @param iterationId
+ * @param testRunId test run ID
+ * @param iterationId test run iteration ID
* @return TestRunIteration object
*/
- public TestRunIteration getTestRunIterationData(int testRunId, int iterationId)
+ public TestRunIteration getTestRunIterationData(final int testRunId, final int iterationId)
throws JsonProcessingException {
Response response = getTestRunIterationBasedOnID(testRunId, iterationId);
TestRunIteration testRunIteration =
- mapper.readValue(response.asString(), TestRunIteration.class);
- checkResponseInRange(response, Range.between(200, 300), "Get Test Run Iteration Data");
+ GenericObjectMapper.getObjectMapper()
+ .readValue(response.asString(), TestRunIteration.class);
+ checkResponseInRange(response, Range.of(200, 300), "Get Test Run Iteration Data");
return testRunIteration;
}
/**
* Upload Test Run attachment
*
- * @param testRunId
+ * @param testRunId test run ID
* @param filePath - path to file
*/
- public void uploadTestRunAttachment(int testRunId, String filePath) throws IOException {
+ public void uploadTestRunAttachment(final int testRunId, @NonNull final String filePath)
+ throws IOException {
Response response = postTestRunAttachment(testRunId, filePath);
- checkResponseInRange(response, Range.between(200, 300), "Upload Test Run attachment");
+ checkResponseInRange(response, Range.of(200, 300), "Upload Test Run attachment");
}
/**
* Post comment to Test Run
*
- * @param testRunId
- * @param comment
+ * @param testRunId test run ID
+ * @param comment test run comment
*/
- public void postTestRunComment(int testRunId, String comment) {
+ public void postTestRunComment(final int testRunId, @NonNull final String comment) {
Response response = postComment(testRunId, comment);
- checkResponseInRange(response, Range.between(200, 300), "Posting Test Run comment");
+ checkResponseInRange(response, Range.of(200, 300), "Posting Test Run comment");
}
private Response getTestRunIdOfTestFromExecution(
- JiraCreateTicketResponse jiraCreateTicketResponseMapping, String testKey) {
+ @NonNull final JiraCreateTicketResponse jiraCreateTicketResponseMapping,
+ @NonNull final String testKey) {
logger.info("Getting X-Ray Test Run ID for test: {}", testKey);
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_RUN)
- .append("?")
- .append(testExecIssueKeyParam)
- .append(jiraCreateTicketResponseMapping.getKey())
- .append("&")
- .append(testIssueKeyParam)
- .append(testKey);
- return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint =
+ XRAY_PATH
+ + TEST_RUN
+ + "?"
+ + testExecIssueKeyParam
+ + jiraCreateTicketResponseMapping.key()
+ + "&"
+ + testIssueKeyParam
+ + testKey;
+ return getRestClient().given().when().get(apiEndpoint).then().extract().response();
}
- private Response putTestRunStatus(int testRunId, String statusToUpdate) {
+ private Response putTestRunStatus(final int testRunId, @NonNull final String statusToUpdate) {
logger.info("Updating X-Ray Test Run: {} with status: {}", testRunId, statusToUpdate);
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_RUN + "/")
- .append(testRunId)
- .append("/")
- .append(STATUS)
- .append("?")
- .append(statusParam)
- .append(statusToUpdate);
- return getRestClient().given().when().put(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint =
+ XRAY_PATH + TEST_RUN + "/" + testRunId + "/" + STATUS + "?" + statusParam + statusToUpdate;
+ return getRestClient().given().when().put(apiEndpoint).then().extract().response();
}
- private Response getTestRunBasedOnID(int testRunId) {
+ private Response getTestRunBasedOnID(final int testRunId) {
logger.info("Getting X-Ray Test Run response for ID: {}", testRunId);
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint.append(TEST_RUN).append("/").append(testRunId);
- return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint = XRAY_PATH + TEST_RUN + "/" + testRunId;
+ return getRestClient().given().when().get(apiEndpoint).then().extract().response();
}
- private Response getTestRunIterationBasedOnID(int testRunId, int iterationId) {
+ private Response getTestRunIterationBasedOnID(final int testRunId, final int iterationId) {
logger.info("Getting X-Ray Test Run {} iteration response for ID: {}", testRunId, iterationId);
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint
- .append(TEST_RUN)
- .append("/")
- .append(testRunId)
- .append("/")
- .append(ITERATION)
- .append("/")
- .append(iterationId);
- return getRestClient().given().when().get(apiEndpoint.toString()).then().extract().response();
+ String apiEndpoint =
+ XRAY_PATH + TEST_RUN + "/" + testRunId + "/" + ITERATION + "/" + iterationId;
+ return getRestClient().given().when().get(apiEndpoint).then().extract().response();
}
- private Response postTestRunAttachment(int testRunId, String filePath) throws IOException {
+ private Response postTestRunAttachment(final int testRunId, @NonNull final String filePath)
+ throws IOException {
logger.info("Attaching {} to X-Ray Test Run {}", filePath, testRunId);
- StepIterationAttachment stepIterationAttachment = new StepIterationAttachment();
- stepIterationAttachment.setData(encodeBase64File(filePath));
- stepIterationAttachment.setFilename(getFileNameFromPath(filePath));
- stepIterationAttachment.setContentType(getFileType(filePath));
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint.append(TEST_RUN).append("/").append(testRunId).append("/").append(ATTACHMENT);
+ StepIterationAttachment stepIterationAttachment =
+ new StepIterationAttachment(
+ encodeBase64File(filePath), getFileNameFromPath(filePath), getFileType(filePath));
+ String apiEndpoint = XRAY_PATH + TEST_RUN + "/" + testRunId + "/" + ATTACHMENT;
return getRestClient()
.given()
.and()
- .body(mapper.writeValueAsString(stepIterationAttachment))
+ .body(GenericObjectMapper.getObjectMapper().writeValueAsString(stepIterationAttachment))
.when()
- .post(apiEndpoint.toString())
+ .post(apiEndpoint)
.then()
.extract()
.response();
}
- private Response postComment(int testRunId, String comment) {
+ private Response postComment(final int testRunId, @NonNull final String comment) {
logger.info("Posting comment [{}] to X-Ray Test Run {}", comment, testRunId);
- StringBuilder apiEndpoint = new StringBuilder(XRAY_PATH);
- apiEndpoint.append(TEST_RUN).append("/").append(testRunId).append("/").append(COMMENT);
+ String apiEndpoint = XRAY_PATH + TEST_RUN + "/" + testRunId + "/" + COMMENT;
return getRestClient()
.given()
.and()
.body(comment)
.when()
- .put(apiEndpoint.toString())
+ .put(apiEndpoint)
.then()
.extract()
.response();
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/constants/Statuses.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/constants/Statuses.java
index e951409..3351858 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/constants/Statuses.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/constants/Statuses.java
@@ -28,5 +28,5 @@ public enum Statuses {
BLOCKED("BLOCKED"),
TODO("TODO");
- @Getter private String value;
+ @Getter private final String value;
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/constants/XrayEndpoints.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/constants/XrayEndpoints.java
index 842b999..c59c4c5 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/constants/XrayEndpoints.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/constants/XrayEndpoints.java
@@ -17,8 +17,8 @@
*/
package com.applause.auto.helpers.jira.constants;
-public class XrayEndpoints {
-
+@SuppressWarnings("PMD.DataClass")
+public final class XrayEndpoints {
public static final String LATEST_API = "/api/latest";
public static final String XRAY_PATH = "/raven/latest/api/";
@@ -46,4 +46,8 @@ public class XrayEndpoints {
public static final String testIssueKeyParam = "testIssueKey=";
public static final String statusParam = "status=";
+
+ private XrayEndpoints() {
+ // utility class
+ }
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/Fields.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/Fields.java
index c1f3ef8..eb6a7ac 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/Fields.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/Fields.java
@@ -19,14 +19,7 @@
import com.applause.auto.helpers.jira.dto.shared.Issuetype;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import lombok.Data;
-@Data
@JsonIgnoreProperties(ignoreUnknown = true)
-public class Fields {
- private String summary;
- private String[] labels;
- private String created;
- private Issuetype issuetype;
- private String environment;
-}
+public record Fields(
+ String summary, String labels, String created, Issuetype issuetype, String environment) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/Issues.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/Issues.java
index 7e1079f..f383430 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/Issues.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/Issues.java
@@ -18,14 +18,6 @@
package com.applause.auto.helpers.jira.dto.jql;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import lombok.Data;
-import lombok.Getter;
-@Data
-@Getter
@JsonIgnoreProperties(ignoreUnknown = true)
-public class Issues {
- public String id;
- public String key;
- public Fields fields;
-}
+public record Issues(String id, String key, Fields fields) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/JqlFilteredResults.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/JqlFilteredResults.java
index 0d52985..06c4d5a 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/JqlFilteredResults.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/jql/JqlFilteredResults.java
@@ -19,14 +19,6 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.List;
-import lombok.Data;
-import lombok.Getter;
-@Data
-@Getter
@JsonIgnoreProperties(ignoreUnknown = true)
-public class JqlFilteredResults {
- private int maxResults;
- private int total;
- private List issues;
-}
+public record JqlFilteredResults(int maxResults, int total, List issues) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/Fields.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/Fields.java
index b084727..9caaeac 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/Fields.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/Fields.java
@@ -19,15 +19,5 @@
import com.applause.auto.helpers.jira.dto.shared.Issuetype;
import com.applause.auto.helpers.jira.dto.shared.Project;
-import lombok.Data;
-@Data
-public class Fields {
- // summary represents ticket's title.
- private String summary;
- // issueTypeId is different per project, and unique per ticket type (defect, task, test plan etc).
- // Example: Test Plan: 12106, Xray Test: 10402.
- private Issuetype issuetype;
- // Project id is the identifier of the project.
- private Project project;
-}
+public record Fields(String summary, Issuetype issuetype, Project project) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/JiraCreateTicketRequest.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/JiraCreateTicketRequest.java
index c97d6c8..f658e58 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/JiraCreateTicketRequest.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/JiraCreateTicketRequest.java
@@ -17,9 +17,4 @@
*/
package com.applause.auto.helpers.jira.dto.requestmappers;
-import lombok.Data;
-
-@Data
-public class JiraCreateTicketRequest {
- private Fields fields;
-}
+public record JiraCreateTicketRequest(Fields fields) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/JiraFields.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/JiraFields.java
index f543a0c..1c529a0 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/JiraFields.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/JiraFields.java
@@ -22,23 +22,15 @@
public class JiraFields {
- private Fields fields = null;
+ private final Fields fields;
- public JiraFields(String issueType, String projectId, String summary) {
- fields = new Fields();
-
- Issuetype issuetype = new Issuetype();
- issuetype.setId(issueType);
- fields.setIssuetype(issuetype);
-
- Project project = new Project();
- project.setId(projectId);
- fields.setProject(project);
-
- fields.setSummary(summary);
+ public JiraFields(final String issueType, final String projectId, final String summary) {
+ fields = new Fields(new Issuetype(issueType, null), new Project(projectId), summary);
}
public Fields getFields() {
return fields;
}
+
+ public record Fields(Issuetype issuetype, Project project, String summary) {}
}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/StepFieldsUpdate.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/StepFieldsUpdate.java
index e5d2b02..80bd2bf 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/StepFieldsUpdate.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/StepFieldsUpdate.java
@@ -17,11 +17,4 @@
*/
package com.applause.auto.helpers.jira.dto.requestmappers;
-import lombok.Data;
-
-@Data
-public class StepFieldsUpdate {
- private String status;
- private String comment;
- private String actualResult;
-}
+public record StepFieldsUpdate(String status, String comment, String actualResult) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/StepIterationAttachment.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/StepIterationAttachment.java
index 4aa9085..32d106a 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/StepIterationAttachment.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/StepIterationAttachment.java
@@ -17,11 +17,4 @@
*/
package com.applause.auto.helpers.jira.dto.requestmappers;
-import lombok.Data;
-
-@Data
-public class StepIterationAttachment {
- private String data;
- private String filename;
- private String contentType;
-}
+public record StepIterationAttachment(String data, String filename, String contentType) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/XrayAddTo.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/XrayAddTo.java
index d0346a1..2384d72 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/XrayAddTo.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/requestmappers/XrayAddTo.java
@@ -18,9 +18,5 @@
package com.applause.auto.helpers.jira.dto.requestmappers;
import java.util.List;
-import lombok.Data;
-@Data
-public class XrayAddTo {
- private List add;
-}
+public record XrayAddTo(List add) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/AvailableIssueTypes.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/AvailableIssueTypes.java
index 1eb7380..42e2b77 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/AvailableIssueTypes.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/AvailableIssueTypes.java
@@ -20,10 +20,11 @@
import com.applause.auto.helpers.jira.dto.shared.Issuetype;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.List;
-import lombok.Data;
-@Data
+/**
+ * Represents a list of available issue types.
+ *
+ * @param values The list of {@link Issuetype} objects.
+ */
@JsonIgnoreProperties(ignoreUnknown = true)
-public class AvailableIssueTypes {
- private List values;
-}
+public record AvailableIssueTypes(List values) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/AvailableProjects.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/AvailableProjects.java
index f1fa8f2..c1ee0ee 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/AvailableProjects.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/AvailableProjects.java
@@ -18,13 +18,14 @@
package com.applause.auto.helpers.jira.dto.responsemappers;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import lombok.Data;
-@Data
+/**
+ * A record representing the available projects in Jira.
+ *
+ * @param self The URL of the project.
+ * @param id The ID of the project.
+ * @param key The key of the project.
+ * @param name The name of the project.
+ */
@JsonIgnoreProperties(ignoreUnknown = true)
-public class AvailableProjects {
- private String self;
- private String id;
- private String key;
- private String name;
-}
+public record AvailableProjects(String self, String id, String key, String name) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/JiraCreateTicketResponse.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/JiraCreateTicketResponse.java
index 2e5e1e0..5e24173 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/JiraCreateTicketResponse.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/JiraCreateTicketResponse.java
@@ -17,11 +17,4 @@
*/
package com.applause.auto.helpers.jira.dto.responsemappers;
-import lombok.Data;
-
-@Data
-public class JiraCreateTicketResponse {
- private String id;
- private String key;
- private String self;
-}
+public record JiraCreateTicketResponse(String id, String key, String self) {}
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/XrayTestRunDetails.java b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/XrayTestRunDetails.java
index f14e96d..b4f7e50 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/XrayTestRunDetails.java
+++ b/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/dto/responsemappers/XrayTestRunDetails.java
@@ -20,28 +20,24 @@
import com.applause.auto.helpers.jira.dto.responsemappers.iteration.Iteration;
import com.applause.auto.helpers.jira.dto.responsemappers.steps.Step;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import java.util.ArrayList;
import java.util.List;
-import lombok.Data;
-@Data
@JsonIgnoreProperties(ignoreUnknown = true)
-public class XrayTestRunDetails {
- private int id;
- private String status;
- private String color;
- private String testKey;
- private String testExecKey;
- private String executedBy;
- private String startedOn;
- private String finishedOn;
- private String startedOnIso;
- private String finishedOnIso;
- private int duration;
- private List iterations;
- private List
diff --git a/auto-sdk-java-testng/src/main/java/com/applause/auto/testng/TestNgContextUtils.java b/auto-sdk-java-testng/src/main/java/com/applause/auto/testng/TestNgContextUtils.java
index 9ac0175..77601d9 100644
--- a/auto-sdk-java-testng/src/main/java/com/applause/auto/testng/TestNgContextUtils.java
+++ b/auto-sdk-java-testng/src/main/java/com/applause/auto/testng/TestNgContextUtils.java
@@ -80,7 +80,7 @@ public static ContextType getContextType(final @NonNull ITestResult testResult)
* @param testResult The TestNG result
* @return A Tuple containing the Class and Method used for the result.
*/
- private static Pair, Method> getUnderlyingClassAndMethod(
+ public static Pair, Method> getUnderlyingClassAndMethod(
final @NonNull ITestResult testResult) {
final ITestNGMethod testMethod = testResult.getMethod();
final String methodName = testMethod.getMethodName();
diff --git a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/listeners/XrayListener.java b/auto-sdk-java-testng/src/main/java/com/applause/auto/testng/listeners/XrayListener.java
similarity index 68%
rename from auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/listeners/XrayListener.java
rename to auto-sdk-java-testng/src/main/java/com/applause/auto/testng/listeners/XrayListener.java
index a249abd..7fcff3f 100644
--- a/auto-sdk-java-helpers/src/main/java/com/applause/auto/helpers/jira/listeners/XrayListener.java
+++ b/auto-sdk-java-testng/src/main/java/com/applause/auto/testng/listeners/XrayListener.java
@@ -15,7 +15,7 @@
* limitations under the License.
*
*/
-package com.applause.auto.helpers.jira.listeners;
+package com.applause.auto.testng.listeners;
import com.applause.auto.helpers.jira.annotations.scanner.JiraAnnotationsScanner;
import com.applause.auto.helpers.jira.clients.JiraXrayClient;
@@ -23,8 +23,12 @@
import com.applause.auto.helpers.jira.dto.responsemappers.JiraCreateTicketResponse;
import com.applause.auto.helpers.jira.exceptions.JiraAnnotationException;
import com.applause.auto.helpers.jira.exceptions.UnidentifiedExecutionStatusException;
+import com.applause.auto.testng.TestNgContextUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
-import java.util.Arrays;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import lombok.NonNull;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.testng.ITestContext;
@@ -34,24 +38,24 @@
public class XrayListener extends TestListenerAdapter {
private static final Logger logger = LogManager.getLogger(XrayListener.class);
- private JiraXrayClient jiraXrayClient = new JiraXrayClient();
+ private final JiraXrayClient jiraXrayClient = new JiraXrayClient();
@Override
- public void onTestFailure(ITestResult result) {
+ public void onTestFailure(@NonNull final ITestResult result) {
logger.info("Setting status for FAILED test: [{}]", result.getTestName());
super.onTestFailure(result);
updateJiraXray(result);
}
@Override
- public void onTestSuccess(ITestResult result) {
+ public void onTestSuccess(@NonNull final ITestResult result) {
logger.info("Setting status for PASSED test: [{}]", result.getTestName());
super.onTestSuccess(result);
updateJiraXray(result);
}
@Override
- public void onTestSkipped(ITestResult result) {
+ public void onTestSkipped(@NonNull final ITestResult result) {
logger.info("Setting status for SKIPPED test: [{}]", result.getTestName());
super.onTestSkipped(result);
updateJiraXray(result);
@@ -60,37 +64,38 @@ public void onTestSkipped(ITestResult result) {
/**
* Updates Jira X-Ray with execution results
*
- * @param result
+ * @param result test result
*/
- private void updateJiraXray(ITestResult result) {
+ private void updateJiraXray(@NonNull final ITestResult result) {
try {
int testRunId = addTestToTestExecution(result);
jiraXrayClient.getTestrunAPI().updateTestRun(testRunId, getExecutionStatus(result));
} catch (JsonProcessingException | JiraAnnotationException e) {
- logger.error("Failed to add Test to Test Execution and update its execution status.");
- e.printStackTrace();
+ logger.error("Failed to add Test to Test Execution and update its execution status.", e);
}
}
/**
* Adds test to X-Ray Test Execution based on data passed as @JiraID annotation
*
- * @param result
+ * @param result test result
* @return testRunId, String value that represents identifier of the test case executed under a
* Test Execution
- * @throws JsonProcessingException
+ * @throws JsonProcessingException when response JSON is invalid
*/
- private int addTestToTestExecution(ITestResult result)
+ private int addTestToTestExecution(@NonNull final ITestResult result)
throws JsonProcessingException, JiraAnnotationException {
- JiraCreateTicketResponse jiraCreateTicketResponseMapping = new JiraCreateTicketResponse();
ITestContext context = result.getTestContext();
- String jiraTestIdentifier = JiraAnnotationsScanner.getJiraIdentifier(result);
+ final Pair, Method> classAndMethod =
+ TestNgContextUtils.getUnderlyingClassAndMethod(result);
+ final Method underlyingMethod = classAndMethod.getRight();
+ String jiraTestIdentifier = JiraAnnotationsScanner.getJiraIdentifier(underlyingMethod);
// Assuming testExecKey refers to Test Execution key (ticket ID) the current test is using which
// must be created before execution of the test
String testExecutionKey = context.getAttribute("testExecKey").toString();
- jiraCreateTicketResponseMapping.setKey(testExecutionKey);
- XrayAddTo xrayAddToMapping = new XrayAddTo();
- xrayAddToMapping.setAdd(Arrays.asList(jiraTestIdentifier));
+ JiraCreateTicketResponse jiraCreateTicketResponseMapping =
+ new JiraCreateTicketResponse(null, testExecutionKey, null);
+ XrayAddTo xrayAddToMapping = new XrayAddTo(Collections.singletonList(jiraTestIdentifier));
jiraXrayClient
.getExecutionsAPI()
.addTestToTestExecution(jiraCreateTicketResponseMapping, xrayAddToMapping);
@@ -102,28 +107,23 @@ private int addTestToTestExecution(ITestResult result)
/**
* Gets test execution status based on the ITestResult and maps it to accepted X-Ray values
*
- * @param result
+ * @param result test result
* @return status
*/
- private String getExecutionStatus(ITestResult result) {
+ private String getExecutionStatus(@NonNull final ITestResult result) {
String testKey = result.getMethod().getMethodName();
String status = "";
logger.info("Getting execution status for test key: {}", testKey);
int statusCode = result.getStatus();
- switch (statusCode) {
- case 1:
- status = "PASS";
- break;
- case 2:
- status = "FAIL";
- break;
- case 3:
- status = "BLOCKED";
- break;
- default:
- throw new UnidentifiedExecutionStatusException(
- String.format("Unable to determine status for code %s", statusCode));
- }
+ status =
+ switch (statusCode) {
+ case 1 -> "PASS";
+ case 2 -> "FAIL";
+ case 3 -> "BLOCKED";
+ default ->
+ throw new UnidentifiedExecutionStatusException(
+ String.format("Unable to determine status for code %s", statusCode));
+ };
return status;
}
}
diff --git a/build-tools/checkstyle.xml b/build-tools/checkstyle.xml
index 5e2379b..7376f0d 100644
--- a/build-tools/checkstyle.xml
+++ b/build-tools/checkstyle.xml
@@ -155,10 +155,6 @@
-
-
-
-
@@ -189,7 +185,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 7a515f9..4d82e7a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,7 +65,8 @@
3.3.2
1.0.12
1.18.34
- 2.1.2
+ 2.1.3
+ 2.0.3
2.3.31
6.0.0
4.4
@@ -80,8 +81,6 @@
0.0.12
2.7.2
v4-rev612-1.25.0
- 2.1.3
-
5.13.0
5.2.0
@@ -240,9 +239,14 @@
${javax.ws.rs-api.version}
- com.sun.mail
- jakarta.mail
- 2.0.1
+ jakarta.mail
+ jakarta.mail-api
+ ${jakarta.mail-api.version}
+
+
+ org.eclipse.angus
+ angus-mail
+ ${jakarta.angus.mail.version}
com.github.spotbugs
@@ -310,11 +314,6 @@
google-api-services-sheets
${google-api-services-sheets.version}
-
- jakarta.mail
- jakarta.mail-api
- ${jakarta.mail-api.version}
-