diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..eded3ad83
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,36 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = space
+indent_size = 4
+charset = utf-8
+
+[*.java]
+ij_visual_guides = 180
+ij_java_align_multiline_throws_list = true
+ij_java_align_multiline_annotation_parameters = true
+ij_java_annotation_parameter_wrap = off
+ij_java_blank_lines_after_imports = 1
+ij_java_blank_lines_before_imports = 1
+ij_java_class_count_to_use_import_on_demand = 5
+ij_java_names_count_to_use_import_on_demand = 5
+ij_java_imports_layout = static java.**,static javax.**,$*,|,java.**,javax.**,*
+ij_java_insert_inner_class_imports = true
+ij_java_layout_static_imports_separately = false
+ij_java_method_call_chain_wrap = off
+ij_java_throws_list_wrap = off
+ij_java_block_comment_at_first_column = false
+ij_java_line_comment_at_first_column = false
+ij_java_line_comment_add_space = true
+
+[{*.yml,*.yaml}]
+indent_size = 2
+ij_continuation_indent_size = 2
+ij_yaml_keep_indents_on_empty_lines = false
+ij_yaml_keep_line_breaks = true
+ij_any_block_comment_at_first_column = false
+ij_java_line_comment_at_first_column = false
+ij_java_line_comment_add_space = true
diff --git a/README.md b/README.md
index 250c46519..44dee97d3 100644
--- a/README.md
+++ b/README.md
@@ -41,17 +41,12 @@
Spectrum is an **e2e test automation framework** that leverages **JUnit 6** and **Selenium 4** to provide these features automatically:
-* **Driver** management
-* **Auto-waiting** before interacting with elements, to **highly reduce flakiness**
-* **Html report** generation with the **execution video**
-* **Coverage report** generation by reading a **testbook**
+* **Driver** management with **auto-waiting**, to **highly reduce flakiness**
+* Generation of a **html report** with the **execution video**, **coverage** and **several additional reports**. All **fully customisable**
* **Mail/Slack notifications** with reports as attachments
-* It is fully configurable via a **declarative yaml file**
-* It provides **out-of-the-box defaults** to let you run tests with no additional configuration
-* It supports **browsers automation** via Selenium
-* It supports **mobile and desktop applications automation** via Appium
+* It is fully configurable via a **declarative yaml file**, providing **out-of-the-box defaults** to let you run tests with no additional configuration
+* It supports **browsers automation** via Selenium and **mobile and desktop automation** via Appium
* It supports **WebDriver BiDi** protocol
-* It generates **several additional reports** that are **fully customisable**
Spectrum manages all the boilerplate code, allowing you to focus on test logic:
you just need to write a JUnit test using the native Selenium API as you would do in a vanilla Selenium test,
@@ -73,37 +68,11 @@ https://github.com/giulong/spectrum/assets/27963644/fecee8f5-f6dc-4b47-81a3-514e
```
2. Run the `LoginFormIT` demo test.
-3. Check the report generated under `target/spectrum/reports`.
+3. Check the generated report, which opens automatically in your browser.
> ⚠️ Tests run on Chrome by default. As shown in the video above, you can change this with:
> `-Dspectrum.driver=firefox`, `-Dspectrum.driver=edge` or `-Dspectrum.driver=safari`
-If you like Spectrum, please consider giving it a GitHub Star ⭐
-
-# Usage
-
-If you'd rather add Spectrum manually to your project, you just need to add its dependency:
-
-## Maven
-
-```xml
-
-
- io.github.giulong
- spectrum
- 1.26.1
- test
-
-```
-
-## Gradle
-
-```gradle
-dependencies {
- testImplementation group: 'io.github.giulong', name: 'spectrum', version: '1.26.1'
-}
-```
-
Here's an overview of the project created by the archetype, along with the generated report and video:
@@ -114,6 +83,54 @@ You can also configure Spectrum to produce additional reports, such as summary a
+If you like Spectrum, please consider giving it a GitHub Star ⭐
+
+# Usage
+
+To start without the archetype, it's as simple as following these steps:
+
+1. Add the Spectrum dependency to your project, you can find the snippet for every build tool [here](https://central.sonatype.com/artifact/io.github.giulong/spectrum).
+
+ ```xml
+
+ io.github.giulong
+ spectrum
+ 1.26.1
+ test
+
+ ```
+
+2. Create the `HelloWorldIT` test class extending `SpectrumTest`:
+
+ ```java
+ import io.github.giulong.spectrum.SpectrumTest;
+ import org.junit.jupiter.api.Test;
+
+ public class HelloWorldIT extends SpectrumTest {
+
+ @Test
+ public void dummyTest() {
+ driver.get(configuration.getApplication().getBaseUrl());
+ }
+ }
+ ```
+
+3. create a basic `src/test/resources/configuration.yaml`:
+
+ ```yaml
+ application:
+ baseUrl: https://the-internet.herokuapp.com/ # Change this with your app's landing page
+
+ video: # video of the execution attached to the html report (will be empty since the test is doing nothing)
+ frames:
+ - autoBefore
+
+ extent:
+ openAtEnd: true # the html report will open automatically in your browser after the execution
+ ```
+
+4. Run the test!
+
# Contributing
Contributions to Spectrum are welcome! Please check out the [CONTRIBUTING.md](CONTRIBUTING.md)
diff --git a/docs/README.md b/docs/README.md
index 61addfa01..a181b8fd7 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -34,8 +34,8 @@ and **mobile and desktop applications** via [Appium](http://appium.io/docs/en/la
## Spectrum Archetype
-You should leverage the latest published version of the [Spectrum Archetype](https://mvnrepository.com/artifact/io.github.giulong/spectrum-archetype){:target="_blank"} to create a
-new project either via your IDE or by running this from command line:
+You should leverage the latest published version of the [Spectrum Archetype](https://central.sonatype.com/artifact/io.github.giulong/spectrum-archetype){:target="_blank"}
+to create a new project either via your IDE or by running this from command line:
{% include copyCode.html %}
@@ -48,10 +48,11 @@ mvn archetype:generate -DarchetypeGroupId=io.github.giulong -DarchetypeArtifactI
> official [archetype:generate docs](https://maven.apache.org/archetype/maven-archetype-plugin/generate-mojo.html){:target="_blank"}.
The project created contains a demo test you can immediately run.
-If you don't want to leverage the archetype, you can manually add the [Spectrum dependency](https://mvnrepository.com/artifact/io.github.giulong/spectrum){:target="_blank"} to your
-project:
-## Maven
+## Manual Configuration
+
+If you don't want to leverage the archetype, you can manually add the Spectrum dependency to your project.
+[Here](https://central.sonatype.com/artifact/io.github.giulong/spectrum){:target="_blank"} you can find the snippet for every build tool.
{% include copyCode.html %}
@@ -65,19 +66,7 @@ project:
```
-## Gradle
-
-{% include copyCode.html %}
-
-```gradle
-dependencies {
- testImplementation group: 'io.github.giulong', name: 'spectrum', version: '1.26.1'
-}
-```
-
-## Test creation
-
-In general, all you need to do is create a **JUnit 6** test class extending the `SpectrumTest` class:
+Then, you need to create a **JUnit 6** test class extending `SpectrumTest`:
{% include copyCode.html %}
@@ -94,7 +83,23 @@ public class HelloWorldIT extends SpectrumTest {
}
```
-After running it, you will find a html report in the `target/spectrum/reports` folder.
+As third and last step, you need create a basic `src/test/resources/configuration.yaml`:
+
+{% include copyCode.html %}
+
+```yaml
+application:
+ baseUrl: https://the-internet.herokuapp.com/ # Change this with your app's landing page
+
+video: # video of the execution attached to the html report (will be empty since the test is doing nothing)
+ frames:
+ - autoBefore
+
+extent:
+ openAtEnd: true # the html report will open automatically in your browser after the execution
+```
+
+Now you can run the test, and the generated report will automatically open in your browser.
> ⚠️ **Running with Maven**
> If you run tests with Maven, the name of your test classes should end with `IT` as in the example above (`HelloWorldIT`),
@@ -1580,6 +1585,9 @@ If you'd like to customise the js applied when highlighting, you have 2 options
JSON Schema really comes in handy when editing `configuration*.yaml`, since it allows you to have autocompletion
and a non-blocking validation (just warnings).
+
+
+
This is the list of the available schemas, be sure to pick the right one according to the version of Spectrum you are using.
> 💡 **Tip**
diff --git a/docs/assets/videos/json-schema.mov b/docs/assets/videos/json-schema.mov
new file mode 100644
index 000000000..9b37f6885
Binary files /dev/null and b/docs/assets/videos/json-schema.mov differ
diff --git a/pom.xml b/pom.xml
index 88c002cc8..7ddff1521 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
${revision}
pom
Spectrum Aggregate
- E2E Test Automation Framework
+ Modern Selenium Framework
https://github.com/giulong/spectrum
@@ -52,7 +52,7 @@
8.12.6
4.38.0
2.0.17
- 4.36.0
+ 4.37.0
@@ -195,7 +195,7 @@
ch.qos.logback
logback-classic
- 1.5.19
+ 1.5.20
org.codehaus.janino
@@ -250,7 +250,7 @@
net.datafaker
datafaker
- 2.5.1
+ 2.5.2
@@ -323,7 +323,7 @@
com.puppycrawl.tools
checkstyle
- 11.1.0
+ 12.1.0
com.github.sevntu-checkstyle
@@ -411,6 +411,7 @@
true
same_thread
concurrent
+ 5 m
@@ -525,10 +526,6 @@
.*]]>
${revision}]]>
-
- testImplementation group: 'io.github.giulong', name: 'spectrum', version: '.*'
- testImplementation group: 'io.github.giulong', name: 'spectrum', version: '${revision}'
-
@@ -545,10 +542,6 @@
.*]]>
${revision}]]>
-
- testImplementation group: 'io.github.giulong', name: 'spectrum', version: '.*'
- testImplementation group: 'io.github.giulong', name: 'spectrum', version: '${revision}'
-
diff --git a/spectrum/pom.xml b/spectrum/pom.xml
index cad716f5b..18496d782 100644
--- a/spectrum/pom.xml
+++ b/spectrum/pom.xml
@@ -12,7 +12,7 @@
spectrum
Spectrum
- E2E Test Automation Framework
+ Modern Selenium Framework
https://github.com/giulong/spectrum
@@ -215,7 +215,7 @@
org.jacoco
jacoco-maven-plugin
- 0.8.13
+ 0.8.14
io/github/giulong/spectrum/pojos/**/*
diff --git a/spectrum/src/main/java/io/github/giulong/spectrum/extensions/resolvers/bidi/BiDiTypeBasedParameterResolver.java b/spectrum/src/main/java/io/github/giulong/spectrum/extensions/resolvers/bidi/BiDiTypeBasedParameterResolver.java
index d1ab4226a..45fd2ae3a 100644
--- a/spectrum/src/main/java/io/github/giulong/spectrum/extensions/resolvers/bidi/BiDiTypeBasedParameterResolver.java
+++ b/spectrum/src/main/java/io/github/giulong/spectrum/extensions/resolvers/bidi/BiDiTypeBasedParameterResolver.java
@@ -1,12 +1,12 @@
package io.github.giulong.spectrum.extensions.resolvers.bidi;
+import io.github.giulong.spectrum.utils.Configuration;
import lombok.extern.slf4j.Slf4j;
import org.jspecify.annotations.NonNull;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.bidi.HasBiDi;
import static io.github.giulong.spectrum.extensions.resolvers.DriverResolver.DRIVER;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
@@ -14,6 +14,8 @@
@Slf4j
public abstract class BiDiTypeBasedParameterResolver implements ParameterResolver {
+ private final Configuration configuration = Configuration.getInstance();
+
abstract String getKey();
abstract Class getType();
@@ -31,7 +33,7 @@ public final T resolveParameter(@NonNull final ParameterContext parameterContext
final WebDriver driver = store.get(DRIVER, WebDriver.class);
final String key = getKey();
- if (!isBiDiEnabledFor(driver)) {
+ if (!configuration.getDrivers().isBiDi()) {
log.debug("BiDi disabled. Avoid resolving {}", key);
return null;
}
@@ -42,8 +44,4 @@ public final T resolveParameter(@NonNull final ParameterContext parameterContext
store.put(key, t);
return t;
}
-
- boolean isBiDiEnabledFor(final WebDriver driver) {
- return driver instanceof HasBiDi && ((HasBiDi) driver).maybeGetBiDi().isPresent();
- }
}
diff --git a/spectrum/src/test/java/io/github/giulong/spectrum/extensions/resolvers/bidi/BiDiTypeBasedParameterResolverTest.java b/spectrum/src/test/java/io/github/giulong/spectrum/extensions/resolvers/bidi/BiDiTypeBasedParameterResolverTest.java
index 91465db84..622833562 100644
--- a/spectrum/src/test/java/io/github/giulong/spectrum/extensions/resolvers/bidi/BiDiTypeBasedParameterResolverTest.java
+++ b/spectrum/src/test/java/io/github/giulong/spectrum/extensions/resolvers/bidi/BiDiTypeBasedParameterResolverTest.java
@@ -1,6 +1,9 @@
package io.github.giulong.spectrum.extensions.resolvers.bidi;
+import io.github.giulong.spectrum.utils.Configuration;
+import io.github.giulong.spectrum.utils.Reflections;
import lombok.Getter;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtensionContext;
@@ -11,21 +14,26 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.bidi.BiDi;
import org.openqa.selenium.bidi.HasBiDi;
import java.lang.reflect.Parameter;
-import java.util.Optional;
import java.util.stream.Stream;
import static io.github.giulong.spectrum.extensions.resolvers.DriverResolver.DRIVER;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.Mockito.*;
class BiDiTypeBasedParameterResolverTest {
+ @Mock
+ private Configuration configuration;
+
+ @Mock
+ private Configuration.Drivers drivers;
+
@Mock
private ParameterContext parameterContext;
@@ -35,9 +43,6 @@ class BiDiTypeBasedParameterResolverTest {
@Mock
private ExtensionContext.Store store;
- @Mock
- private BiDi biDi;
-
@Mock
private WebDriver driver;
@@ -50,6 +55,11 @@ class BiDiTypeBasedParameterResolverTest {
@InjectMocks
private DummyBiDiTypeBasedParameterResolver biDiTypeBasedParameterResolver;
+ @BeforeEach
+ void beforeEach() {
+ Reflections.setField("configuration", biDiTypeBasedParameterResolver, configuration);
+ }
+
@DisplayName("supportsParameter should check if the provided parameter type matches the concrete instance type")
@ParameterizedTest(name = "with concrete type {0} we expect {1}")
@MethodSource("valuesProvider")
@@ -74,6 +84,8 @@ static Stream valuesProvider() {
void resolveParameter() {
when(context.getStore(GLOBAL)).thenReturn(store);
when(store.get(DRIVER, WebDriver.class)).thenReturn(driver);
+ when(configuration.getDrivers()).thenReturn(drivers);
+ when(drivers.isBiDi()).thenReturn(false);
assertNull(biDiTypeBasedParameterResolver.resolveParameter(parameterContext, context));
@@ -88,7 +100,8 @@ void resolveParameter() {
void resolveParameterBiDi() {
when(context.getStore(GLOBAL)).thenReturn(store);
when(store.get(DRIVER, WebDriver.class)).thenReturn(bidiDriver);
- when(((HasBiDi) bidiDriver).maybeGetBiDi()).thenReturn(Optional.of(biDi));
+ when(configuration.getDrivers()).thenReturn(drivers);
+ when(drivers.isBiDi()).thenReturn(true);
assertEquals("parameter", biDiTypeBasedParameterResolver.resolveParameter(parameterContext, context));
@@ -99,28 +112,6 @@ void resolveParameterBiDi() {
verifyNoMoreInteractions(driver);
}
- @Test
- @DisplayName("isBiDiEnabledFor should return false if the provided driver doesn't support BiDi")
- void isBiDiEnabledForFalse() {
- assertFalse(biDiTypeBasedParameterResolver.isBiDiEnabledFor(driver));
- }
-
- @Test
- @DisplayName("isBiDiEnabledFor should return false if the provided driver supports BiDi but the optional is empty")
- void isBiDiEnabledForEmpty() {
- when(((HasBiDi) bidiDriver).maybeGetBiDi()).thenReturn(Optional.empty());
-
- assertFalse(biDiTypeBasedParameterResolver.isBiDiEnabledFor(bidiDriver));
- }
-
- @Test
- @DisplayName("isBiDiEnabledFor should return true if the provided driver supports BiDi")
- void isBiDiEnabledFor() {
- when(((HasBiDi) bidiDriver).maybeGetBiDi()).thenReturn(Optional.of(biDi));
-
- assertTrue(biDiTypeBasedParameterResolver.isBiDiEnabledFor(bidiDriver));
- }
-
@Getter
private static final class DummyBiDiTypeBasedParameterResolver extends BiDiTypeBasedParameterResolver {