Skip to content

Commit f3aefd7

Browse files
authored
Make @issue repeatable (#1189)
Fixes #1030
1 parent 3370650 commit f3aefd7

File tree

5 files changed

+99
-13
lines changed

5 files changed

+99
-13
lines changed

docs/extensions.adoc

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -490,14 +490,7 @@ To indicate that a feature or spec relates to one or more issues in an external
490490

491491
[source,groovy]
492492
----
493-
@Issue("http://my.issues.org/FOO-1")
494-
class MySpec {
495-
@Issue("http://my.issues.org/FOO-2")
496-
def "Foo should do bar"() { ... }
497-
498-
@Issue(["http://my.issues.org/FOO-3", "http://my.issues.org/FOO-4"])
499-
def "I have two related issues"() { ... }
500-
}
493+
include::{sourcedir}/extension/IssueDocSpec.groovy[tag=example]
501494
----
502495

503496
If you have a common prefix URL for all issues in a project, you can use the <<Spock Configuration File>> to set it up

docs/release_notes.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ include::include.adoc[]
1414

1515
- `@ConfineMetaClassChanges` is now repeatable
1616

17+
- `@Issue` is now repeatable
18+
1719

1820
== 2.0-M3 (2020-06-11)
1921

spock-core/src/main/java/spock/lang/Issue.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.spockframework.runtime.extension.ExtensionAnnotation;
2020
import org.spockframework.runtime.extension.builtin.IssueExtension;
21+
import org.spockframework.util.Beta;
2122

2223
import java.lang.annotation.*;
2324

@@ -30,11 +31,22 @@
3031
@Retention(RetentionPolicy.RUNTIME)
3132
@Target({ElementType.TYPE, ElementType.METHOD})
3233
@ExtensionAnnotation(IssueExtension.class)
34+
@Repeatable(Issue.Container.class)
3335
public @interface Issue {
3436
/**
3537
* The IDs of the issues that the annotated element relates to.
3638
*
3739
* @return the IDs of the issues that the annotated element relates to
3840
*/
3941
String[] value();
42+
43+
/**
44+
* @since 2.0
45+
*/
46+
@Beta
47+
@Retention(RetentionPolicy.RUNTIME)
48+
@Target({ElementType.TYPE, ElementType.METHOD})
49+
@interface Container {
50+
Issue[] value();
51+
}
4052
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.spockframework.docs.extension
2+
3+
import spock.lang.Issue
4+
import spock.lang.Specification
5+
6+
// tag::example[]
7+
@Issue("http://my.issues.org/FOO-1")
8+
class IssueDocSpec extends Specification {
9+
@Issue("http://my.issues.org/FOO-2")
10+
def "Foo should do bar"() {
11+
expect: true
12+
}
13+
14+
@Issue(["http://my.issues.org/FOO-3", "http://my.issues.org/FOO-4"])
15+
def "I have two related issues"() {
16+
expect: true
17+
}
18+
19+
@Issue(["http://my.issues.org/FOO-5", "http://my.issues.org/FOO-6"])
20+
@Issue("http://my.issues.org/FOO-7")
21+
def "I have three related issues"() {
22+
expect: true
23+
}
24+
}
25+
// end::example[]

spock-specs/src/test/groovy/org/spockframework/smoke/extension/IssueExtension.groovy

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,65 @@ class IssueExtension extends EmbeddedSpecification {
6161
url == "http://my.issues.org/FOO-1"
6262
}
6363
with(tags[1]) {
64-
name == "FOO-2"
65-
key == "issue"
66-
value == "FOO-2"
67-
url == "http://my.issues.org/FOO-2"
68-
}
64+
name == "FOO-2"
65+
key == "issue"
66+
value == "FOO-2"
67+
url == "http://my.issues.org/FOO-2"
68+
}
69+
}
70+
71+
@Issue("http://my.issues.org/FOO-1")
72+
@Issue("http://my.issues.org/FOO-2")
73+
def "if multiple issue annotations are applied, all of them are converted to a tag"() {
74+
def tags = specificationContext.currentFeature.tags
75+
76+
expect:
77+
tags.size() == 2
78+
with(tags[0]) {
79+
name == "FOO-1"
80+
key == "issue"
81+
value == "FOO-1"
82+
url == "http://my.issues.org/FOO-1"
83+
}
84+
with(tags[1]) {
85+
name == "FOO-2"
86+
key == "issue"
87+
value == "FOO-2"
88+
url == "http://my.issues.org/FOO-2"
89+
}
90+
}
91+
92+
@Issue(["http://my.issues.org/FOO-1", "http://my.issues.org/FOO-2"])
93+
@Issue(["http://my.issues.org/FOO-3", "http://my.issues.org/FOO-4"])
94+
def "if multiple issue annotations with multiple issues are applied, all of them are converted to a tag"() {
95+
def tags = specificationContext.currentFeature.tags
96+
97+
expect:
98+
tags.size() == 4
99+
with(tags[0]) {
100+
name == "FOO-1"
101+
key == "issue"
102+
value == "FOO-1"
103+
url == "http://my.issues.org/FOO-1"
104+
}
105+
with(tags[1]) {
106+
name == "FOO-2"
107+
key == "issue"
108+
value == "FOO-2"
109+
url == "http://my.issues.org/FOO-2"
110+
}
111+
with(tags[2]) {
112+
name == "FOO-3"
113+
key == "issue"
114+
value == "FOO-3"
115+
url == "http://my.issues.org/FOO-3"
116+
}
117+
with(tags[3]) {
118+
name == "FOO-4"
119+
key == "issue"
120+
value == "FOO-4"
121+
url == "http://my.issues.org/FOO-4"
122+
}
69123
}
70124

71125
def "complains if @Issue is used on anything other than a spec or feature"() {

0 commit comments

Comments
 (0)