From f7c2b0069d29314adc9ce4493c796058d48808a5 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Wed, 28 Aug 2024 12:56:31 +0300 Subject: [PATCH 01/19] refactor browser configuration comparison --- .../infrastructure/BrowserConfiguration.java | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java index fe849269..dd7e35d7 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java @@ -18,6 +18,7 @@ import org.openqa.selenium.Platform; import java.util.HashMap; +import java.util.Objects; public class BrowserConfiguration { @Setter @Getter private Browser browser; @@ -72,25 +73,18 @@ public BrowserConfiguration(DeviceName deviceName, Lifecycle browserBehavior, St @Override public boolean equals(Object obj) { - if (!(obj instanceof BrowserConfiguration)) - return false; - BrowserConfiguration that = (BrowserConfiguration)obj; - if (!((this.getBrowser() == null) ? (that.getBrowser() == null) : this.getBrowser().equals(that.getBrowser()))) - return false; - if (this.deviceName != that.deviceName) - return false; - if (!(this.getLifecycle() == null ? that.getLifecycle() == null : this.getLifecycle().equals(that.getLifecycle()))) - return false; - if (this.getHeight() != that.getHeight()) - return false; - if (this.getWidth() != that.getWidth()) - return false; - if (this.getVersion() != that.getVersion()) - return false; - if (!(this.getPlatform() == null ? that.getPlatform() == null : this.getPlatform().equals(that.getPlatform()))) - return false; - if (!(this.getDriverOptions() == null ? that.getDriverOptions() == null : this.getDriverOptions().equals(that.getDriverOptions()))) - return false; - return true; + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + + BrowserConfiguration that = (BrowserConfiguration) obj; + + if (!Objects.equals(this.getBrowser(), that.getBrowser())) return false; + if (!Objects.equals(this.deviceName, that.deviceName)) return false; + if (!Objects.equals(this.getLifecycle(), that.getLifecycle())) return false; + if (this.getHeight() != that.getHeight()) return false; + if (this.getWidth() != that.getWidth()) return false; + if (this.getVersion() != that.getVersion()) return false; + if (!Objects.equals(this.getPlatform(), that.getPlatform())) return false; + return Objects.equals(this.getDriverOptions(), that.getDriverOptions()); } } \ No newline at end of file From 50ca09c6e5ebe0524df0a53d9323037c890a80e8 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Tue, 10 Sep 2024 17:20:22 +0300 Subject: [PATCH 02/19] enhance EntitiesAsserter logging --- .../bellatrix/core/assertions/EntitiesAsserter.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java index f9cebf76..0181a9d1 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java @@ -12,6 +12,8 @@ */ package solutions.bellatrix.core.assertions; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import org.junit.jupiter.api.Assertions; import java.lang.reflect.Method; @@ -74,9 +76,11 @@ private static List assertAreEqualsInternal(TEntity expecte (LocalDateTime)currentRealProperty.invoke(realObject), deltaType, deltaQuantity, exceptionMessage); } else { + Gson serializer = new GsonBuilder().setPrettyPrinting().create(); + Assertions.assertEquals( - currentExpectedProperty.invoke(expectedObject), - currentRealProperty.invoke(realObject), + serializer.toJson(currentExpectedProperty.invoke(expectedObject)), + serializer.toJson(currentRealProperty.invoke(realObject)), exceptionMessage); } } From f3c1995fb697c09ba33f1824f176a59b09225fe0 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Tue, 10 Sep 2024 18:05:28 +0300 Subject: [PATCH 03/19] revert logging --- .../bellatrix/core/assertions/EntitiesAsserter.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java index 0181a9d1..f9cebf76 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java @@ -12,8 +12,6 @@ */ package solutions.bellatrix.core.assertions; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import org.junit.jupiter.api.Assertions; import java.lang.reflect.Method; @@ -76,11 +74,9 @@ private static List assertAreEqualsInternal(TEntity expecte (LocalDateTime)currentRealProperty.invoke(realObject), deltaType, deltaQuantity, exceptionMessage); } else { - Gson serializer = new GsonBuilder().setPrettyPrinting().create(); - Assertions.assertEquals( - serializer.toJson(currentExpectedProperty.invoke(expectedObject)), - serializer.toJson(currentRealProperty.invoke(realObject)), + currentExpectedProperty.invoke(expectedObject), + currentRealProperty.invoke(realObject), exceptionMessage); } } From 8a528cdd4f94fe949e2a9be97c40a0760c13216c Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Wed, 11 Sep 2024 16:18:59 +0300 Subject: [PATCH 04/19] add LocalDateTimeAdapter to Proxy Server --- .../infrastructure/LocalDateTimeAdapter.java | 22 +++++++++++++++ .../web/infrastructure/ProxyServer.java | 27 ++++++++++--------- 2 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/LocalDateTimeAdapter.java diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/LocalDateTimeAdapter.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/LocalDateTimeAdapter.java new file mode 100644 index 00000000..eac4cd3e --- /dev/null +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/LocalDateTimeAdapter.java @@ -0,0 +1,22 @@ +package solutions.bellatrix.web.infrastructure; + +import com.google.gson.*; + +import java.lang.reflect.Type; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class LocalDateTimeAdapter implements JsonSerializer, JsonDeserializer { + private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + + @Override + public JsonElement serialize(LocalDateTime src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(formatter.format(src).replace("+00:00", "")); + } + + @Override + public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return LocalDateTime.parse(json.getAsString().replace("+00:00", ""), formatter); + } +} \ No newline at end of file diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java index 65ef8c30..9b9ecb04 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java @@ -13,10 +13,7 @@ package solutions.bellatrix.web.infrastructure; -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import com.google.gson.*; import lombok.SneakyThrows; import net.lightbody.bmp.BrowserMobProxyServer; import net.lightbody.bmp.core.har.HarEntry; @@ -37,6 +34,7 @@ import java.lang.reflect.Type; import java.net.ServerSocket; import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -55,6 +53,8 @@ public class ProxyServer { HttpStatus.SC_PARTIAL_CONTENT, HttpStatus.SC_MULTI_STATUS); + private static Gson gson; + @SneakyThrows public static int init() { Log.info("Starting Proxy Service..."); @@ -64,6 +64,9 @@ public static int init() { PROXY_SERVER.get().enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT, CaptureType.REQUEST_HEADERS); PORT.set(port); Log.info("Proxy Service Started at Port %s".formatted(port)); + gson = new GsonBuilder() + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()) + .create(); return port; } @@ -220,7 +223,7 @@ public static T getLastRequest(Class requestModelClass) { return getCapturedEntries().stream() .map(HarEntry::getRequest) .filter(request -> request.getPostData() != null) - .map(request -> new Gson().fromJson(request.getPostData().getText(), requestModelClass)) + .map(request -> gson.fromJson(request.getPostData().getText(), requestModelClass)) .reduce((first, second) -> second) .orElse(null); } @@ -229,7 +232,7 @@ public static T getLastResponse(Class responseModelClass) { return getCapturedEntries().stream() .map(HarEntry::getResponse) .filter(response -> response.getContent() != null) - .map(response -> new Gson().fromJson(getDataObject(response.getContent().getText()), responseModelClass)) + .map(response -> gson.fromJson(getDataObject(response.getContent().getText()), responseModelClass)) .reduce((first, second) -> second) .orElse(null); } @@ -238,13 +241,13 @@ public static T getRequestByIndex(int index, Class requestModelClass) { var entries = getCapturedEntries(); var harEntry = entries.get(index); String json = harEntry.getRequest().getPostData().getText(); - return new Gson().fromJson(json, requestModelClass); + return gson.fromJson(json, requestModelClass); } public static T getResponseByIndex(int index, Class responseModelClass) { var harEntry = getCapturedEntries().get(index); String json = harEntry.getResponse().getContent().getText(); - return new Gson().fromJson(getDataObject(json), responseModelClass); + return gson.fromJson(getDataObject(json), responseModelClass); } public static T getRequestByUrl(String url, String httpMethod, Class requestModelClass) { @@ -258,7 +261,7 @@ public static T getRequestByUrl(String url, String httpMethod, Class requ } String json = harEntry.getRequest().getPostData().getText(); try { - return new Gson().fromJson(json, requestModelClass); + return gson.fromJson(json, requestModelClass); } catch (Exception e) { throw new RuntimeException("Error occurred while converting json to model. Json was: %s".formatted(json), e); @@ -276,7 +279,7 @@ public static T getRequestByUrl(String url, String httpMethod, Type modelTyp } String json = harEntry.getRequest().getPostData().getText(); try { - return new Gson().fromJson(json, modelType); + return gson.fromJson(json, modelType); } catch (Exception e) { throw new RuntimeException("Error occurred while converting json to model. Json was: %s".formatted(json), e); @@ -295,7 +298,7 @@ public static T getResponseByUrl(String url, String httpMethod, Class res } String json = harEntry.getResponse().getContent().getText(); try { - return new Gson().fromJson(getDataObject(json), responseModelClass); + return gson.fromJson(getDataObject(json), responseModelClass); } catch (Exception ex){ throw new AssertionFailedError("Cannot get JSON body from the string: " + json + ". Error was: " + ex.getMessage()); @@ -313,7 +316,7 @@ public static T getResponseByUrl(String url, String httpMethod, Type respons return null; } String json = harEntry.getResponse().getContent().getText(); - return new Gson().fromJson(getDataObject(json), responseModelType); + return gson.fromJson(getDataObject(json), responseModelType); } public static void blockRequestByUrl(String url, HttpMethod httpMethod) { From 7f9f52ab170b94922945845c61c02bbefe07c3de Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Thu, 12 Sep 2024 11:52:49 +0300 Subject: [PATCH 05/19] fix throw exception --- .../bellatrix/core/assertions/LocalDateTimeAssert.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/LocalDateTimeAssert.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/LocalDateTimeAssert.java index 8bc00f9a..2a71f6e8 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/LocalDateTimeAssert.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/LocalDateTimeAssert.java @@ -37,7 +37,7 @@ else if (actualDate == null){ } } - public static void areEqual(LocalDateTime expectedDate, LocalDateTime actualDate, Duration expectedDelta, String exceptionMessage) throws Exception { + public static void areEqual(LocalDateTime expectedDate, LocalDateTime actualDate, Duration expectedDelta, String exceptionMessage) { if (expectedDate == null && actualDate == null){ return; } @@ -54,7 +54,7 @@ else if (actualDate == null){ { var message = exceptionMessage+"\nExpected Date: "+expectedDate+", Actual Date: "+actualDate+ " \nExpected Delta: "+expectedDelta+", Actual Delta: "+actualDelta; - throw new Exception(message); + throw new RuntimeException(message); } } private static Duration getTimeSpanDeltaByType(DateTimeDeltaType type, int count) throws UnsupportedOperationException { From 4bd9e72abb3d809ec5484ba4608424a06ddae6d8 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Fri, 13 Sep 2024 15:37:27 +0300 Subject: [PATCH 06/19] add serialization Adapter --- .../core/assertions/EntitiesAsserter.java | 7 ++++++ .../core/assertions/LocalDateTimeAssert.java | 1 + .../OffsetDateTimeTypeAdapter.java | 22 +++++++++++++++++++ .../web/infrastructure/ProxyServer.java | 2 ++ 4 files changed, 32 insertions(+) create mode 100644 bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/OffsetDateTimeTypeAdapter.java diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java index f9cebf76..d569618c 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java @@ -16,6 +16,8 @@ import java.lang.reflect.Method; import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.OffsetTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -73,6 +75,11 @@ private static List assertAreEqualsInternal(TEntity expecte (LocalDateTime)currentExpectedProperty.invoke(expectedObject), (LocalDateTime)currentRealProperty.invoke(realObject), deltaType, deltaQuantity, exceptionMessage); + } else if (currentRealProperty.getReturnType() == OffsetDateTime.class) { + LocalDateTimeAssert.areEqual( + ((OffsetDateTime)currentExpectedProperty.invoke(expectedObject)).toLocalDateTime(), + ((OffsetDateTime)currentRealProperty.invoke(realObject)).toLocalDateTime(), + deltaType, deltaQuantity, exceptionMessage); } else { Assertions.assertEquals( currentExpectedProperty.invoke(expectedObject), diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/LocalDateTimeAssert.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/LocalDateTimeAssert.java index 2a71f6e8..d532a159 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/LocalDateTimeAssert.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/LocalDateTimeAssert.java @@ -37,6 +37,7 @@ else if (actualDate == null){ } } + public static void areEqual(LocalDateTime expectedDate, LocalDateTime actualDate, Duration expectedDelta, String exceptionMessage) { if (expectedDate == null && actualDate == null){ return; diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/OffsetDateTimeTypeAdapter.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/OffsetDateTimeTypeAdapter.java new file mode 100644 index 00000000..dd4ad690 --- /dev/null +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/OffsetDateTimeTypeAdapter.java @@ -0,0 +1,22 @@ +package solutions.bellatrix.web.infrastructure; + +import com.google.gson.*; + +import java.lang.reflect.Type; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; + +public class OffsetDateTimeTypeAdapter implements JsonSerializer, JsonDeserializer { + private final DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + + @Override + public JsonElement serialize(OffsetDateTime src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(formatter.format(src)); + } + + @Override + public OffsetDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return OffsetDateTime.parse(json.getAsString(), formatter); + } +} \ No newline at end of file diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java index 9b9ecb04..dfb1d8b1 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java @@ -35,6 +35,7 @@ import java.net.ServerSocket; import java.time.Duration; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -66,6 +67,7 @@ public static int init() { Log.info("Proxy Service Started at Port %s".formatted(port)); gson = new GsonBuilder() .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()) + .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) .create(); return port; } From d3bc0f751af444430572f6408088a4bc14a9abc5 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Mon, 16 Sep 2024 14:05:36 +0300 Subject: [PATCH 07/19] fix issue with PHP backend returning empty array instead of empty object --- .../EmptyObjectTypeAdapterFactory.java | 53 +++++++++++++++++++ .../OffsetDateTimeTypeAdapter.java | 13 ++++- .../web/infrastructure/ProxyServer.java | 1 + 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/EmptyObjectTypeAdapterFactory.java diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/EmptyObjectTypeAdapterFactory.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/EmptyObjectTypeAdapterFactory.java new file mode 100644 index 00000000..1acd84b8 --- /dev/null +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/EmptyObjectTypeAdapterFactory.java @@ -0,0 +1,53 @@ +package solutions.bellatrix.web.infrastructure; + +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class EmptyObjectTypeAdapterFactory implements TypeAdapterFactory { + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + TypeAdapter delegate = gson.getDelegateAdapter(this, type); + + return new TypeAdapter() { + @Override + public void write(JsonWriter out, T value) throws IOException { + delegate.write(out, value); + } + + @Override + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.BEGIN_ARRAY) { + JsonArray arr = new JsonParser().parse(in).getAsJsonArray(); + if (arr.size() == 0) { + if (isCollectionType(type.getType())) { + return delegate.fromJsonTree(arr); + } else { + return delegate.fromJsonTree(new JsonObject()); + } + } + return delegate.fromJsonTree(arr); + } + return delegate.read(in); + } + }; + } + + private boolean isCollectionType(Type type) { + if (type instanceof Class) { + return Collection.class.isAssignableFrom((Class)type); + } else if (type instanceof ParameterizedType) { + return isCollectionType(((ParameterizedType)type).getRawType()); + } + return false; + } +} \ No newline at end of file diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/OffsetDateTimeTypeAdapter.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/OffsetDateTimeTypeAdapter.java index dd4ad690..033d116d 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/OffsetDateTimeTypeAdapter.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/OffsetDateTimeTypeAdapter.java @@ -3,11 +3,14 @@ import com.google.gson.*; import java.lang.reflect.Type; +import java.time.LocalDateTime; import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; public class OffsetDateTimeTypeAdapter implements JsonSerializer, JsonDeserializer { private final DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + private final DateTimeFormatter localDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); @Override public JsonElement serialize(OffsetDateTime src, Type typeOfSrc, JsonSerializationContext context) { @@ -17,6 +20,14 @@ public JsonElement serialize(OffsetDateTime src, Type typeOfSrc, JsonSerializati @Override public OffsetDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return OffsetDateTime.parse(json.getAsString(), formatter); + OffsetDateTime result; + try { + result = OffsetDateTime.parse(json.getAsString(), formatter); + } + catch(Exception ex) { + result = LocalDateTime.parse(json.getAsString(), localDateTimeFormatter).atOffset(ZoneOffset.UTC); + } + + return result; } } \ No newline at end of file diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java index dfb1d8b1..c4ecaa4f 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java @@ -68,6 +68,7 @@ public static int init() { gson = new GsonBuilder() .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()) .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) + .registerTypeAdapterFactory(new EmptyObjectTypeAdapterFactory()) .create(); return port; } From 52af61fd324a390a299accf052618ccbe9566982 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Wed, 25 Sep 2024 13:28:54 +0300 Subject: [PATCH 08/19] add overload for request waiting methods --- .../solutions/bellatrix/web/infrastructure/ProxyServer.java | 2 +- .../solutions/bellatrix/web/services/BrowserService.java | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java index c4ecaa4f..993e75c5 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java @@ -170,7 +170,7 @@ public static void waitForResponse(WebDriver driver, String requestPartialUrl, H catch (TimeoutException exception){ String allUrlsString = getSimilarRequestsString(requestPartialUrl, allHarEntries); - throw new AssertionFailedError(String.format("The expected response with request URL '%s' with method %s is not loaded! \r\nSimilar requests: %s", requestPartialUrl, httpMethod, allUrlsString)); + throw new RuntimeException(String.format("The expected response with request URL '%s' with method %s is not loaded! \r\nSimilar requests: %s", requestPartialUrl, httpMethod, allUrlsString)); } } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java index 416e313b..22faa0c2 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java @@ -428,7 +428,7 @@ public void waitForRequest(String partialUrl) { } } - public void tryWaitForResponse(String partialUrl) { + public void tryWaitForResponse(String partialUrl, int additionalTimeoutInSeconds) { try { if(ProxyServer.get() != null) { ProxyServer.waitForResponse(getWrappedDriver(), partialUrl, HttpMethod.GET, 0); @@ -442,6 +442,10 @@ public void tryWaitForResponse(String partialUrl) { } } + public void tryWaitForResponse(String partialUrl) { + tryWaitForResponse(partialUrl, 0); + } + public void waitForAngular() { long angularTimeout = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getWaitForAngularTimeout(); long sleepInterval = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getSleepInterval(); From 365517aafff81fe3192cadcea6c9e8fcc121303f Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Thu, 26 Sep 2024 09:39:51 +0300 Subject: [PATCH 09/19] add exception type to error handling --- .../java/solutions/bellatrix/web/components/WebComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/WebComponent.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/WebComponent.java index 4b17d3f4..fd57b34c 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/WebComponent.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/WebComponent.java @@ -119,7 +119,7 @@ public WebElement getWrappedElement() { try { wrappedElement.isDisplayed(); // checking if getting property throws exception return wrappedElement; - } catch (StaleElementReferenceException | NoSuchElementException | NullPointerException ex) { + } catch (StaleElementReferenceException | NoSuchElementException | NullPointerException | ScriptTimeoutException ex ) { return findElement(); } } From 84a52d2cd474f06230e61599705fe5549df1a43c Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Fri, 27 Sep 2024 09:38:09 +0300 Subject: [PATCH 10/19] add exception type to error handling --- .../bellatrix/web/infrastructure/ProxyServer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java index 993e75c5..f9461bc6 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/ProxyServer.java @@ -319,7 +319,12 @@ public static T getResponseByUrl(String url, String httpMethod, Type respons return null; } String json = harEntry.getResponse().getContent().getText(); - return gson.fromJson(getDataObject(json), responseModelType); + try { + return gson.fromJson(getDataObject(json), responseModelType); + } + catch (Exception ex) { + throw new RuntimeException("Failed to Serialize Json to Object: \n Entity Type: %s\n Json was: %s".formatted(responseModelType.getTypeName(), json)); + } } public static void blockRequestByUrl(String url, HttpMethod httpMethod) { From a18ad7511c64e22b584f187a9316363f5578f57d Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Mon, 30 Sep 2024 11:13:11 +0300 Subject: [PATCH 11/19] improve Entities Assert --- .../bellatrix/core/assertions/EntitiesAsserter.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java index d569618c..ec30640f 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java @@ -70,6 +70,7 @@ private static List assertAreEqualsInternal(TEntity expecte var exceptionMessage = "The property " + currentRealProperty.getName() + " of class " + realObject.getClass().getSimpleName() + " was not as expected."; try { + assert currentExpectedProperty != null; if (currentRealProperty.getReturnType() == LocalDateTime.class) { LocalDateTimeAssert.areEqual( (LocalDateTime)currentExpectedProperty.invoke(expectedObject), @@ -82,8 +83,8 @@ private static List assertAreEqualsInternal(TEntity expecte deltaType, deltaQuantity, exceptionMessage); } else { Assertions.assertEquals( - currentExpectedProperty.invoke(expectedObject), - currentRealProperty.invoke(realObject), + ((Object)currentExpectedProperty.invoke(expectedObject)).toString(), + currentRealProperty.invoke(realObject).toString(), exceptionMessage); } } From c8a18b7378304afb793480b9363a738b2446007d Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Mon, 30 Sep 2024 14:50:55 +0300 Subject: [PATCH 12/19] revert assert logic --- .../bellatrix/core/assertions/EntitiesAsserter.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java index ec30640f..c34b507a 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/assertions/EntitiesAsserter.java @@ -17,7 +17,6 @@ import java.lang.reflect.Method; import java.time.LocalDateTime; import java.time.OffsetDateTime; -import java.time.OffsetTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -25,10 +24,7 @@ public class EntitiesAsserter { public static Boolean areEqual(TEntity expectedObject, TEntity realObject, DateTimeDeltaType deltaType, int deltaQuantity, String... propertiesNotToCompare) { List failedAssertions = assertAreEqualsInternal(expectedObject, realObject, deltaType, deltaQuantity, propertiesNotToCompare); - if (failedAssertions.size() > 1) { - return false; - } - return true; + return failedAssertions.size() <= 1; } public static Boolean areEqual(TEntity expectedObject, TEntity realObject, String... propertiesNotToCompare) { return areEqual(expectedObject, realObject, DateTimeDeltaType.MILLISECONDS, 300, propertiesNotToCompare); @@ -70,21 +66,22 @@ private static List assertAreEqualsInternal(TEntity expecte var exceptionMessage = "The property " + currentRealProperty.getName() + " of class " + realObject.getClass().getSimpleName() + " was not as expected."; try { - assert currentExpectedProperty != null; if (currentRealProperty.getReturnType() == LocalDateTime.class) { + assert currentExpectedProperty != null; LocalDateTimeAssert.areEqual( (LocalDateTime)currentExpectedProperty.invoke(expectedObject), (LocalDateTime)currentRealProperty.invoke(realObject), deltaType, deltaQuantity, exceptionMessage); } else if (currentRealProperty.getReturnType() == OffsetDateTime.class) { + assert currentExpectedProperty != null; LocalDateTimeAssert.areEqual( ((OffsetDateTime)currentExpectedProperty.invoke(expectedObject)).toLocalDateTime(), ((OffsetDateTime)currentRealProperty.invoke(realObject)).toLocalDateTime(), deltaType, deltaQuantity, exceptionMessage); } else { Assertions.assertEquals( - ((Object)currentExpectedProperty.invoke(expectedObject)).toString(), - currentRealProperty.invoke(realObject).toString(), + currentExpectedProperty != null ? currentExpectedProperty.invoke(expectedObject) : null, + currentRealProperty.invoke(realObject), exceptionMessage); } } From 02b4d5645fa4fc35dff4e848ad4dd5646f1494f7 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Fri, 4 Oct 2024 10:54:13 +0300 Subject: [PATCH 13/19] Add event postAfterALl to enable plugins code execution after all tests from all packages have finished. --- bellatrix.core/pom.xml | 6 ++++++ .../solutions/bellatrix/core/plugins/Plugin.java | 3 +++ .../core/plugins/PluginExecutionEngine.java | 7 +++++++ .../core/plugins/junit/GlobalTestListener.java | 13 +++++++++++++ ...rg.junit.platform.launcher.TestExecutionListener | 1 + .../web/infrastructure/BrowserLifecyclePlugin.java | 10 +++++++++- .../java/solutions/bellatrix/web/pages/WebPage.java | 1 - .../bellatrix/web/services/BrowserService.java | 6 +++++- 8 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/GlobalTestListener.java create mode 100644 bellatrix.core/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener diff --git a/bellatrix.core/pom.xml b/bellatrix.core/pom.xml index 667a658e..51e875c6 100644 --- a/bellatrix.core/pom.xml +++ b/bellatrix.core/pom.xml @@ -158,5 +158,11 @@ jsoup 1.17.2 + + org.junit.platform + junit-platform-launcher + 1.11.0-M1 + compile + \ No newline at end of file diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java index 508b4b21..b04da638 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java @@ -70,6 +70,9 @@ public void preAfterClass(Class type) { public void postAfterClass(Class type) { } + public void postAfterAll() { + } + public void afterClassFailed(Exception e) { } } diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java index a4a65280..ba914006 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java @@ -132,6 +132,13 @@ public static void postAfterClass(Class type) { } } + public static void postAfterAll() { + for (var currentObserver : PLUGINS) { + if (currentObserver != null) + currentObserver.postAfterAll(); + } + } + public static void afterClassFailed(Exception e) { for (var currentObserver : PLUGINS) { if (currentObserver != null) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/GlobalTestListener.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/GlobalTestListener.java new file mode 100644 index 00000000..d388f91e --- /dev/null +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/GlobalTestListener.java @@ -0,0 +1,13 @@ +package solutions.bellatrix.core.plugins.junit; + +import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestPlan; +import solutions.bellatrix.core.plugins.PluginExecutionEngine; + +public class GlobalTestListener implements TestExecutionListener { + + @Override + public void testPlanExecutionFinished(TestPlan testPlan) { + PluginExecutionEngine.postAfterAll(); + } +} \ No newline at end of file diff --git a/bellatrix.core/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener b/bellatrix.core/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener new file mode 100644 index 00000000..a068904a --- /dev/null +++ b/bellatrix.core/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener @@ -0,0 +1 @@ +solutions.bellatrix.core.plugins.junit.GlobalTestListener \ No newline at end of file diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java index f36893e2..9cc19941 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java @@ -49,7 +49,9 @@ public void preBeforeClass(Class type) { @Override public void postAfterClass(Class type) { - shutdownBrowser(); + if(Objects.equals(ConfigurationService.get(WebSettings.class).getExecutionType(), "grid")) { + shutdownBrowser(); + } super.preAfterClass(type); } @@ -82,7 +84,13 @@ public void postAfterTest(TestResult testResult, Method memberInfo, Throwable fa shutdownBrowser(); } + @Override + public void postAfterAll() { + shutdownBrowser(); + } + private void shutdownBrowser() { + Log.info("Shutting down driver..."); DriverService.close(); PREVIOUS_BROWSER_CONFIGURATION.remove(); } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/pages/WebPage.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/pages/WebPage.java index 593c94c2..ff6b5b80 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/pages/WebPage.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/pages/WebPage.java @@ -13,7 +13,6 @@ package solutions.bellatrix.web.pages; -import solutions.bellatrix.web.infrastructure.Browser; import solutions.bellatrix.web.services.App; import solutions.bellatrix.web.services.BrowserService; import solutions.bellatrix.web.services.ComponentCreateService; diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java index 22faa0c2..c1900c38 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java @@ -164,7 +164,11 @@ public void setItemInLocalStorage(String item, String value) { } public void clearLocalStorage() { - ((JavascriptExecutor)getWrappedDriver()).executeScript("localStorage.clear()"); + try { + ((JavascriptExecutor)getWrappedDriver()).executeScript("localStorage.clear()"); + } catch (Exception ex) { + Log.error("Failed to clear local storage because of error: %s".formatted(ex.getMessage())); + } } public List getBrowserLogs() { From 9b134b97f9435144c40f2e78da30815e4350351a Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Mon, 7 Oct 2024 15:04:46 +0300 Subject: [PATCH 14/19] add browser lifespan property in webSettings --- .../web/configuration/WebSettings.java | 1 + .../infrastructure/BrowserConfiguration.java | 5 +- .../BrowserLifecyclePlugin.java | 11 ++-- .../infrastructure/MaxBrowserLifeSpan.java | 51 +++++++++++++++++++ 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/MaxBrowserLifeSpan.java diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/configuration/WebSettings.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/configuration/WebSettings.java index 596561ee..17ddbc56 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/configuration/WebSettings.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/configuration/WebSettings.java @@ -34,6 +34,7 @@ public class WebSettings { @Getter @Setter private String baseUrl; @Getter @Setter private String executionType; @Getter @Setter private String defaultLifeCycle; + @Getter @Setter private String maxBrowserLifespan; @Getter @Setter private String defaultBrowser; @Getter @Setter private Integer defaultBrowserWidth = 0; @Getter @Setter private Integer defaultBrowserHeight = 0; diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java index dd7e35d7..522357c9 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java @@ -24,6 +24,7 @@ public class BrowserConfiguration { @Setter @Getter private Browser browser; @Setter @Getter private DeviceName deviceName; @Setter @Getter private Lifecycle lifecycle; + @Setter @Getter private MaxBrowserLifeSpan maxBrowserLifespan; @Setter @Getter private int height; @Setter @Getter private int width; @Setter @Getter private int version; @@ -48,9 +49,10 @@ public BrowserConfiguration(Browser browser, DeviceName deviceName, Lifecycle br driverOptions = new HashMap<>(); } - public BrowserConfiguration(Browser browser, Lifecycle browserBehavior, Integer browserWidth, Integer browserHeight) { + public BrowserConfiguration(Browser browser, Lifecycle browserBehavior, MaxBrowserLifeSpan lifespan, Integer browserWidth, Integer browserHeight) { this.browser = browser; this.lifecycle = browserBehavior; + this.maxBrowserLifespan = lifespan; this.width = browserWidth; this.height = browserHeight; driverOptions = new HashMap<>(); @@ -66,6 +68,7 @@ public BrowserConfiguration(Browser browser, Lifecycle browserBehavior, String t public BrowserConfiguration(DeviceName deviceName, Lifecycle browserBehavior, String testName) { this.browser = Browser.CHROME_MOBILE; this.lifecycle = browserBehavior; + this.maxBrowserLifespan = MaxBrowserLifeSpan.TEST_RUN; this.testName = testName; this.deviceName = deviceName; driverOptions = new HashMap<>(); diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java index 9cc19941..c4c84169 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java @@ -49,7 +49,8 @@ public void preBeforeClass(Class type) { @Override public void postAfterClass(Class type) { - if(Objects.equals(ConfigurationService.get(WebSettings.class).getExecutionType(), "grid")) { + if(CURRENT_BROWSER_CONFIGURATION.get().getLifecycle() == Lifecycle.REUSE_IF_STARTED + && CURRENT_BROWSER_CONFIGURATION.get().getMaxBrowserLifespan() == MaxBrowserLifeSpan.CLASS) { shutdownBrowser(); } super.preAfterClass(type); @@ -86,7 +87,10 @@ public void postAfterTest(TestResult testResult, Method memberInfo, Throwable fa @Override public void postAfterAll() { - shutdownBrowser(); + if(CURRENT_BROWSER_CONFIGURATION.get().getLifecycle() == Lifecycle.REUSE_IF_STARTED + && CURRENT_BROWSER_CONFIGURATION.get().getMaxBrowserLifespan() != MaxBrowserLifeSpan.CLASS) { + shutdownBrowser(); + } } private void shutdownBrowser() { @@ -150,6 +154,7 @@ private BrowserConfiguration getExecutionBrowserMethodLevel(Method memberInfo) { private BrowserConfiguration getExecutionBrowserClassLevel(Class clazz) { var browser = Browser.fromText(SecretsResolver.getSecret(ConfigurationService.get(WebSettings.class).getDefaultBrowser())); var lifecycle = Lifecycle.fromText(ConfigurationService.get(WebSettings.class).getDefaultLifeCycle()); + var lifespan = MaxBrowserLifeSpan.fromText(ConfigurationService.get(WebSettings.class).getMaxBrowserLifespan()); var width = ConfigurationService.get(WebSettings.class).getDefaultBrowserWidth(); var height = ConfigurationService.get(WebSettings.class).getDefaultBrowserHeight(); @@ -166,6 +171,6 @@ private BrowserConfiguration getExecutionBrowserClassLevel(Class clazz) { } } - return new BrowserConfiguration(browser, lifecycle, width, height); + return new BrowserConfiguration(browser, lifecycle, lifespan, width, height); } } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/MaxBrowserLifeSpan.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/MaxBrowserLifeSpan.java new file mode 100644 index 00000000..5ef9947f --- /dev/null +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/MaxBrowserLifeSpan.java @@ -0,0 +1,51 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Nikolay Avramov + * 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 solutions.bellatrix.web.infrastructure;/* + * Copyright 2022 Automate The Planet Ltd. + * Author: Anton Angelov + * 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. + */ + +import java.util.Arrays; + +public enum MaxBrowserLifeSpan { + NOT_SET("not_set"), + CLASS("class"), + TEST_RUN("test_run"); + + private final String text; + + MaxBrowserLifeSpan(String text) { + this.text = text; + } + + public String getText() { + return this.text; + } + + public static MaxBrowserLifeSpan fromText(String text) { + return Arrays.stream(values()) + .filter(l -> l.text.equalsIgnoreCase(text) || + l.text.replace("_", " ").equalsIgnoreCase(text) || + l.text.replace("_", "").equalsIgnoreCase(text)) + .findFirst().orElse(MaxBrowserLifeSpan.NOT_SET); + } +} From 7b8294733beebe7af1722fda0be79a4fd57616a0 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Thu, 10 Oct 2024 16:25:11 +0300 Subject: [PATCH 15/19] Revert "add browser lifespan property in webSettings" This reverts commit 9b134b97f9435144c40f2e78da30815e4350351a. --- .../web/configuration/WebSettings.java | 1 - .../infrastructure/BrowserConfiguration.java | 5 +- .../BrowserLifecyclePlugin.java | 11 ++-- .../infrastructure/MaxBrowserLifeSpan.java | 51 ------------------- 4 files changed, 4 insertions(+), 64 deletions(-) delete mode 100644 bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/MaxBrowserLifeSpan.java diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/configuration/WebSettings.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/configuration/WebSettings.java index 17ddbc56..596561ee 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/configuration/WebSettings.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/configuration/WebSettings.java @@ -34,7 +34,6 @@ public class WebSettings { @Getter @Setter private String baseUrl; @Getter @Setter private String executionType; @Getter @Setter private String defaultLifeCycle; - @Getter @Setter private String maxBrowserLifespan; @Getter @Setter private String defaultBrowser; @Getter @Setter private Integer defaultBrowserWidth = 0; @Getter @Setter private Integer defaultBrowserHeight = 0; diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java index 522357c9..dd7e35d7 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserConfiguration.java @@ -24,7 +24,6 @@ public class BrowserConfiguration { @Setter @Getter private Browser browser; @Setter @Getter private DeviceName deviceName; @Setter @Getter private Lifecycle lifecycle; - @Setter @Getter private MaxBrowserLifeSpan maxBrowserLifespan; @Setter @Getter private int height; @Setter @Getter private int width; @Setter @Getter private int version; @@ -49,10 +48,9 @@ public BrowserConfiguration(Browser browser, DeviceName deviceName, Lifecycle br driverOptions = new HashMap<>(); } - public BrowserConfiguration(Browser browser, Lifecycle browserBehavior, MaxBrowserLifeSpan lifespan, Integer browserWidth, Integer browserHeight) { + public BrowserConfiguration(Browser browser, Lifecycle browserBehavior, Integer browserWidth, Integer browserHeight) { this.browser = browser; this.lifecycle = browserBehavior; - this.maxBrowserLifespan = lifespan; this.width = browserWidth; this.height = browserHeight; driverOptions = new HashMap<>(); @@ -68,7 +66,6 @@ public BrowserConfiguration(Browser browser, Lifecycle browserBehavior, String t public BrowserConfiguration(DeviceName deviceName, Lifecycle browserBehavior, String testName) { this.browser = Browser.CHROME_MOBILE; this.lifecycle = browserBehavior; - this.maxBrowserLifespan = MaxBrowserLifeSpan.TEST_RUN; this.testName = testName; this.deviceName = deviceName; driverOptions = new HashMap<>(); diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java index c4c84169..9cc19941 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java @@ -49,8 +49,7 @@ public void preBeforeClass(Class type) { @Override public void postAfterClass(Class type) { - if(CURRENT_BROWSER_CONFIGURATION.get().getLifecycle() == Lifecycle.REUSE_IF_STARTED - && CURRENT_BROWSER_CONFIGURATION.get().getMaxBrowserLifespan() == MaxBrowserLifeSpan.CLASS) { + if(Objects.equals(ConfigurationService.get(WebSettings.class).getExecutionType(), "grid")) { shutdownBrowser(); } super.preAfterClass(type); @@ -87,10 +86,7 @@ public void postAfterTest(TestResult testResult, Method memberInfo, Throwable fa @Override public void postAfterAll() { - if(CURRENT_BROWSER_CONFIGURATION.get().getLifecycle() == Lifecycle.REUSE_IF_STARTED - && CURRENT_BROWSER_CONFIGURATION.get().getMaxBrowserLifespan() != MaxBrowserLifeSpan.CLASS) { - shutdownBrowser(); - } + shutdownBrowser(); } private void shutdownBrowser() { @@ -154,7 +150,6 @@ private BrowserConfiguration getExecutionBrowserMethodLevel(Method memberInfo) { private BrowserConfiguration getExecutionBrowserClassLevel(Class clazz) { var browser = Browser.fromText(SecretsResolver.getSecret(ConfigurationService.get(WebSettings.class).getDefaultBrowser())); var lifecycle = Lifecycle.fromText(ConfigurationService.get(WebSettings.class).getDefaultLifeCycle()); - var lifespan = MaxBrowserLifeSpan.fromText(ConfigurationService.get(WebSettings.class).getMaxBrowserLifespan()); var width = ConfigurationService.get(WebSettings.class).getDefaultBrowserWidth(); var height = ConfigurationService.get(WebSettings.class).getDefaultBrowserHeight(); @@ -171,6 +166,6 @@ private BrowserConfiguration getExecutionBrowserClassLevel(Class clazz) { } } - return new BrowserConfiguration(browser, lifecycle, lifespan, width, height); + return new BrowserConfiguration(browser, lifecycle, width, height); } } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/MaxBrowserLifeSpan.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/MaxBrowserLifeSpan.java deleted file mode 100644 index 5ef9947f..00000000 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/MaxBrowserLifeSpan.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2024 Automate The Planet Ltd. - * Author: Nikolay Avramov - * 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 solutions.bellatrix.web.infrastructure;/* - * Copyright 2022 Automate The Planet Ltd. - * Author: Anton Angelov - * 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. - */ - -import java.util.Arrays; - -public enum MaxBrowserLifeSpan { - NOT_SET("not_set"), - CLASS("class"), - TEST_RUN("test_run"); - - private final String text; - - MaxBrowserLifeSpan(String text) { - this.text = text; - } - - public String getText() { - return this.text; - } - - public static MaxBrowserLifeSpan fromText(String text) { - return Arrays.stream(values()) - .filter(l -> l.text.equalsIgnoreCase(text) || - l.text.replace("_", " ").equalsIgnoreCase(text) || - l.text.replace("_", "").equalsIgnoreCase(text)) - .findFirst().orElse(MaxBrowserLifeSpan.NOT_SET); - } -} From d78a28a2fd8730b5af1e750179536a2b1c4de2ae Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Thu, 10 Oct 2024 16:25:11 +0300 Subject: [PATCH 16/19] Revert "Add event postAfterALl to enable plugins code execution after all tests from all packages have finished." This reverts commit 02b4d5645fa4fc35dff4e848ad4dd5646f1494f7. --- bellatrix.core/pom.xml | 6 ------ .../solutions/bellatrix/core/plugins/Plugin.java | 3 --- .../core/plugins/PluginExecutionEngine.java | 7 ------- .../core/plugins/junit/GlobalTestListener.java | 13 ------------- ...rg.junit.platform.launcher.TestExecutionListener | 1 - .../web/infrastructure/BrowserLifecyclePlugin.java | 10 +--------- .../java/solutions/bellatrix/web/pages/WebPage.java | 1 + .../bellatrix/web/services/BrowserService.java | 6 +----- 8 files changed, 3 insertions(+), 44 deletions(-) delete mode 100644 bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/GlobalTestListener.java delete mode 100644 bellatrix.core/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener diff --git a/bellatrix.core/pom.xml b/bellatrix.core/pom.xml index 51e875c6..667a658e 100644 --- a/bellatrix.core/pom.xml +++ b/bellatrix.core/pom.xml @@ -158,11 +158,5 @@ jsoup 1.17.2 - - org.junit.platform - junit-platform-launcher - 1.11.0-M1 - compile - \ No newline at end of file diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java index b04da638..508b4b21 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java @@ -70,9 +70,6 @@ public void preAfterClass(Class type) { public void postAfterClass(Class type) { } - public void postAfterAll() { - } - public void afterClassFailed(Exception e) { } } diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java index ba914006..a4a65280 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java @@ -132,13 +132,6 @@ public static void postAfterClass(Class type) { } } - public static void postAfterAll() { - for (var currentObserver : PLUGINS) { - if (currentObserver != null) - currentObserver.postAfterAll(); - } - } - public static void afterClassFailed(Exception e) { for (var currentObserver : PLUGINS) { if (currentObserver != null) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/GlobalTestListener.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/GlobalTestListener.java deleted file mode 100644 index d388f91e..00000000 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/GlobalTestListener.java +++ /dev/null @@ -1,13 +0,0 @@ -package solutions.bellatrix.core.plugins.junit; - -import org.junit.platform.launcher.TestExecutionListener; -import org.junit.platform.launcher.TestPlan; -import solutions.bellatrix.core.plugins.PluginExecutionEngine; - -public class GlobalTestListener implements TestExecutionListener { - - @Override - public void testPlanExecutionFinished(TestPlan testPlan) { - PluginExecutionEngine.postAfterAll(); - } -} \ No newline at end of file diff --git a/bellatrix.core/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener b/bellatrix.core/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener deleted file mode 100644 index a068904a..00000000 --- a/bellatrix.core/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener +++ /dev/null @@ -1 +0,0 @@ -solutions.bellatrix.core.plugins.junit.GlobalTestListener \ No newline at end of file diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java index 9cc19941..f36893e2 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java @@ -49,9 +49,7 @@ public void preBeforeClass(Class type) { @Override public void postAfterClass(Class type) { - if(Objects.equals(ConfigurationService.get(WebSettings.class).getExecutionType(), "grid")) { - shutdownBrowser(); - } + shutdownBrowser(); super.preAfterClass(type); } @@ -84,13 +82,7 @@ public void postAfterTest(TestResult testResult, Method memberInfo, Throwable fa shutdownBrowser(); } - @Override - public void postAfterAll() { - shutdownBrowser(); - } - private void shutdownBrowser() { - Log.info("Shutting down driver..."); DriverService.close(); PREVIOUS_BROWSER_CONFIGURATION.remove(); } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/pages/WebPage.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/pages/WebPage.java index ff6b5b80..593c94c2 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/pages/WebPage.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/pages/WebPage.java @@ -13,6 +13,7 @@ package solutions.bellatrix.web.pages; +import solutions.bellatrix.web.infrastructure.Browser; import solutions.bellatrix.web.services.App; import solutions.bellatrix.web.services.BrowserService; import solutions.bellatrix.web.services.ComponentCreateService; diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java index c1900c38..22faa0c2 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java @@ -164,11 +164,7 @@ public void setItemInLocalStorage(String item, String value) { } public void clearLocalStorage() { - try { - ((JavascriptExecutor)getWrappedDriver()).executeScript("localStorage.clear()"); - } catch (Exception ex) { - Log.error("Failed to clear local storage because of error: %s".formatted(ex.getMessage())); - } + ((JavascriptExecutor)getWrappedDriver()).executeScript("localStorage.clear()"); } public List getBrowserLogs() { From 3eb792aa9937bfbbdf771a3cdde28407584f14a1 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Mon, 14 Oct 2024 17:23:02 +0300 Subject: [PATCH 17/19] Include number of ajax connections in error message --- .../solutions/bellatrix/web/services/BrowserService.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java index 22faa0c2..608eb861 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java @@ -38,6 +38,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.logging.Level; @@ -212,12 +213,13 @@ public void waitForAjax() { long ajaxTimeout = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getWaitForAjaxTimeout(); long sleepInterval = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getSleepInterval(); var javascriptExecutor = (JavascriptExecutor)getWrappedDriver(); + AtomicInteger ajaxConnections = new AtomicInteger(); try { Wait.retry(() -> { var numberOfAjaxConnections = javascriptExecutor.executeScript("return !isNaN(window.$openHTTPs) ? window.$openHTTPs : null"); if (Objects.nonNull(numberOfAjaxConnections)) { - int ajaxConnections = Integer.parseInt(numberOfAjaxConnections.toString()); - if (ajaxConnections > 0) { + ajaxConnections.set(Integer.parseInt(numberOfAjaxConnections.toString())); + if (ajaxConnections.get() > 0) { String message = "Waiting for %s Ajax Connections...".formatted(ajaxConnections); injectInfoNotificationToast(message); Log.info(message); @@ -233,7 +235,7 @@ public void waitForAjax() { TimeoutException.class); } catch (Exception e) { - var message = "Timed out waiting for Ajax connections."; + var message = "Timed out waiting for %s Ajax connections.".formatted(ajaxConnections.get()); Log.error(message); injectErrorNotificationToast(message); } From 98ca167ec8d4f6f7dc337132f00e01f39fe6120f Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Thu, 31 Oct 2024 17:01:54 +0200 Subject: [PATCH 18/19] fix issue with browser lifecycle --- .../bellatrix/web/infrastructure/BrowserLifecyclePlugin.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java index f36893e2..59a86f27 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/BrowserLifecyclePlugin.java @@ -109,10 +109,6 @@ private boolean shouldRestartBrowser() { return true; } else if (!previousConfiguration.equals(currentConfiguration)) { return true; - } else if (currentConfiguration.getLifecycle() == Lifecycle.REUSE_IF_STARTED) { - return false; - } else if (currentConfiguration.getLifecycle() == Lifecycle.RESTART_EVERY_TIME) { - return true; } else { return false; } From 5e3be3cc36df38cdeca908e1f6f49773153c3912 Mon Sep 17 00:00:00 2001 From: NikolayAvramov Date: Thu, 31 Oct 2024 17:20:04 +0200 Subject: [PATCH 19/19] revert singleton in app services --- .../java/solutions/bellatrix/web/services/App.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/App.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/App.java index da557850..c9cc0801 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/App.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/App.java @@ -22,31 +22,31 @@ public class App implements AutoCloseable { private boolean disposed = false; public NavigationService navigate() { - return SingletonFactory.getInstance(NavigationService.class); + return new NavigationService(); } public BrowserService browser() { - return SingletonFactory.getInstance(BrowserService.class); + return new BrowserService(); } public CookiesService cookies() { - return SingletonFactory.getInstance(CookiesService.class); + return new CookiesService(); } public DialogService dialogs() { - return SingletonFactory.getInstance(DialogService.class); + return new DialogService(); } public JavaScriptService script() { - return SingletonFactory.getInstance(JavaScriptService.class); + return new JavaScriptService(); } public ComponentCreateService create() { - return SingletonFactory.getInstance(ComponentCreateService.class); + return new ComponentCreateService(); } public ComponentWaitService waitFor() { - return SingletonFactory.getInstance(ComponentWaitService.class); + return new ComponentWaitService(); } public void addDriverOptions(String key, String value) {