diff --git a/serenity-model/src/test/java/net/thucydides/model/requirements/AggregateRequirementsTest.java b/serenity-model/src/test/java/net/thucydides/model/requirements/AggregateRequirementsTest.java new file mode 100644 index 000000000..00139ff7a --- /dev/null +++ b/serenity-model/src/test/java/net/thucydides/model/requirements/AggregateRequirementsTest.java @@ -0,0 +1,118 @@ +package net.thucydides.model.requirements; + +import net.serenitybdd.model.environment.ConfiguredEnvironment; +import net.thucydides.model.domain.RequirementCache; +import net.thucydides.model.requirements.model.Requirement; +import org.junit.jupiter.api.*; + +import java.io.File; +import java.nio.file.Path; +import java.util.List; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +@Disabled("Examples that demonstrate how Serenity/JS requirements aggregation should work") +class AggregateRequirementsTest { + + @BeforeEach + void setUp() { + ConfiguredEnvironment.reset(); + DefaultCapabilityTypes.instance().clear(); + RequirementCache.getInstance().clear(); + } + + @AfterAll + static void afterAll() { + ConfiguredEnvironment.reset(); + DefaultCapabilityTypes.instance().clear(); + RequirementCache.getInstance().clear(); + } + + @Nested + @DisplayName("when interpreting Serenity/JS test outcomes") + class SerenityJSTestOutcomes { + + @Test + void should_treat_files_in_a_flat_directory_structure_as_representing_features() { + + List requirements = requirementsFrom(pathTo("serenity-js/spec-0-levels")); + + System.out.println(requirements); + + assertThat(requirements).hasSize(1); + + Requirement feature = requirements.get(0); + + assertThat(feature.getChildren()).hasSize(0); + + assertThat(feature.getName()).isEqualTo("card_payment"); + assertThat(feature.getDisplayName()).isEqualTo("Card payment"); + assertThat(feature.getType()).isEqualTo("feature"); + } + } + + @Test + void should_treat_files_in_a_single_level_directory_structure_as_representing_capabilities_and_features() { + + List requirements = requirementsFrom(pathTo("serenity-js/spec-1-level")); + + System.out.println(requirements); + + assertThat(requirements).hasSize(1); + + Requirement capability = requirements.get(0); + assertThat(capability.getName()).isEqualTo("payments"); + assertThat(capability.getDisplayName()).isEqualTo("Payments"); + assertThat(capability.getType()).isEqualTo("capability"); + + assertThat(capability.getChildren()).hasSize(1); + + Requirement feature = capability.getChildren().get(0); + assertThat(feature.getName()).isEqualTo("card_payment"); + assertThat(feature.getDisplayName()).isEqualTo("Card payment"); + assertThat(feature.getType()).isEqualTo("feature"); + } + + @Test + void should_treat_files_in_a_two_level_directory_structure_as_representing_themes_capabilities_and_features() { + + List requirements = requirementsFrom(pathTo("serenity-js/spec-2-levels")); + + System.out.println(requirements); + + assertThat(requirements).hasSize(1); + + Requirement theme = requirements.get(0); + assertThat(theme.getName()).isEqualTo("ecommerce"); + assertThat(theme.getDisplayName()).isEqualTo("Ecommerce"); + assertThat(theme.getType()).isEqualTo("theme"); + + assertThat(theme.getChildren()).hasSize(1); + + Requirement capability = theme.getChildren().get(0); + assertThat(capability.getName()).isEqualTo("payments"); + assertThat(capability.getDisplayName()).isEqualTo("Payments"); + assertThat(capability.getType()).isEqualTo("capability"); + + assertThat(capability.getChildren()).hasSize(1); + + Requirement feature = capability.getChildren().get(0); + assertThat(feature.getName()).isEqualTo("card_payment"); + assertThat(feature.getDisplayName()).isEqualTo("Card payment"); + assertThat(feature.getType()).isEqualTo("feature"); + } + + private List requirementsFrom(Path exampleRootDirectory) { + + Path requirementsDirectory = exampleRootDirectory.resolve("spec"); + Path jsonOutcomesDirectory = exampleRootDirectory.resolve("outcomes"); + + Requirements requirements = new AggregateRequirements(jsonOutcomesDirectory, requirementsDirectory.toString()); + + return requirements.getRequirementsService().getRequirements(); + } + + private static Path pathTo(String resource) { + return new File(ClassLoader.getSystemClassLoader().getResource(resource).getFile()).toPath(); + } +} diff --git a/serenity-model/src/test/java/net/thucydides/model/requirements/WhenReadingRequirementsFromACollectionOfTestOutcomes.java b/serenity-model/src/test/java/net/thucydides/model/requirements/WhenReadingRequirementsFromACollectionOfTestOutcomes.java index 43e5708a9..9aa40ebe2 100644 --- a/serenity-model/src/test/java/net/thucydides/model/requirements/WhenReadingRequirementsFromACollectionOfTestOutcomes.java +++ b/serenity-model/src/test/java/net/thucydides/model/requirements/WhenReadingRequirementsFromACollectionOfTestOutcomes.java @@ -8,9 +8,7 @@ import net.thucydides.model.reports.TestOutcomeLoader; import net.thucydides.model.requirements.model.Requirement; import net.thucydides.model.util.EnvironmentVariables; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import java.io.File; import java.io.IOException; @@ -31,6 +29,15 @@ class WhenReadingRequirementsFromACollectionOfTestOutcomes { @BeforeEach void clearCaches() { + ConfiguredEnvironment.reset(); + DefaultCapabilityTypes.instance().clear(); + RequirementCache.getInstance().clear(); + } + + @AfterAll + static void afterAll() { + ConfiguredEnvironment.reset(); + DefaultCapabilityTypes.instance().clear(); RequirementCache.getInstance().clear(); } diff --git a/serenity-model/src/test/java/net/thucydides/model/requirements/WhenReadingRequirementsFromThePackageStructure.java b/serenity-model/src/test/java/net/thucydides/model/requirements/WhenReadingRequirementsFromThePackageStructure.java index 3414ce476..0ea178a87 100644 --- a/serenity-model/src/test/java/net/thucydides/model/requirements/WhenReadingRequirementsFromThePackageStructure.java +++ b/serenity-model/src/test/java/net/thucydides/model/requirements/WhenReadingRequirementsFromThePackageStructure.java @@ -1,10 +1,13 @@ package net.thucydides.model.requirements; import net.serenitybdd.model.environment.ConfiguredEnvironment; +import net.thucydides.model.domain.RequirementCache; +import net.thucydides.model.environment.MockEnvironmentVariables; import net.thucydides.model.requirements.model.Requirement; import net.thucydides.model.util.EnvironmentVariables; -import net.thucydides.model.environment.MockEnvironmentVariables; import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; import java.util.List; @@ -13,6 +16,20 @@ public class WhenReadingRequirementsFromThePackageStructure { + @BeforeEach + void clearCaches() { + ConfiguredEnvironment.reset(); + DefaultCapabilityTypes.instance().clear(); + RequirementCache.getInstance().clear(); + } + + @AfterAll + static void afterAll() { + ConfiguredEnvironment.reset(); + DefaultCapabilityTypes.instance().clear(); + RequirementCache.getInstance().clear(); + } + @Test public void should_read_requirements_from_a_one_level_package_hierarchy() { diff --git a/serenity-model/src/test/resources/serenity-js/spec-0-levels/outcomes/scenario-card-payment.json b/serenity-model/src/test/resources/serenity-js/spec-0-levels/outcomes/scenario-card-payment.json new file mode 100644 index 000000000..83c41464a --- /dev/null +++ b/serenity-model/src/test/resources/serenity-js/spec-0-levels/outcomes/scenario-card-payment.json @@ -0,0 +1,64 @@ +{ + "id": "checkout-should-allow-the-customer-to-pick-their-preferred-card;macos-23-1-0;chromium-120-0-6099-28", + "name": "Checkout should allow the customer to pick their preferred card", + "title": "Checkout should allow the customer to pick their preferred card", + "manual": false, + "testSteps": [ + { + "number": 1, + "description": "Tess starts with an empty basket", + "startTime": 1701531998839, + "children": [], + "reportData": [], + "screenshots": [], + "duration": 1897, + "result": "SUCCESS" + } + ], + "userStory": { + "id": "card-payment", + "storyName": "Card payment", + "displayName": "Card payment", + "path": "card_payment", + "type": "feature", + "narrative": "", + "pathElements": [ + { + "name": "card_payment", + "description": "" + } + ] + }, + "startTime": "2023-12-02T15:46:38.235Z", + "tags": [ + { + "name": "card_payment", + "type": "feature", + "displayName": "Card payment" + }, + { + "name": "macOS 23.1.0", + "type": "platform", + "platformName": "macOS", + "platformVersion": "23.1.0", + "displayName": "macOS 23.1.0" + }, + { + "name": "chromium 120.0.6099.28", + "type": "browser", + "browserName": "chromium", + "browserVersion": "120.0.6099.28", + "displayName": "chromium 120.0.6099.28" + } + ], + "featureTag": { + "name": "card_payment", + "type": "feature", + "displayName": "Card payment" + }, + "testSource": "Serenity/JS", + "context": "mac,chrome", + "driver": "chromium", + "result": "SUCCESS", + "duration": 3499 +} diff --git a/serenity-model/src/test/resources/serenity-js/spec-0-levels/spec/card_payment.spec.ts b/serenity-model/src/test/resources/serenity-js/spec-0-levels/spec/card_payment.spec.ts new file mode 100644 index 000000000..3426d707b --- /dev/null +++ b/serenity-model/src/test/resources/serenity-js/spec-0-levels/spec/card_payment.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from '@serenity-js/playwright-test' + +describe('Card payment', () => { + + describe('Checkout', () => { + it('should allow the customer to pick their preferred card', async ({ actor }) => { + // ... + }) + }) +}) diff --git a/serenity-model/src/test/resources/serenity-js/spec-1-level/outcomes/scenario-card-payment.json b/serenity-model/src/test/resources/serenity-js/spec-1-level/outcomes/scenario-card-payment.json new file mode 100644 index 000000000..b538c917b --- /dev/null +++ b/serenity-model/src/test/resources/serenity-js/spec-1-level/outcomes/scenario-card-payment.json @@ -0,0 +1,73 @@ +{ + "id": "checkout-should-allow-the-customer-to-pick-their-preferred-card;macos-23-1-0;chromium-120-0-6099-28", + "name": "Checkout should allow the customer to pick their preferred card", + "title": "Checkout should allow the customer to pick their preferred card", + "manual": false, + "testSteps": [ + { + "number": 1, + "description": "Tess starts with an empty basket", + "startTime": 1701531998839, + "children": [], + "reportData": [], + "screenshots": [], + "duration": 1897, + "result": "SUCCESS" + } + ], + "userStory": { + "id": "card-payment", + "storyName": "Card payment", + "displayName": "Card payment", + "path": "payments/card_payment", + "type": "feature", + "narrative": "", + "pathElements": [ + { + "name": "payments", + "description": "" + }, + { + "name": "card_payment", + "description": "" + } + ] + }, + "startTime": "2023-12-02T15:46:38.235Z", + "tags": [ + { + "name": "payments", + "type": "capability", + "displayName": "Payments" + }, + { + "name": "payments/card_payment", + "type": "feature", + "displayName": "Card payment" + }, + { + "name": "macOS 23.1.0", + "type": "platform", + "platformName": "macOS", + "platformVersion": "23.1.0", + "displayName": "macOS 23.1.0" + }, + { + "name": "chromium 120.0.6099.28", + "type": "browser", + "browserName": "chromium", + "browserVersion": "120.0.6099.28", + "displayName": "chromium 120.0.6099.28" + } + ], + "featureTag": { + "name": "payments/card_payment", + "type": "feature", + "displayName": "Card payment" + }, + "testSource": "Serenity/JS", + "context": "mac,chrome", + "driver": "chromium", + "result": "SUCCESS", + "duration": 3499 +} diff --git a/serenity-model/src/test/resources/serenity-js/spec-1-level/spec/payments/card_payment.spec.ts b/serenity-model/src/test/resources/serenity-js/spec-1-level/spec/payments/card_payment.spec.ts new file mode 100644 index 000000000..3426d707b --- /dev/null +++ b/serenity-model/src/test/resources/serenity-js/spec-1-level/spec/payments/card_payment.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from '@serenity-js/playwright-test' + +describe('Card payment', () => { + + describe('Checkout', () => { + it('should allow the customer to pick their preferred card', async ({ actor }) => { + // ... + }) + }) +}) diff --git a/serenity-model/src/test/resources/serenity-js/spec-2-levels/outcomes/scenario-card-payment.json b/serenity-model/src/test/resources/serenity-js/spec-2-levels/outcomes/scenario-card-payment.json new file mode 100644 index 000000000..a11b24e7f --- /dev/null +++ b/serenity-model/src/test/resources/serenity-js/spec-2-levels/outcomes/scenario-card-payment.json @@ -0,0 +1,82 @@ +{ + "id": "card_payment;checkout-should-allow-the-customer-to-pick-their-preferred-card;macos-23-1-0;chromium-120-0-6099-28", + "name": "Checkout should allow the customer to pick their preferred card", + "title": "Checkout should allow the customer to pick their preferred card", + "manual": false, + "testSteps": [ + { + "number": 1, + "description": "Tess starts with an empty basket", + "startTime": 1701531998839, + "children": [], + "reportData": [], + "screenshots": [], + "duration": 1897, + "result": "SUCCESS" + } + ], + "userStory": { + "id": "card-payment", + "storyName": "Card payment", + "displayName": "Card payment", + "path": "ecommerce/payments/card_payment", + "type": "feature", + "narrative": "", + "pathElements": [ + { + "name": "ecommerce", + "description": "" + }, + { + "name": "payments", + "description": "" + }, + { + "name": "card_payment", + "description": "" + } + ] + }, + "startTime": "2023-12-02T15:46:38.235Z", + "tags": [ + { + "name": "ecommerce", + "type": "theme", + "displayName": "Ecommerce" + }, + { + "name": "ecommerce/payments", + "type": "capability", + "displayName": "payments" + }, + { + "name": "payments/card_payment", + "type": "feature", + "displayName": "Card payment" + }, + { + "name": "macOS 23.1.0", + "type": "platform", + "platformName": "macOS", + "platformVersion": "23.1.0", + "displayName": "macOS 23.1.0" + }, + { + "name": "chromium 120.0.6099.28", + "type": "browser", + "browserName": "chromium", + "browserVersion": "120.0.6099.28", + "displayName": "chromium 120.0.6099.28" + } + ], + "featureTag": { + "name": "payments/card_payment", + "type": "feature", + "displayName": "Card payment" + }, + "testSource": "Serenity/JS", + "context": "mac,chrome", + "driver": "chromium", + "result": "SUCCESS", + "duration": 3499 +} diff --git a/serenity-model/src/test/resources/serenity-js/spec-2-levels/spec/ecommerce/payments/card_payment.spec.ts b/serenity-model/src/test/resources/serenity-js/spec-2-levels/spec/ecommerce/payments/card_payment.spec.ts new file mode 100644 index 000000000..3426d707b --- /dev/null +++ b/serenity-model/src/test/resources/serenity-js/spec-2-levels/spec/ecommerce/payments/card_payment.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from '@serenity-js/playwright-test' + +describe('Card payment', () => { + + describe('Checkout', () => { + it('should allow the customer to pick their preferred card', async ({ actor }) => { + // ... + }) + }) +})