From be90df19a2ba3e9d9d32929e9c5a78919317141f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4fer?= Date: Sun, 3 Jul 2016 00:49:46 +0200 Subject: [PATCH] implement new attribute showInNavigation for the IsTag annotation (fixes #211) --- CHANGELOG.md | 8 +++++ .../com/tngtech/jgiven/annotation/IsTag.java | 23 +++++++++----- .../jgiven/config/TagConfiguration.java | 23 +++++++++++--- .../jgiven/impl/ScenarioModelBuilder.java | 18 ++++++----- .../com/tngtech/jgiven/report/model/Tag.java | 29 +++++++++++++---- .../tags/TagHierarchyExampleTest.java | 1 + .../tags/TagThatIsNotVisibleInNavigation.java | 14 +++++++++ jgiven-html5-report/src/app/lib/tagService.js | 28 +++++++++-------- .../jgiven/junit/TagAnnotationTest.java | 31 +++++++++++++++++++ 9 files changed, 135 insertions(+), 40 deletions(-) create mode 100644 jgiven-examples/src/test/java/com/tngtech/jgiven/examples/tags/TagThatIsNotVisibleInNavigation.java create mode 100644 jgiven-junit/src/test/java/com/tngtech/jgiven/junit/TagAnnotationTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index f64b6d9411..a831e675f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,15 @@ # v0.12.0 +## New Features + * Allow multiple formatter annotations on arguments, e.g., "@Quoted @YesNo", see [#204](https://github.com/TNG/JGiven/issues/204). * Added a new comment() method to provide further information on specific step method invocations, see [#50](https://github.com/TNG/JGiven/issues/50). +* Steps can now have multiple attachments [#194](https://github.com/TNG/JGiven/issues/194). +* Tags can now be hidden from the navigation bar in the HTML report by setting the `showInNavigation` attribute to `false` [#211](https://github.com/TNG/JGiven/issues/211). + +## Breaking Changes in the JSON model + +* Due to the introduction of multiple attachments per step, the JSON model had to be changed in an backwards-incompatible way. Instead of a single field `attachment` that holds a single attachment object, a step has now an `attachments` field that holds an array of attachment objects. # v0.11.4 diff --git a/jgiven-core/src/main/java/com/tngtech/jgiven/annotation/IsTag.java b/jgiven-core/src/main/java/com/tngtech/jgiven/annotation/IsTag.java index df3f478cd7..a131fd639a 100644 --- a/jgiven-core/src/main/java/com/tngtech/jgiven/annotation/IsTag.java +++ b/jgiven-core/src/main/java/com/tngtech/jgiven/annotation/IsTag.java @@ -1,13 +1,13 @@ package com.tngtech.jgiven.annotation; +import com.tngtech.jgiven.impl.tag.DefaultTagDescriptionGenerator; +import com.tngtech.jgiven.impl.tag.DefaultTagHrefGenerator; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.tngtech.jgiven.impl.tag.DefaultTagDescriptionGenerator; -import com.tngtech.jgiven.impl.tag.DefaultTagHrefGenerator; - /** * Marks an annotation to be used as a tag in JGiven reports. * The name and a possible value will be stored. @@ -68,7 +68,7 @@ *

* If this attribute is set, the {@link #description()} attribute is ignored. *

- * + * * @since 0.7.0 */ Class descriptionGenerator() default DefaultTagDescriptionGenerator.class; @@ -102,7 +102,7 @@ *

* Non-HTML reports ignore this attribute *

- * + * * @since 0.7.2 */ String cssClass() default ""; @@ -120,7 +120,7 @@ * This attribute is for simple use cases. * For advanced styling options use the {@link #cssClass()} or {@link #style()} attributes instead. *

- * + * * @since 0.7.2 */ String color() default ""; @@ -135,14 +135,14 @@ *

* Non-HTML reports ignore this attribute *

- * + * * @since 0.8.0 */ String style() default ""; /** * An optional href of the tag that will appear in the generated report. - * + * * @since 0.9.5 */ String href() default ""; @@ -162,4 +162,11 @@ */ Class hrefGenerator() default DefaultTagHrefGenerator.class; + /** + * Whether the tag should be shown in the navigation part of the report + * + * @since 0.12.0 + */ + boolean showInNavigation() default true; + } diff --git a/jgiven-core/src/main/java/com/tngtech/jgiven/config/TagConfiguration.java b/jgiven-core/src/main/java/com/tngtech/jgiven/config/TagConfiguration.java index 1dd3f53e57..fb021112f2 100644 --- a/jgiven-core/src/main/java/com/tngtech/jgiven/config/TagConfiguration.java +++ b/jgiven-core/src/main/java/com/tngtech/jgiven/config/TagConfiguration.java @@ -1,17 +1,17 @@ package com.tngtech.jgiven.config; -import java.lang.annotation.Annotation; -import java.util.List; - import com.google.common.collect.Lists; +import com.tngtech.jgiven.annotation.TagDescriptionGenerator; import com.tngtech.jgiven.annotation.TagHrefGenerator; import com.tngtech.jgiven.impl.tag.DefaultTagDescriptionGenerator; -import com.tngtech.jgiven.annotation.TagDescriptionGenerator; import com.tngtech.jgiven.impl.tag.DefaultTagHrefGenerator; +import java.lang.annotation.Annotation; +import java.util.List; + /** * Represents the configuration of a tag. - * + * * @see com.tngtech.jgiven.annotation.IsTag for a documentation of the different values. */ public class TagConfiguration { @@ -29,6 +29,7 @@ public class TagConfiguration { private List tags = Lists.newArrayList(); private String href = ""; private Class hrefGenerator = DefaultTagHrefGenerator.class; + private boolean showInNavigation = true; public TagConfiguration( Class tagAnnotation ) { this.annotationType = tagAnnotation.getSimpleName(); @@ -119,6 +120,11 @@ public Builder hrefGenerator( Class hrefGenerator ) return this; } + public Builder showInNavigation( boolean value ) { + configuration.showInNavigation = value; + return this; + } + public TagConfiguration build() { return configuration; } @@ -226,4 +232,11 @@ public Class getHrefGenerator() { return hrefGenerator; } + /** + * @see com.tngtech.jgiven.annotation.IsTag#showInNavigation + */ + public boolean showInNavigation() { + return showInNavigation; + } + } diff --git a/jgiven-core/src/main/java/com/tngtech/jgiven/impl/ScenarioModelBuilder.java b/jgiven-core/src/main/java/com/tngtech/jgiven/impl/ScenarioModelBuilder.java index be414d34e5..4c6999d14d 100644 --- a/jgiven-core/src/main/java/com/tngtech/jgiven/impl/ScenarioModelBuilder.java +++ b/jgiven-core/src/main/java/com/tngtech/jgiven/impl/ScenarioModelBuilder.java @@ -1,12 +1,5 @@ package com.tngtech.jgiven.impl; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.*; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.common.base.CaseFormat; import com.google.common.base.Strings; import com.google.common.collect.ImmutableSet; @@ -26,6 +19,12 @@ import com.tngtech.jgiven.impl.util.ReflectionUtil; import com.tngtech.jgiven.impl.util.WordUtil; import com.tngtech.jgiven.report.model.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.*; public class ScenarioModelBuilder implements ScenarioListener { private static final Logger log = LoggerFactory.getLogger( ScenarioModelBuilder.class ); @@ -412,6 +411,8 @@ public List toTags( Annotation annotation ) { tag.setPrependType( true ); } + tag.setShowInNavigation( tagConfig.showInNavigation() ); + if( !Strings.isNullOrEmpty( tagConfig.getCssClass() ) ) { tag.setCssClass( tagConfig.getCssClass() ); } @@ -471,7 +472,8 @@ public TagConfiguration fromIsTag( IsTag isTag, Annotation annotation ) { .explodeArray( isTag.explodeArray() ).ignoreValue( isTag.ignoreValue() ).prependType( isTag.prependType() ).name( name ) .descriptionGenerator( isTag.descriptionGenerator() ).cssClass( isTag.cssClass() ).color( isTag.color() ) .style( isTag.style() ).tags( getTagNames( isTag, annotation ) ) - .href( isTag.href() ).hrefGenerator( isTag.hrefGenerator() ).build(); + .href( isTag.href() ).hrefGenerator( isTag.hrefGenerator() ) + .showInNavigation( isTag.showInNavigation() ).build(); } diff --git a/jgiven-core/src/main/java/com/tngtech/jgiven/report/model/Tag.java b/jgiven-core/src/main/java/com/tngtech/jgiven/report/model/Tag.java index b2f264e5f1..bfa41b5f90 100644 --- a/jgiven-core/src/main/java/com/tngtech/jgiven/report/model/Tag.java +++ b/jgiven-core/src/main/java/com/tngtech/jgiven/report/model/Tag.java @@ -1,12 +1,12 @@ package com.tngtech.jgiven.report.model; -import java.util.Collections; -import java.util.List; - import com.google.common.base.Joiner; import com.google.common.base.Objects; import com.google.common.collect.Lists; +import java.util.Collections; +import java.util.List; + /** * A tag represents a Java annotation of a scenario-test. */ @@ -35,7 +35,7 @@ public class Tag { /** * Whether the type should be prepended in the report. *

- * Is either {@code true} or {@code null} + * Is either {@code true} or {@code null} */ private Boolean prependType; @@ -68,6 +68,14 @@ public class Tag { */ private String href; + /** + * Whether the tag should appear in the navigation part of the report + *

+ * Is either {@code true} or {@code null} + */ + private Boolean hideInNav; + private boolean shownInNavigation; + public Tag( String type ) { this.type = type; } @@ -134,7 +142,7 @@ public String getHref() { return href; } - public void setHref(String href) { + public void setHref( String href ) { this.href = href; } @@ -162,6 +170,10 @@ public Tag setPrependType( boolean prependType ) { return this; } + public void setShowInNavigation( boolean show ) { + this.hideInNav = show ? null : true; + } + @Override public String toString() { if( value != null ) { @@ -213,7 +225,7 @@ public boolean equals( Object obj ) { /** * Returns a string representation where all non-alphanumeric characters are replaced with an underline (_). * In addition, the result is cut-off at a length of 255 characters. - * + * * @return a string representation without special characters */ public String toEscapedString() { @@ -235,6 +247,10 @@ public String getType() { return type; } + public boolean getShownInNavigation() { + return shownInNavigation; + } + public List getTags() { if( tags == null ) { return Collections.emptyList(); @@ -257,6 +273,7 @@ public Tag copy() { tag.prependType = this.prependType; tag.tags = this.tags; tag.href = this.href; + tag.hideInNav = this.hideInNav; return tag; } diff --git a/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/tags/TagHierarchyExampleTest.java b/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/tags/TagHierarchyExampleTest.java index 3c7cb3e73e..31a07ec41b 100644 --- a/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/tags/TagHierarchyExampleTest.java +++ b/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/tags/TagHierarchyExampleTest.java @@ -22,6 +22,7 @@ public void tags_can_form_a_hierarchy() { then().the_tags_appear_in_a_hierarchy(); } + @TagThatIsNotVisibleInNavigation @AnotherExampleSubCategory @Test public void parent_tags_can_have_values() { diff --git a/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/tags/TagThatIsNotVisibleInNavigation.java b/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/tags/TagThatIsNotVisibleInNavigation.java new file mode 100644 index 0000000000..18d43656a1 --- /dev/null +++ b/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/tags/TagThatIsNotVisibleInNavigation.java @@ -0,0 +1,14 @@ +package com.tngtech.jgiven.examples.tags; + +import com.tngtech.jgiven.annotation.IsTag; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Used to be able to sort scenarios in the HMTL5 report + */ +@IsTag( showInNavigation = false ) +@Retention( RetentionPolicy.RUNTIME ) +public @interface TagThatIsNotVisibleInNavigation { +} diff --git a/jgiven-html5-report/src/app/lib/tagService.js b/jgiven-html5-report/src/app/lib/tagService.js index a0955034e0..9fc941b474 100644 --- a/jgiven-html5-report/src/app/lib/tagService.js +++ b/jgiven-html5-report/src/app/lib/tagService.js @@ -31,7 +31,7 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { * where a tag entry contains the tag definition and the list of scenarios * that are tagged with that tag */ - function getTagScenarioMap(scenarios) { + function getTagScenarioMap (scenarios) { var tagScenarioMap = {}; _.forEach(scenarios, function (testCase) { _.forEach(testCase.scenarios, function (scenario) { @@ -43,7 +43,7 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { var tag = addEntry(tagId).tag; scenario.tags.push(tag); - function addEntry(tagId) { + function addEntry (tagId) { var tag = getTagByTagId(tagId); var tagKey = getTagKey(tag); var tagEntry = tagScenarioMap[tagKey]; @@ -72,7 +72,7 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { return tagScenarioMap; } - function getRootTags() { + function getRootTags () { if (!rootTags) { rootTags = calculateRootTags(); } @@ -83,8 +83,10 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { * Builds up a hierarchy of tag nodes that is shown in the * navigation and returns the list of root nodes */ - function calculateRootTags() { + function calculateRootTags () { _.forEach(_.values(tagScenarioMap), function (tagEntry) { + if (tagEntry.tag.hideInNav) return; + var tagNode = getTagNode(tagEntry); var name = getTagName(tagEntry.tag); var nameNode = tagNameMap[name]; @@ -116,7 +118,7 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { }); - function getTagNode(tagEntry) { + function getTagNode (tagEntry) { var tag = tagEntry.tag; var key = getTagKey(tag); var tagNode = tagNodeMap[key]; @@ -135,7 +137,7 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { return tagNode; } - function createTagNode(tagEntry) { + function createTagNode (tagEntry) { var tag = tagEntry.tag; var scenarios = tagEntry.scenarios; var node = createNode(tagToString(tag)); @@ -161,7 +163,7 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { * A name node is a pseudo tag node that * has as sub nodes all tags with the same name */ - function createNameNode(name) { + function createNameNode (name) { var node = createNode(name); node.url = function () { @@ -183,7 +185,7 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { return node; } - function createNode(name) { + function createNode (name) { var subTags = []; return { @@ -218,26 +220,26 @@ jgivenReportApp.factory('tagService', ['dataService', function (dataService) { } } - function getScenariosByTag(tag) { + function getScenariosByTag (tag) { return tagScenarioMap[getTagKey(tag)].scenarios; } - function getTagByKey(tagKey) { + function getTagByKey (tagKey) { var tagEntry = tagScenarioMap[tagKey]; return tagEntry && tagEntry.tag; } - function getTagNameNode(name) { + function getTagNameNode (name) { return tagNameMap[name]; } - function getTagByTagId(tagId) { + function getTagByTagId (tagId) { var tagInstance = dataService.getTagFile().tags[tagId]; var tagType = dataService.getTagFile().tagTypeMap[tagInstance.tagType]; var tag = Object.create(tagType); tag.value = tagInstance.value; if (tagInstance.description) { - tag.description = tagInstance.description; + tag.description = tagInstance.description; } if (tagInstance.href) { tag.href = tagInstance.href; diff --git a/jgiven-junit/src/test/java/com/tngtech/jgiven/junit/TagAnnotationTest.java b/jgiven-junit/src/test/java/com/tngtech/jgiven/junit/TagAnnotationTest.java new file mode 100644 index 0000000000..ded1b82fa2 --- /dev/null +++ b/jgiven-junit/src/test/java/com/tngtech/jgiven/junit/TagAnnotationTest.java @@ -0,0 +1,31 @@ +package com.tngtech.jgiven.junit; + +import com.tngtech.jgiven.annotation.IsTag; +import com.tngtech.jgiven.junit.test.GivenTestStep; +import com.tngtech.jgiven.junit.test.ThenTestStep; +import com.tngtech.jgiven.junit.test.WhenTestStep; +import org.junit.Test; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TagAnnotationTest extends ScenarioTest { + + @IsTag( showInNavigation = false ) + @Retention( RetentionPolicy.RUNTIME ) + @interface TagNotShownInNavigation {} + + + @TagNotShownInNavigation + @Test + public void shownInNavigation_is_correctly_evaluated() throws Throwable { + given().some_boolean_value( true ); + + getScenario().finished(); + + assertThat( getScenario().getModel().getTagMap().entrySet().iterator().next().getValue().getShownInNavigation() ) + .isEqualTo( false ); + } +}