Skip to content

Commit

Permalink
fix(serenity-cli): Fixed merging test outcome reports with requiremen…
Browse files Browse the repository at this point in the history
…ts with narratives (#3395)

* Requirements with narratives are now correctly merged with outcomes of tests from those directories

* Updated the tests

* Corrected a typo

* Updated tests and cleaned up the code

* Removed duplicate dependency declaration

* Corrected parent pom version

* Attempting to fix the smoke tests

* Use Serenity/JS instance of the TodoMVC app for smoke tests

* Migrated the page object tests

* Fixed selectors
  • Loading branch information
jan-molak authored Feb 3, 2024
1 parent 2595bcb commit a5a6214
Show file tree
Hide file tree
Showing 15 changed files with 52 additions and 51 deletions.
6 changes: 0 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -460,12 +460,6 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<distributionManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class WhenAssociatingATestOutcomeWithARequirementInAFeatureFile extends Specific
def testOutcome = TestOutcome.forTestInStory("someTest", Story.withIdAndPath("PlantPotatoes","Plant potatoes","grow_potatoes/grow_new_potatoes/PlantPotatoes.story"))
then:
capabilityProvider.getParentRequirementOf(testOutcome).isPresent()
capabilityProvider.getParentRequirementOf(testOutcome).get().name == "Plant Potatoes"
capabilityProvider.getParentRequirementOf(testOutcome).get().name == "PlantPotatoes"
capabilityProvider.getParentRequirementOf(testOutcome).get().displayName == "Plant Potatoes"
}

def "Should not find the requirement if there are no matching requirements for a tag"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class WhenGeneratingRequirementsReportData extends Specification {
RequirementsOutcomes outcomes = requirmentsOutcomeFactory.buildRequirementsOutcomesFrom(noTestOutcomes)
then: "all the known capabilities should be listed"
def requirementsNames = outcomes.requirementOutcomes.collect {it.requirement.name}
requirementsNames == ["grow cucumbers", "Grow potatoes", "Grow wheat", "raise_chickens", "Apples", "Nice zucchinis", "Potatoes"]
requirementsNames == ["grow cucumbers", "grow_potatoes", "grow_wheat", "raise_chickens", "Apples", "Nice zucchinis", "Potatoes"]
and: "the display name should be obtained from the narrative file where present"
def requirementsDisplayNames = outcomes.requirementOutcomes.collect {it.requirement.displayName}
requirementsDisplayNames == ["Grow cucumbers", "Grow potatoes", "Grow wheat", "Raise chickens", "Apples", "Nice zucchinis", "Potatoes title"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ class WhenLoadingRequirementOutcomesFromTheFileSystem extends Specification {
capabilityNames == ["Grow cucumbers", "Grow potatoes", "Grow wheat", "Raise chickens"]
and: "the child requirements should be found"
def growCucumbers = capabilities.get(0)
def cucumberFeatures = growCucumbers.children.collect { it.name }
cucumberFeatures == ["Grow green cucumbers"]

def cucumberFeatureNames = growCucumbers.children.collect { it.name }
cucumberFeatureNames == ["grow green cucumbers"]
}

def "Should be able to load issues from the default directory structure"() {
Expand All @@ -78,7 +79,8 @@ class WhenLoadingRequirementOutcomesFromTheFileSystem extends Specification {
then: "the capability should be found"
def potatoeGrowingCapability = capabilities.get(1)
then: "the title should be a human-readable version of the directory name"
potatoeGrowingCapability.name == "Grow potatoes"
potatoeGrowingCapability.name == "grow_potatoes"
potatoeGrowingCapability.displayName == "Grow potatoes"
}

def "Should support feature files in the requirements directory"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,8 @@ public void should_get_requirement_from_story_with_narrative_if_present() {
Optional<Requirement> requirement = tagProvider.getParentRequirementOf(testOutcome);

assertThat(requirement.isPresent(), is(true));
assertThat(requirement.get().getName(), is("Plant Potatoes"));
assertThat(requirement.get().getName(), is("PlantPotatoes"));
assertThat(requirement.get().getDisplayName(), is("Plant Potatoes"));
assertThat(requirement.get().getNarrative().getText(), containsString("As a farmer"));
assertThat(requirement.get().getNarrative().getText(), containsString("I want to plant potatoes"));
assertThat(requirement.get().getNarrative().getText(), containsString("So that I can harvest them later on"));
Expand All @@ -374,7 +375,8 @@ public void should_get_requirement_from_feature_with_narrative_if_present() {
Optional<Requirement> requirement = tagProvider.getParentRequirementOf(testOutcome);

assertThat(requirement.isPresent(), is(true));
assertThat(requirement.get().getName(), is("Watering the potatoes"));
assertThat(requirement.get().getName(), is("WaterPotatoes"));
assertThat(requirement.get().getDisplayName(), is("Watering the potatoes"));
assertThat(requirement.get().getNarrative().getText(), containsString("As a farmer"));
assertThat(requirement.get().getNarrative().getText(), containsString("I want to plant potatoes"));
assertThat(requirement.get().getNarrative().getText(), containsString("So that I can harvest them later on"));
Expand All @@ -389,7 +391,8 @@ public void should_get_requirement_from_feature_in_a_foreign_language() throws U

Requirement norwegenRequirement = tagProvider.readRequirementsFromStoryOrFeatureFile(norwegenfeatureFile).get();

assertThat(norwegenRequirement.getName(), is("Summering"));
assertThat(norwegenRequirement.getName(), is("PlantScandanavianPotatoes"));
assertThat(norwegenRequirement.getDisplayName(), is("Summering"));
}

@Test
Expand All @@ -401,7 +404,8 @@ public void should_get_requirement_from_feature_file_using_the_title_of_the_feat

Requirement featureRequirement = tagProvider.readRequirementsFromStoryOrFeatureFile(featureFile).get();

assertThat(featureRequirement.getName(), is("Planting some potatoes"));
assertThat(featureRequirement.getName(), is("PlantPotatoes"));
assertThat(featureRequirement.getDisplayName(), is("Planting some potatoes"));
}

@Test
Expand Down Expand Up @@ -429,7 +433,8 @@ public void should_match_requirements_path_for_serenity_js_outcomes() throws URI
Optional<Requirement> requirement = tagProvider.getParentRequirementOf(testOutcome);

assertThat(requirement.isPresent(), is(true));
assertThat(requirement.get().getName(), is("Add new items to the todo list"));
assertThat(requirement.get().getName(), is("add_new_items"));
assertThat(requirement.get().getDisplayName(), is("Add new items to the todo list"));
assertThat(requirement.get().getParent(), is("record_todos"));
}

Expand All @@ -448,7 +453,8 @@ public void should_match_requirements_path_for_serenity_js_outcomes_with_long_pa
Optional<Requirement> requirement = tagProvider.getParentRequirementOf(testOutcome);

assertThat(requirement.isPresent(), is(true));
assertThat(requirement.get().getName(), is("Add new items to the todo list"));
assertThat(requirement.get().getName(), is("add_new_items"));
assertThat(requirement.get().getDisplayName(), is("Add new items to the todo list"));
assertThat(requirement.get().getParent(), is("record_todos"));
}

Expand All @@ -460,10 +466,9 @@ public void should_match_requirements_path_for_cucumber_jvm_outcomes() throws UR
for(TestOutcome outcome : TestOutcomeStream.testOutcomesInDirectory(Paths.get(Resources.getResource("serenity-cucumber/json").toURI()))) {
Optional<Requirement> feature = tagProvider.getParentRequirementOf(outcome);
assertThat(feature.isPresent(), is(true));
assertThat(feature.get().getName(), equalToIgnoringCase(outcome.getFeatureTag().get().getName()));
assertThat(feature.get().getName(), equalToIgnoringCase(outcome.getPath().substring(0, outcome.getPath().lastIndexOf("."))));
assertThat(feature.get().getDisplayName(), equalToIgnoringCase(outcome.getFeatureTag().get().getName()));
assertThat(feature.get().getParent(), not(isEmptyString()));
}
}

}

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Grow potatoes

Narrative:
In order to let my country eat chips
As a farmer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
Expand Down Expand Up @@ -592,7 +591,7 @@ public Requirement readRequirementFrom(File requirementDirectory) {

return requirementWithNarrative(
requirementDirectory,
humanReadableVersionOf(requirementDirectory.getName()),
requirementDirectory.getName(),
requirementNarrative.get()
);
}
Expand All @@ -612,12 +611,17 @@ public Optional<Requirement> readRequirementsFromStoryOrFeatureFile(File storyFi
java.util.Optional<RequirementDefinition> narrative = (type == FeatureType.STORY) ? loadFromStoryFile(storyFile) : loadFromFeatureFile(storyFile);

String storyPath = requirementsConfiguration.relativePathOfFeatureFile(storyFile);
String storyName = storyNameFrom(narrative, type, storyFile);
String storyFileName = storyNameFrom(storyFile);
String displayName = storyDisplayNameFrom(narrative, type, storyFile);

Requirement requirement;
if (narrative.isPresent()) {
requirement = leafRequirementWithNarrative(storyName,
requirement = leafRequirementWithNarrative(
storyFileName,
displayName,
storyPath,
narrative.get()).withType(type.toString());
narrative.get()
).withType(type.toString());

if (narrative.get().background().isPresent()) {
requirement = requirement.withBackground(narrative.get().background().get());
Expand All @@ -626,7 +630,7 @@ public Optional<Requirement> readRequirementsFromStoryOrFeatureFile(File storyFi
requirement = requirement.withNoScenarios();
}
} else {
requirement = storyNamed(storyName, storyPath).withType(type.toString());
requirement = storyNamed(storyFileName, displayName, storyPath).withType(type.toString());
}

return Optional.of(requirement.definedInFile(storyFile));
Expand All @@ -636,7 +640,11 @@ public Optional<Requirement> readRequirementsFromStoryOrFeatureFile(File storyFi
}
}

private String storyNameFrom(java.util.Optional<RequirementDefinition> narrative, FeatureType type, File storyFile) {
private String storyNameFrom(File storyFile) {
return storyFile.getName().substring(0, storyFile.getName().lastIndexOf("."));
}

private String storyDisplayNameFrom(java.util.Optional<RequirementDefinition> narrative, FeatureType type, File storyFile) {
if (narrative.isPresent() && isNotBlank(narrative.get().getTitle().orElse(""))) {
return narrative.get().getTitle().get();
} else {
Expand Down Expand Up @@ -749,19 +757,19 @@ private String relativeDirectoryOf(String path) {
}
}

private Requirement storyNamed(String storyName, String path) {
private Requirement storyNamed(String storyName, String displayName, String path) {
String shortName = humanReadableVersionOf(storyName);
String relativePath = new FeatureFilePath(environmentVariables).relativePathFor(path);
return Requirement.named(shortName)
.withId(relativePath)
.withOptionalDisplayName(displayName)
.withType(STORY_EXTENSION)
.withNarrative(shortName)
.withParent(parentFrom(relativePath))
.withPath(relativePath);
}

private Requirement leafRequirementWithNarrative(String requirementName, String path, RequirementDefinition requirementNarrative) {
String displayName = getTitleFromNarrativeOrDirectoryName(requirementNarrative, requirementName);
private Requirement leafRequirementWithNarrative(String requirementName, String displayName, String path, RequirementDefinition requirementNarrative) {
String cardNumber = requirementNarrative.getCardNumber().orElse(null);
String type = requirementNarrative.getType();
List<String> releaseVersions = requirementNarrative.getVersionNumbers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,6 @@ private Requirement nonLeafRequirementFrom(PathElements relativePath, int maxReq
.withParent(parentPath);
}

// fixme: duplicated from AbstractRequirementsTagProvider
// as it is not the parent of this class (should it be?).
// This is to make the discovered requirements compatible with the results
// of the FileSystemRequirementsTagProvider.
protected String humanReadableVersionOf(String name) {
String underscoredName = Inflector.getInstance().underscore(name);
return Inflector.getInstance().humanize(underscoredName);
}

private PathElements relativePathFrom(PathElements pathElements) {
List<String> rootPackageElements = rootPackageElements();
List<PathElement> relativePathElements = new ArrayList<>(pathElements);
Expand Down
2 changes: 1 addition & 1 deletion serenity-smoketests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>serenity-bdd</artifactId>
<groupId>net.serenity-bdd</groupId>
<version>4.0.40-SNAPSHOT</version>
<version>4.0.47-SNAPSHOT</version>
</parent>
<artifactId>serenity-smoketests</artifactId>
<packaging>jar</packaging>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@DefaultUrl("http://todomvc.com/examples/angularjs/#/")
@DefaultUrl("https://todo-app.serenity-js.org/#/")
public class TodoListPage extends PageObject {

// -----------------------------------------------------------------------------------------------------------------
Expand All @@ -26,7 +26,7 @@ public class TodoListPage extends PageObject {
private static final String NEW_TODO_INPUT_FIELD = ".new-todo";
private static final String ITEM_ROW = "//div[@class='view' and contains(.,'%s')]";
private static final String ITEM_ROW_LABEL = "//label[contains(.,'%s')]";
private static final String COMPLETE_TICKBOX = ".//input[@ng-model='todo.completed']";
private static final String COMPLETE_TICKBOX = ".//input[@type='checkbox']";
private static final String DELETE_BUTTON = "//button[@class='destroy']";
private static final String FILTERS = ".filters";
private static final String SELECTED_FILTER = ".filters li .selected";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.annotations.DefaultUrl;

@DefaultUrl("http://todomvc.com/")
@DefaultUrl("https://todo-app.serenity-js.org/#/")
public class TodoMVCHomePage extends PageObject {}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public void should_see_that_displayed_items_do_not_contain(String... items) {

@Step
public void should_see_the_correct_website_title() {
assertThat(todoListPage.getTitle(), is("AngularJS • TodoMVC"));
assertThat(todoListPage.getTitle(), is("Serenity/JS TodoApp"));
}

@Step
Expand All @@ -142,7 +142,6 @@ public void should_see_the_correct_application_heading() {

@Step
public void should_see_the_about_section() {
assertThat(todoListPage.footer(), containsString("Credits"));
assertThat(todoListPage.footer(), containsString("Serenity/JS TodoApp, based on TodoMVC"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,4 @@ public void shouldBeAbleToAddANewTodoItem() {
james.should_see_the_correct_application_heading();
james.should_see_the_about_section();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ public void should_be_able_to_identify_the_application() {

then(james).should(
seeThat(Application.information(),
displays("title",equalTo("AngularJS • TodoMVC")),
displays("title",equalTo("Serenity/JS TodoApp")),
displays("heading",equalTo("todos")),
displays("about", containsString("Credits"))
displays("about", containsString("Serenity/JS TodoApp, based on TodoMVC"))
)
);
}
Expand Down
4 changes: 2 additions & 2 deletions serenity-smoketests/src/test/resources/serenity.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
webdriver {
base.url = "http://todomvc.com/examples/angularjs/#/"
base.url = "https://todo-app.serenity-js.org/#/"
autodownload = true
}

Expand All @@ -15,7 +15,7 @@ serenity {
restart.browser.for.each = scenario
}

home.page = "http://todomvc.com/examples/angularjs/#/"
home.page = "https://todo-app.serenity-js.org/#/"

//drivers {
// windows {
Expand Down

0 comments on commit a5a6214

Please sign in to comment.