From 9dd51eeedacdf4043c9dc0d257ea801afde05c0a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Sep 2025 07:44:32 +0000 Subject: [PATCH 1/3] Initial plan From ae4b40717cb2f003d629cb4815de3302c59dc25f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Sep 2025 07:53:03 +0000 Subject: [PATCH 2/3] Code quality improvements: Fix typos, improve constants naming, add JavaDoc, refactor utilities Co-authored-by: cmccarthyIrl <32817808+cmccarthyIrl@users.noreply.github.com> --- README.md | 14 +- .../common/utils/ApplicationProperties.java | 36 +- .../com/cmccarthy/common/utils/Constants.java | 31 +- .../cmccarthy/common/utils/DateTimeUtil.java | 158 +++++++-- .../com/cmccarthy/common/utils/HookUtil.java | 59 +++- .../cmccarthy/common/utils/StringUtil.java | 322 ++++++++++++------ .../com/cmccarthy/ui/utils/DriverManager.java | 4 +- .../com/cmccarthy/ui/utils/DriverWait.java | 2 +- .../ClickabilityOfElement.java | 2 +- .../ClickabilityOfElementByLocator.java | 2 +- 10 files changed, 439 insertions(+), 191 deletions(-) diff --git a/README.md b/README.md index 6a8851f..4536cd5 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Spring ``: ```xml - + ... org.springframework.amqp @@ -65,14 +65,14 @@ Spring ``: spring-test ... - + ``` Cucumber & Rest Assured ``: ```xml - + ... io.rest-assured @@ -95,14 +95,14 @@ Cucumber & Rest Assured ``: ${cucumber.version} ... - + ``` Selenium ``: ```xml - + ... org.seleniumhq.selenium @@ -115,7 +115,7 @@ Selenium ``: ${selenium-version} ... - + ``` # Quickstart @@ -126,7 +126,7 @@ Selenium ``: # TestNG -By using the [TestNG Framework](https://junit.org/junit4/) we can utilize the [Cucumber Framework](https://cucumber.io/) +By using the [TestNG Framework](https://testng.org/) we can utilize the [Cucumber Framework](https://cucumber.io/) and the `@CucumberOptions` Annotation Type to execute the `*.feature` file tests > Right click the `WikipediParallelRunner` class and select `Run` diff --git a/common/src/main/java/com/cmccarthy/common/utils/ApplicationProperties.java b/common/src/main/java/com/cmccarthy/common/utils/ApplicationProperties.java index d93bbad..a0f1875 100644 --- a/common/src/main/java/com/cmccarthy/common/utils/ApplicationProperties.java +++ b/common/src/main/java/com/cmccarthy/common/utils/ApplicationProperties.java @@ -1,32 +1,42 @@ package com.cmccarthy.common.utils; import lombok.Getter; +import lombok.Setter; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +/** + * Configuration properties class that holds application-specific settings + * loaded from application properties files. + */ @Getter @Component public class ApplicationProperties { + /** + * The URL for the weather application API. + */ @Value("${weather.url.value}") + @Setter private String weatherAppUrl; + + /** + * The URL for the Wikipedia website. + */ @Value("${wikipedia.url.value}") + @Setter private String wikipediaUrl; + + /** + * The browser type to use for UI tests (e.g., chrome, firefox, edge). + */ @Value("${browser}") + @Setter private String browser; + + /** + * The URL for the Selenium Grid when running tests remotely. + */ @Value("${gridUrl}") private String gridUrl; - - public void setWeatherAppUrl(String weatherAppUrl) { - this.weatherAppUrl = weatherAppUrl; - } - - public void setWikipediaUrl(String wikipediaUrl) { - this.wikipediaUrl = wikipediaUrl; - } - - public void setBrowser(String browser) { - this.browser = browser; - } - } \ No newline at end of file diff --git a/common/src/main/java/com/cmccarthy/common/utils/Constants.java b/common/src/main/java/com/cmccarthy/common/utils/Constants.java index d0df20f..237a7f2 100644 --- a/common/src/main/java/com/cmccarthy/common/utils/Constants.java +++ b/common/src/main/java/com/cmccarthy/common/utils/Constants.java @@ -1,13 +1,34 @@ package com.cmccarthy.common.utils; -public class Constants { +/** + * Constants class containing timeout and polling values used throughout the test framework. + */ +public final class Constants { - public static final long timeoutLong = 30; + /** + * Long timeout duration in seconds for extended wait operations. + */ + public static final long TIMEOUT_LONG = 30; - public static final long pollingLong = 200; + /** + * Long polling interval in milliseconds for extended wait operations. + */ + public static final long POLLING_LONG = 200; - public static final long timeoutShort = 10; + /** + * Short timeout duration in seconds for quick wait operations. + */ + public static final long TIMEOUT_SHORT = 10; - public static final long pollingShort = 100; + /** + * Short polling interval in milliseconds for quick wait operations. + */ + public static final long POLLING_SHORT = 100; + /** + * Private constructor to prevent instantiation of this utility class. + */ + private Constants() { + throw new AssertionError("Constants class should not be instantiated"); + } } diff --git a/common/src/main/java/com/cmccarthy/common/utils/DateTimeUtil.java b/common/src/main/java/com/cmccarthy/common/utils/DateTimeUtil.java index 4fa61a7..c77f9f9 100644 --- a/common/src/main/java/com/cmccarthy/common/utils/DateTimeUtil.java +++ b/common/src/main/java/com/cmccarthy/common/utils/DateTimeUtil.java @@ -5,8 +5,13 @@ import static java.time.OffsetDateTime.now; +/** + * Utility class for date and time operations used in test scenarios. + * Provides various methods for date manipulation, formatting, and generation + * of test-specific dates. + */ @SuppressWarnings("unused") -public class DateTimeUtil { +public final class DateTimeUtil { private static final DateTimeFormatter ISO_DATE_TIME_FORMAT = DateTimeFormatter .ofPattern("dd/MM/yyyy HH:mm:ss"); @@ -17,101 +22,186 @@ public class DateTimeUtil { private static final DateTimeFormatter ISO_DATE_FORMAT_LONG_NO_TIME = DateTimeFormatter .ofPattern("d MMM yyyy"); - private static final DateTimeFormatter ISO_DATE_FORMAT_LONG_MILI = DateTimeFormatter + private static final DateTimeFormatter ISO_DATE_FORMAT_LONG_MILLISECONDS = DateTimeFormatter .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); private static final DateTimeFormatter ISO_DATE_FORMAT_SHORT_NO_TIME = DateTimeFormatter .ofPattern("yyyy-MM-dd"); + /** + * Private constructor to prevent instantiation of this utility class. + */ + private DateTimeUtil() { + throw new AssertionError("DateTimeUtil class should not be instantiated"); + } + + /** + * Gets a fixed effective date for testing purposes. + * + * @return OffsetDateTime representing January 1, 2018 + */ public static OffsetDateTime getEffectiveDate() { return getOffsetDateTime(2018, 1, 1); } + /** + * Gets a far future expiration date for testing purposes. + * + * @return OffsetDateTime representing January 1, 3000 + */ public static OffsetDateTime getExpirationDate() { return getOffsetDateTime(3000, 1, 1); } + /** + * Gets the current Unix timestamp as a string. + * + * @return current Unix timestamp in seconds + */ public static String getNowUnixTimestampDate() { return String.valueOf(System.currentTimeMillis() / 1000L); } + /** + * Creates an OffsetDateTime for the specified date at midnight UTC. + * + * @param year the year + * @param month the month (1-12) + * @param dayOfMonth the day of month (1-31) + * @return OffsetDateTime at midnight UTC + */ public static OffsetDateTime getOffsetDateTime(int year, int month, int dayOfMonth) { return OffsetDateTime .of(LocalDate.of(year, month, dayOfMonth), LocalTime.of(0, 0), ZoneOffset.UTC); } + /** + * Gets the current local date as a formatted string. + * + * @return current date in dd/MM/yyyy format + */ public static String localDateNow() { return OffsetDateTime.of(now().toLocalDateTime(), ZoneOffset.UTC) .format(ISO_DATE_FORMAT_NO_TIME); } + /** + * Gets today's date as an OffsetDateTime. + * + * @return today's date in UTC + */ public static OffsetDateTime getDateToday() { return OffsetDateTime.of(now().toLocalDateTime(), ZoneOffset.UTC); } + /** + * Converts a date string to long date format. + * + * @param dateString date in dd/MM/yyyy format + * @return date in long format (e.g., "1 Jan 2023") + */ public static String getLongDateStringFromDateString(String dateString) { LocalDate date = LocalDate.parse(dateString, ISO_DATE_FORMAT_NO_TIME); return ISO_DATE_FORMAT_LONG_NO_TIME.format(date); } + /** + * Converts a date string to short ISO format. + * + * @param dateString date in dd/MM/yyyy format + * @return date in yyyy-MM-dd format + */ public static String getShortDateStringFromDateString(String dateString) { LocalDate date = LocalDate.parse(dateString, ISO_DATE_FORMAT_NO_TIME); return ISO_DATE_FORMAT_SHORT_NO_TIME.format(date); } - public static String getLongDateMiliString() { - return ISO_DATE_FORMAT_LONG_MILI.format(getDateToday()); + /** + * Gets the current date with milliseconds in ISO format. + * + * @return current date in yyyy-MM-dd'T'HH:mm:ss.SSS'Z' format + */ + public static String getLongDateMillisecondsString() { + return ISO_DATE_FORMAT_LONG_MILLISECONDS.format(getDateToday()); } + /** + * Gets the current local date and time in UTC. + * + * @return current date and time as OffsetDateTime + */ public static OffsetDateTime localDateTimeNow() { return OffsetDateTime.of(now().toLocalDateTime(), ZoneOffset.UTC); } /** - * @return - get month date as 01-2020 String + * Gets the current month and year as a formatted string. + * + * @return current month and year in MM/yyyy format */ public static String getMonthYearNumericalString() { - return now().toString().split("-")[1] + "/" + now().getYear(); + return String.format("%02d/%d", now().getMonthValue(), now().getYear()); } /** - * @return next week day as dd/MM/yyyy + * Gets the next weekday (Monday-Friday) in numerical format. + * + * @return next weekday in dd/MM/yyyy format */ public static String getNextDayOfWeekNumericalFormat() { LocalDateTime date = LocalDateTime.now(); do { date = date.plusDays(1); - } while (date.getDayOfWeek().getValue() >= 5); + } while (date.getDayOfWeek().getValue() > 5); // 6=Saturday, 7=Sunday return date.format(ISO_DATE_FORMAT_NO_TIME); } + /** + * Manages feature date generation based on table input. + * Expected format: "Day +/-", "Month +/-", "Year +/-" followed by number + * Examples: "Day + 5", "Month - 2", "Year + 1" + * + * @param tableDate the table date specification + * @return formatted date string or null if input is null + * @throws IllegalArgumentException if the input format is invalid + */ public static String featureDateManager(String tableDate) { - if (tableDate != null) { - - final String[] dateTableData = tableDate.split("\\s+"); - String switchType; - int dateValue = 0; - - if (dateTableData.length > 1) { - switchType = dateTableData[0] + " " + dateTableData[1]; - dateValue = Integer.parseInt(dateTableData[2]); - } else { - switchType = "Day"; - } - - final LocalDateTime date = LocalDateTime.now(); - - return switch (switchType) { - case "Day +" -> date.plusDays(dateValue).format(ISO_DATE_FORMAT_NO_TIME); - case "Day -" -> date.minusDays(dateValue).format(ISO_DATE_FORMAT_NO_TIME); - case "Month +" -> date.plusMonths(dateValue).format(ISO_DATE_FORMAT_NO_TIME); - case "Month -" -> date.minusMonths(dateValue).format(ISO_DATE_FORMAT_NO_TIME); - case "Year +" -> date.plusYears(dateValue).format(ISO_DATE_FORMAT_NO_TIME); - case "Year -" -> date.minusYears(dateValue).format(ISO_DATE_FORMAT_NO_TIME); - default -> date.format(ISO_DATE_FORMAT_NO_TIME); - }; + if (tableDate == null) { + return null; } - return null; - } + final String[] dateTableData = tableDate.trim().split("\\s+"); + final LocalDateTime date = LocalDateTime.now(); + + if (dateTableData.length == 1 && "Day".equals(dateTableData[0])) { + return date.format(ISO_DATE_FORMAT_NO_TIME); + } + + if (dateTableData.length < 3) { + throw new IllegalArgumentException("Invalid date format. Expected: 'Unit +/- Value' (e.g., 'Day + 5')"); + } + + final String unit = dateTableData[0]; + final String operation = dateTableData[1]; + final int dateValue; + + try { + dateValue = Integer.parseInt(dateTableData[2]); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid numeric value: " + dateTableData[2]); + } + + final String switchType = unit + " " + operation; + + return switch (switchType) { + case "Day +" -> date.plusDays(dateValue).format(ISO_DATE_FORMAT_NO_TIME); + case "Day -" -> date.minusDays(dateValue).format(ISO_DATE_FORMAT_NO_TIME); + case "Month +" -> date.plusMonths(dateValue).format(ISO_DATE_FORMAT_NO_TIME); + case "Month -" -> date.minusMonths(dateValue).format(ISO_DATE_FORMAT_NO_TIME); + case "Year +" -> date.plusYears(dateValue).format(ISO_DATE_FORMAT_NO_TIME); + case "Year -" -> date.minusYears(dateValue).format(ISO_DATE_FORMAT_NO_TIME); + default -> throw new IllegalArgumentException("Unsupported date operation: " + switchType + + ". Supported: Day +/-, Month +/-, Year +/-"); + }; + } } diff --git a/common/src/main/java/com/cmccarthy/common/utils/HookUtil.java b/common/src/main/java/com/cmccarthy/common/utils/HookUtil.java index ce4fb47..f539187 100644 --- a/common/src/main/java/com/cmccarthy/common/utils/HookUtil.java +++ b/common/src/main/java/com/cmccarthy/common/utils/HookUtil.java @@ -6,29 +6,60 @@ import java.nio.charset.StandardCharsets; +/** + * Utility service for handling test hooks and post-test cleanup operations. + * This service manages test scenario lifecycle events and logging. + */ @Service public class HookUtil { + private static final String LOG_SEPARATOR = "=========================================================================="; + private static final String TEST_STATUS_PREFIX = "================================Test "; + private static final String TEST_STATUS_SUFFIX = "==============================="; + @Autowired - LogManager logManager; + private LogManager logManager; + /** + * Handles end-of-test operations including screenshot attachment for failed scenarios + * and logging of test results. + * + * @param scenario the completed test scenario + */ public void endOfTest(Scenario scenario) { - - if (scenario.getStatus() != null) { - if (scenario.isFailed()) { - String filename = scenario.getName().replaceAll("\\s+", "_"); - final String featureError = scenario.getId().replaceAll("\\s+", "_").replaceAll(":", "_").split("\\.")[1]; - filename = filename + "_" + featureError; - scenario.attach(filename.getBytes(StandardCharsets.UTF_8), "image/png", filename); - } + if (scenario.getStatus() != null && scenario.isFailed()) { + attachScreenshotForFailedScenario(scenario); } - logManager.info(""); - logManager.info("=========================================================================="); - logManager.info("================================Test " + scenario.getStatus().toString() + "==============================="); - logManager.info("=========================================================================="); - logManager.info(""); + logTestResult(scenario); } + /** + * Attaches a screenshot for failed scenarios. + * + * @param scenario the failed test scenario + */ + private void attachScreenshotForFailedScenario(Scenario scenario) { + String sanitizedScenarioName = scenario.getName().replaceAll("\\s+", "_"); + String sanitizedFeatureName = scenario.getId() + .replaceAll("\\s+", "_") + .replaceAll(":", "_") + .split("\\.")[1]; + String filename = sanitizedScenarioName + "_" + sanitizedFeatureName; + + scenario.attach(filename.getBytes(StandardCharsets.UTF_8), "image/png", filename); + } + /** + * Logs the test result with formatted output. + * + * @param scenario the completed test scenario + */ + private void logTestResult(Scenario scenario) { + logManager.info(""); + logManager.info(LOG_SEPARATOR); + logManager.info(TEST_STATUS_PREFIX + scenario.getStatus() + TEST_STATUS_SUFFIX); + logManager.info(LOG_SEPARATOR); + logManager.info(""); + } } \ No newline at end of file diff --git a/common/src/main/java/com/cmccarthy/common/utils/StringUtil.java b/common/src/main/java/com/cmccarthy/common/utils/StringUtil.java index 1ee3505..f8014fa 100644 --- a/common/src/main/java/com/cmccarthy/common/utils/StringUtil.java +++ b/common/src/main/java/com/cmccarthy/common/utils/StringUtil.java @@ -1,114 +1,210 @@ -package com.cmccarthy.common.utils; - -import java.security.SecureRandom; -import java.util.NoSuchElementException; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - -@SuppressWarnings("unused") -public class StringUtil { - - private static final Random random = new Random(); - private static final SecureRandom secureRandom = new SecureRandom(); - private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - private static final String NUMBERS = "0123456789"; - private static final String ALPHANUMERIC = ALPHABET + NUMBERS; - - /** - * Generates a random string from the given character set. - * - * @param length the length of the string to generate - * @param charset the character set to use - * @return a random string - */ - private static String generateRandomString(int length, String charset) { - StringBuilder sb = new StringBuilder(length); - for (int i = 0; i < length; i++) { - sb.append(charset.charAt(secureRandom.nextInt(charset.length()))); - } - return sb.toString(); - } - - public static boolean getRandomBoolean() { - return random.nextBoolean(); - } - - public static int getRandomNumber(int min, int max) { - if (min > max) { - throw new IllegalArgumentException( - "Min (" + min + ") should not be larger than Max (" + max + ")"); - } - return ThreadLocalRandom.current().nextInt(min, max + 1); - } - - public static String getRandomAlphaString(int length) { - return generateRandomString(length, ALPHABET); - } - - public static String getRandomAlphaString(int min, int max) { - return generateRandomString(getRandomNumber(min, max), ALPHABET); - } - - public static String getRandomNumericString(int length, int min, int max) { - // Generate numeric string with values between min and max - StringBuilder sb = new StringBuilder(length); - for (int i = 0; i < length; i++) { - int digit = ThreadLocalRandom.current().nextInt(min, max + 1) % 10; - sb.append(digit); - } - return sb.toString(); - } - - public static String getRandomNumericString(int min, int max) { - return generateRandomString(getRandomNumber(min, max), NUMBERS); - } - - public static String getRandomAlphaNumericString(int length) { - return generateRandomString(length, ALPHANUMERIC); - } - - public static String getRandomAlphaNumericString(int min, int max) { - return generateRandomString(getRandomNumber(min, max), ALPHANUMERIC); - } - - public static String getRandomAmount(String min, String max) { - if (Double.parseDouble(min) > Double.parseDouble(max)) { - throw new IllegalArgumentException( - ": Min (" + min + ") should not be larger than Max (" + max + ")"); - } - return String.format("%.2f", ThreadLocalRandom.current() - .nextDouble(Double.parseDouble(min), Double.parseDouble(max) + 0.01)); - } - - public static double getRandomAmount(double min, double max) { - if (min > max) { - throw new IllegalArgumentException( - ": Min (" + min + ") should not be larger than Max (" + max + ")"); - } - return Double.parseDouble( - String.format("%.2f", ThreadLocalRandom.current().nextDouble(min, max + 0.01))); - } - - public static String featureStringManager(String tableValue) { - if (tableValue != null) { - final String[] dateTableData = tableValue.split("\\s+"); - - final String switchType = dateTableData[0]; - - final int length = Integer.parseInt(dateTableData[1]); - - switch (switchType) { - case "StringInteger": - return getRandomAlphaNumericString(length); - case "String": - return getRandomAlphaString(length); - case "Integer": - return getRandomNumericString(length, 2, 66); - default: - throw new NoSuchElementException("Could not create a String of type : " + switchType); - } - } else { - return null; - } - } +package com.cmccarthy.common.utils; + +import java.security.SecureRandom; +import java.util.NoSuchElementException; +import java.util.concurrent.ThreadLocalRandom; + +/** + * Utility class for generating random strings and numbers for test data. + * This class provides various methods to generate random data that can be used + * in test scenarios for creating test inputs. + */ +@SuppressWarnings("unused") +public final class StringUtil { + + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + private static final String NUMBERS = "0123456789"; + private static final String ALPHANUMERIC = ALPHABET + NUMBERS; + + /** + * Private constructor to prevent instantiation of this utility class. + */ + private StringUtil() { + throw new AssertionError("StringUtil class should not be instantiated"); + } + + /** + * Generates a random string from the given character set. + * + * @param length the length of the string to generate + * @param charset the character set to use + * @return a random string + * @throws IllegalArgumentException if length is negative + */ + private static String generateRandomString(int length, String charset) { + if (length < 0) { + throw new IllegalArgumentException("Length must be non-negative, but was: " + length); + } + if (length == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; i++) { + sb.append(charset.charAt(SECURE_RANDOM.nextInt(charset.length()))); + } + return sb.toString(); + } + + /** + * Generates a random boolean value. + * + * @return a random boolean + */ + public static boolean getRandomBoolean() { + return SECURE_RANDOM.nextBoolean(); + } + + /** + * Generates a random integer between min and max (inclusive). + * + * @param min the minimum value (inclusive) + * @param max the maximum value (inclusive) + * @return a random integer + * @throws IllegalArgumentException if min is greater than max + */ + public static int getRandomNumber(int min, int max) { + if (min > max) { + throw new IllegalArgumentException( + "Min (" + min + ") should not be greater than Max (" + max + ")"); + } + return ThreadLocalRandom.current().nextInt(min, max + 1); + } + + /** + * Generates a random alphabetic string of specified length. + * + * @param length the length of the string to generate + * @return a random alphabetic string + */ + public static String getRandomAlphaString(int length) { + return generateRandomString(length, ALPHABET); + } + + /** + * Generates a random alphabetic string of random length between min and max. + * + * @param min the minimum length + * @param max the maximum length + * @return a random alphabetic string + */ + public static String getRandomAlphaString(int min, int max) { + return generateRandomString(getRandomNumber(min, max), ALPHABET); + } + + /** + * Generates a random numeric string of specified length. + * + * @param length the length of the string to generate + * @return a random numeric string + */ + public static String getRandomNumericString(int length) { + return generateRandomString(length, NUMBERS); + } + + /** + * Generates a random numeric string of random length between min and max. + * + * @param min the minimum length + * @param max the maximum length + * @return a random numeric string + */ + public static String getRandomNumericString(int min, int max) { + return generateRandomString(getRandomNumber(min, max), NUMBERS); + } + + /** + * Generates a random alphanumeric string of specified length. + * + * @param length the length of the string to generate + * @return a random alphanumeric string + */ + public static String getRandomAlphaNumericString(int length) { + return generateRandomString(length, ALPHANUMERIC); + } + + /** + * Generates a random alphanumeric string of random length between min and max. + * + * @param min the minimum length + * @param max the maximum length + * @return a random alphanumeric string + */ + public static String getRandomAlphaNumericString(int min, int max) { + return generateRandomString(getRandomNumber(min, max), ALPHANUMERIC); + } + + /** + * Generates a random amount as a string between min and max values. + * + * @param min the minimum value as string + * @param max the maximum value as string + * @return a random amount formatted to 2 decimal places + * @throws IllegalArgumentException if min is greater than max + */ + public static String getRandomAmount(String min, String max) { + double minValue = Double.parseDouble(min); + double maxValue = Double.parseDouble(max); + + if (minValue > maxValue) { + throw new IllegalArgumentException( + "Min (" + min + ") should not be greater than Max (" + max + ")"); + } + return String.format("%.2f", ThreadLocalRandom.current() + .nextDouble(minValue, maxValue + 0.01)); + } + + /** + * Generates a random amount as a double between min and max values. + * + * @param min the minimum value + * @param max the maximum value + * @return a random amount formatted to 2 decimal places + * @throws IllegalArgumentException if min is greater than max + */ + public static double getRandomAmount(double min, double max) { + if (min > max) { + throw new IllegalArgumentException( + "Min (" + min + ") should not be greater than Max (" + max + ")"); + } + return Double.parseDouble( + String.format("%.2f", ThreadLocalRandom.current().nextDouble(min, max + 0.01))); + } + + /** + * Manages feature string generation based on table value input. + * Expected format: "StringType Length" (e.g., "String 10", "Integer 5") + * + * @param tableValue the table value containing type and length + * @return a random string based on the specified type and length + * @throws NoSuchElementException if the string type is not supported + */ + public static String featureStringManager(String tableValue) { + if (tableValue == null) { + return null; + } + + final String[] tableData = tableValue.trim().split("\\s+"); + if (tableData.length < 2) { + throw new IllegalArgumentException("Invalid table value format. Expected: 'Type Length'"); + } + + final String stringType = tableData[0]; + final int length; + + try { + length = Integer.parseInt(tableData[1]); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid length value: " + tableData[1]); + } + + return switch (stringType) { + case "StringInteger" -> getRandomAlphaNumericString(length); + case "String" -> getRandomAlphaString(length); + case "Integer" -> getRandomNumericString(length); + default -> throw new NoSuchElementException("Unsupported string type: " + stringType + + ". Supported types: String, Integer, StringInteger"); + }; + } } diff --git a/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverManager.java b/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverManager.java index 07e903e..12072d2 100644 --- a/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverManager.java +++ b/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverManager.java @@ -122,7 +122,7 @@ public void setLocalWebDriver() { driverWait.getDriverWaitThreadLocal() .set(new WebDriverWait(driver, Duration.ofSeconds(testConfig.getTimeoutSeconds()), - Duration.ofMillis(Constants.pollingShort))); + Duration.ofMillis(Constants.POLLING_SHORT))); } private void setRemoteDriver(URL hubUrl) { @@ -174,7 +174,7 @@ private void setRemoteDriver(URL hubUrl) { driverWait.getDriverWaitThreadLocal() .set(new WebDriverWait(driver, Duration.ofSeconds(testConfig.getTimeoutSeconds()), - Duration.ofMillis(Constants.pollingShort))); + Duration.ofMillis(Constants.POLLING_SHORT))); } public WebDriver getDriver() { diff --git a/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverWait.java b/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverWait.java index 3e2b3e9..37045fd 100644 --- a/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverWait.java +++ b/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverWait.java @@ -117,7 +117,7 @@ public Wait waitLong() { public Wait waitShort() { return new FluentWait<>(driverManager.getDriver()) .withTimeout(Duration.ofSeconds(Constants.timeoutShort)) - .pollingEvery(Duration.ofMillis(Constants.pollingShort)) + .pollingEvery(Duration.ofMillis(Constants.POLLING_SHORT)) .ignoring(NoSuchElementException.class, StaleElementReferenceException.class); } diff --git a/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElement.java b/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElement.java index ecb0414..1612ff2 100644 --- a/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElement.java +++ b/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElement.java @@ -25,7 +25,7 @@ public WebElement apply(WebDriver webDriver) { final Wait wait = new FluentWait<>(webDriver) .withTimeout(Duration.ofSeconds(Constants.timeoutShort)) - .pollingEvery(Duration.ofMillis(Constants.pollingShort)) + .pollingEvery(Duration.ofMillis(Constants.POLLING_SHORT)) .ignoring(java.util.NoSuchElementException.class, StaleElementReferenceException.class); try { diff --git a/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElementByLocator.java b/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElementByLocator.java index 66a5b10..aead8cc 100644 --- a/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElementByLocator.java +++ b/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElementByLocator.java @@ -22,7 +22,7 @@ public WebElement apply(WebDriver webDriver) { final Wait wait = new FluentWait<>(webDriver) .withTimeout(Duration.ofSeconds(Constants.timeoutShort)) - .pollingEvery(Duration.ofMillis(Constants.pollingShort)) + .pollingEvery(Duration.ofMillis(Constants.POLLING_SHORT)) .ignoring(java.util.NoSuchElementException.class, StaleElementReferenceException.class); From 23f30dc6f6a0bc10076b0b1003f9667729daa665 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Sep 2025 07:55:55 +0000 Subject: [PATCH 3/3] Fix remaining constant name references to complete naming convention improvements Co-authored-by: cmccarthyIrl <32817808+cmccarthyIrl@users.noreply.github.com> --- .../com/cmccarthy/ui/utils/DriverWait.java | 24 +++++++++---------- .../ClickabilityOfElement.java | 2 +- .../ClickabilityOfElementByLocator.java | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverWait.java b/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverWait.java index 37045fd..c308efd 100644 --- a/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverWait.java +++ b/wikipedia/src/test/java/com/cmccarthy/ui/utils/DriverWait.java @@ -107,18 +107,18 @@ private void waitForElementClickable(By locator) throws NoSuchFieldException { } } - public Wait waitLong() { - return new FluentWait<>(driverManager.getDriver()) - .withTimeout(Duration.ofSeconds(Constants.timeoutLong)) - .pollingEvery(Duration.ofMillis(Constants.pollingLong)) - .ignoring(NoSuchElementException.class, StaleElementReferenceException.class); - } - - public Wait waitShort() { - return new FluentWait<>(driverManager.getDriver()) - .withTimeout(Duration.ofSeconds(Constants.timeoutShort)) - .pollingEvery(Duration.ofMillis(Constants.POLLING_SHORT)) - .ignoring(NoSuchElementException.class, StaleElementReferenceException.class); + public Wait waitLong() { + return new FluentWait<>(driverManager.getDriver()) + .withTimeout(Duration.ofSeconds(Constants.TIMEOUT_LONG)) + .pollingEvery(Duration.ofMillis(Constants.POLLING_LONG)) + .ignoring(NoSuchElementException.class, StaleElementReferenceException.class); + } + + public Wait waitShort() { + return new FluentWait<>(driverManager.getDriver()) + .withTimeout(Duration.ofSeconds(Constants.TIMEOUT_SHORT)) + .pollingEvery(Duration.ofMillis(Constants.POLLING_SHORT)) + .ignoring(NoSuchElementException.class, StaleElementReferenceException.class); } private void waitUntilAngularReady() { diff --git a/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElement.java b/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElement.java index 1612ff2..e92a911 100644 --- a/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElement.java +++ b/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElement.java @@ -24,7 +24,7 @@ public ClickabilityOfElement(WebElement element) { public WebElement apply(WebDriver webDriver) { final Wait wait = new FluentWait<>(webDriver) - .withTimeout(Duration.ofSeconds(Constants.timeoutShort)) + .withTimeout(Duration.ofSeconds(Constants.TIMEOUT_SHORT)) .pollingEvery(Duration.ofMillis(Constants.POLLING_SHORT)) .ignoring(java.util.NoSuchElementException.class, StaleElementReferenceException.class); diff --git a/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElementByLocator.java b/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElementByLocator.java index aead8cc..6a242a0 100644 --- a/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElementByLocator.java +++ b/wikipedia/src/test/java/com/cmccarthy/ui/utils/expectedConditions/ClickabilityOfElementByLocator.java @@ -21,7 +21,7 @@ public ClickabilityOfElementByLocator(By locator) { public WebElement apply(WebDriver webDriver) { final Wait wait = new FluentWait<>(webDriver) - .withTimeout(Duration.ofSeconds(Constants.timeoutShort)) + .withTimeout(Duration.ofSeconds(Constants.TIMEOUT_SHORT)) .pollingEvery(Duration.ofMillis(Constants.POLLING_SHORT)) .ignoring(java.util.NoSuchElementException.class, StaleElementReferenceException.class);