Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Spring `<dependencies>`:

```xml

<dependecies>
<dependencies>
...
<dependency>
<groupId>org.springframework.amqp</groupId>
Expand All @@ -65,14 +65,14 @@ Spring `<dependencies>`:
<artifactId>spring-test</artifactId>
</dependency>
...
</dependecies>
</dependencies>
```

Cucumber & Rest Assured `<dependencies>`:

```xml

<dependecies>
<dependencies>
...
<dependency>
<groupId>io.rest-assured</groupId>
Expand All @@ -95,14 +95,14 @@ Cucumber & Rest Assured `<dependencies>`:
<version>${cucumber.version}</version>
</dependency>
...
</dependecies>
</dependencies>
```

Selenium `<dependencies>`:

```xml

<dependecies>
<dependencies>
...
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
Expand All @@ -115,7 +115,7 @@ Selenium `<dependencies>`:
<version>${selenium-version}</version>
</dependency>
...
</dependecies>
</dependencies>
```

# Quickstart
Expand All @@ -126,7 +126,7 @@ Selenium `<dependencies>`:

# 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`
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}

}
31 changes: 26 additions & 5 deletions common/src/main/java/com/cmccarthy/common/utils/Constants.java
Original file line number Diff line number Diff line change
@@ -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");
}
}
158 changes: 124 additions & 34 deletions common/src/main/java/com/cmccarthy/common/utils/DateTimeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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 +/-");
};
}
}
Loading