Skip to content

Commit 2a0838b

Browse files
committed
feat(dsl-core): add expect status step
1 parent e18c5d5 commit 2a0838b

File tree

9 files changed

+208
-14
lines changed

9 files changed

+208
-14
lines changed

app.hypermedia.testing.dsl/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,5 +253,11 @@
253253
<version>3.11.1</version>
254254
<scope>test</scope>
255255
</dependency>
256+
<dependency>
257+
<groupId>org.junit.jupiter</groupId>
258+
<artifactId>junit-jupiter-params</artifactId>
259+
<version>5.5.0</version>
260+
<scope>test</scope>
261+
</dependency>
256262
</dependencies>
257263
</project>

app.hypermedia.testing.dsl/src/main/java/app/hypermedia/testing/dsl/Core.xtext

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ Model:
77

88
TopLevelStep:
99
ClassBlock;
10+
11+
ResponseStep:
12+
StatusStatement |
13+
RepresentationStep
14+
;
1015

1116
RepresentationStep:
1217
PropertyBlock |
@@ -32,4 +37,8 @@ PropertyStatement:
3237
EXPECT_MODIFIER 'Property' name=STRING (value=STRING)?
3338
;
3439

40+
StatusStatement:
41+
EXPECT_MODIFIER 'Status' status=INT
42+
;
43+
3544
terminal HATCH: '++' -> '++';

app.hypermedia.testing.dsl/src/main/java/app/hypermedia/testing/dsl/Hydra.xtext

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ OperationBlock:
3333

3434
InvocationBlock:
3535
{InvocationBlock} 'Invoke' '{'
36-
(children+=RepresentationStep)*
36+
(children+=ResponseStep)*
3737
'}'
3838
;

app.hypermedia.testing.dsl/src/main/java/app/hypermedia/testing/dsl/generator/CoreGenerator.xtend

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import app.hypermedia.testing.dsl.core.PropertyStatement
1414
import org.apache.commons.lang3.NotImplementedException
1515
import org.eclipse.emf.ecore.EObject
1616
import app.hypermedia.testing.dsl.Modifier
17+
import app.hypermedia.testing.dsl.core.StatusStatement
1718

1819
/**
1920
* Generates code from your model files on save.
@@ -56,7 +57,7 @@ class CoreGenerator extends AbstractGenerator {
5657
}
5758
'''
5859
59-
def dispatch CharSequence step(PropertyBlock it) '''
60+
def dispatch step(PropertyBlock it) '''
6061
{
6162
"type": "Property",
6263
"propertyId": "«name»",
@@ -74,7 +75,7 @@ class CoreGenerator extends AbstractGenerator {
7475
}
7576
'''
7677
77-
def dispatch CharSequence step(PropertyStatement it) '''
78+
def dispatch step(PropertyStatement it) '''
7879
{
7980
"type": "Property",
8081
"propertyId": "«name»",
@@ -85,6 +86,14 @@ class CoreGenerator extends AbstractGenerator {
8586
}
8687
'''
8788
89+
def dispatch step(StatusStatement it) '''
90+
{
91+
"type": "Expectation",
92+
"expectation": "Status",
93+
"code": «status»
94+
}
95+
'''
96+
8897
def dispatch step(EObject step) {
8998
throw new NotImplementedException(String.format("Unrecognized step %s", step.class))
9099
}

app.hypermedia.testing.dsl/src/main/java/app/hypermedia/testing/dsl/generator/HydraGenerator.xtend

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@ class HydraGenerator extends CoreGenerator {
4848
4949
def dispatch step(InvocationBlock it) '''
5050
{
51-
"type": "Invocation"
51+
"type": "Invocation",
52+
"children": [
53+
«FOR child:children SEPARATOR ","»
54+
«child.step»
55+
«ENDFOR»
56+
]
5257
}
5358
'''
5459
}

app.hypermedia.testing.dsl/src/main/java/app/hypermedia/testing/dsl/validation/CoreValidator.xtend

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
*/
44
package app.hypermedia.testing.dsl.validation
55

6+
import app.hypermedia.testing.dsl.core.StatusStatement
7+
import app.hypermedia.testing.dsl.core.CorePackage
8+
import org.eclipse.xtext.validation.Check
69

710
/**
811
* This class contains custom validation rules.
@@ -11,15 +14,12 @@ package app.hypermedia.testing.dsl.validation
1114
*/
1215
class CoreValidator extends AbstractCoreValidator {
1316

14-
// public static val INVALID_NAME = 'invalidName'
15-
//
16-
// @Check
17-
// def checkGreetingStartsWithCapital(Greeting greeting) {
18-
// if (!Character.isUpperCase(greeting.name.charAt(0))) {
19-
// warning('Name should start with a capital',
20-
// CorePackage.Literals.GREETING__NAME,
21-
// INVALID_NAME)
22-
// }
23-
// }
17+
@Check
18+
def checkStatusIsWithinRange(StatusStatement statusStatement) {
19+
if (statusStatement.status < 100 || statusStatement.status > 599) {
20+
error('Status can be an integer between 100 and 599',
21+
CorePackage.Literals.STATUS_STATEMENT__STATUS)
22+
}
23+
}
2424

2525
}

app.hypermedia.testing.dsl/src/test/java/app/hypermedia/testing/dsl/tests/generator/hydra/OperationTest.snap

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,52 @@ app.hypermedia.testing.dsl.tests.generator.hydra.OperationTest.emptyWithOperatio
4949
]
5050

5151

52+
app.hypermedia.testing.dsl.tests.generator.hydra.OperationTest.topLevelOperationInvocationWithStatusExpectation_generatesSteps=[
53+
{
54+
"map": {
55+
"steps": {
56+
"myArrayList": [
57+
{
58+
"map": {
59+
"children": {
60+
"myArrayList": [
61+
{
62+
"map": {
63+
"children": {
64+
"myArrayList": [
65+
{
66+
"map": {
67+
"code": 201,
68+
"expectation": "Status",
69+
"type": "Expectation"
70+
},
71+
"empty": false
72+
}
73+
],
74+
"empty": false
75+
},
76+
"type": "Invocation"
77+
},
78+
"empty": false
79+
}
80+
],
81+
"empty": false
82+
},
83+
"operationId": "CreateUser",
84+
"strict": false,
85+
"type": "Operation"
86+
},
87+
"empty": false
88+
}
89+
],
90+
"empty": false
91+
}
92+
},
93+
"empty": false
94+
}
95+
]
96+
97+
5298
app.hypermedia.testing.dsl.tests.generator.hydra.OperationTest.topLevelOperationMultipleInvocations_generatesStep=[
5399
{
54100
"map": {
@@ -60,18 +106,30 @@ app.hypermedia.testing.dsl.tests.generator.hydra.OperationTest.topLevelOperation
60106
"myArrayList": [
61107
{
62108
"map": {
109+
"children": {
110+
"myArrayList": [ ],
111+
"empty": true
112+
},
63113
"type": "Invocation"
64114
},
65115
"empty": false
66116
},
67117
{
68118
"map": {
119+
"children": {
120+
"myArrayList": [ ],
121+
"empty": true
122+
},
69123
"type": "Invocation"
70124
},
71125
"empty": false
72126
},
73127
{
74128
"map": {
129+
"children": {
130+
"myArrayList": [ ],
131+
"empty": true
132+
},
75133
"type": "Invocation"
76134
},
77135
"empty": false

app.hypermedia.testing.dsl/src/test/java/app/hypermedia/testing/dsl/tests/generator/hydra/OperationTest.xtend

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,25 @@ class OperationTest {
7676
val file = new JSONObject(fsa.textFiles.values.get(0).toString)
7777
expect(file).toMatchSnapshot()
7878
}
79+
80+
@Test
81+
def topLevelOperationInvocationWithStatusExpectation_generatesSteps() {
82+
// given
83+
val model = parseHelper.parse('''
84+
With Operation "CreateUser" {
85+
Invoke {
86+
Expect Status 201
87+
}
88+
}
89+
''')
90+
91+
// when
92+
val fsa = new InMemoryFileSystemAccess()
93+
generator.doGenerate(model.eResource, fsa, new GeneratorContext())
94+
println(fsa.textFiles)
95+
96+
// then
97+
val file = new JSONObject(fsa.textFiles.values.get(0).toString)
98+
expect(file).toMatchSnapshot()
99+
}
79100
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* generated by Xtext 2.18.0
3+
*/
4+
package app.hypermedia.testing.dsl.tests.hydra
5+
6+
import app.hypermedia.testing.dsl.core.Model
7+
import com.google.inject.Inject
8+
import org.eclipse.xtext.testing.InjectWith
9+
import org.eclipse.xtext.testing.extensions.InjectionExtension
10+
import org.eclipse.xtext.testing.util.ParseHelper
11+
import org.junit.jupiter.api.Test
12+
import org.junit.jupiter.api.^extension.ExtendWith
13+
import static org.junit.Assert.assertEquals
14+
import app.hypermedia.testing.dsl.tests.HydraInjectorProvider
15+
import app.hypermedia.testing.dsl.tests.TestHelpers
16+
import app.hypermedia.testing.dsl.hydra.RelaxedOperationBlock
17+
import app.hypermedia.testing.dsl.core.StatusStatement
18+
import org.junit.jupiter.params.provider.MethodSource
19+
import org.junit.jupiter.params.ParameterizedTest
20+
import app.hypermedia.testing.dsl.hydra.InvocationBlock
21+
import app.hypermedia.testing.dsl.core.CorePackage
22+
import org.eclipse.xtext.testing.validation.ValidationTestHelper
23+
24+
@ExtendWith(InjectionExtension)
25+
@InjectWith(HydraInjectorProvider)
26+
class StatusParsingTest {
27+
@Inject extension ParseHelper<Model>
28+
@Inject extension ValidationTestHelper
29+
30+
@ParameterizedTest
31+
@MethodSource("validStatuses")
32+
def void expectStatus_parsesSuccessfullyUnderInvoke(int status) {
33+
// when
34+
val result = '''
35+
With Operation "CreateUser" {
36+
Invoke {
37+
Expect Status «status»
38+
}
39+
}
40+
'''.parse
41+
42+
// then
43+
TestHelpers.assertModelParsedSuccessfully(result)
44+
45+
val operationBlock = result.steps.get(0) as RelaxedOperationBlock
46+
val invocationBlock = operationBlock.invocations.get(0) as InvocationBlock
47+
val statusBlock = invocationBlock.children.get(0) as StatusStatement
48+
assertEquals(statusBlock.status, status)
49+
}
50+
51+
@ParameterizedTest
52+
@MethodSource("invalidStatuses")
53+
def void expectStatus_failsToParseBogusStatus(int status) {
54+
// when
55+
val result = '''
56+
With Operation "CreateUser" {
57+
Invoke {
58+
Expect Status «status»
59+
}
60+
}
61+
'''.parse
62+
63+
// then
64+
result.assertError(
65+
CorePackage.Literals.STATUS_STATEMENT,
66+
null,
67+
"Status can be an integer between 100 and 599"
68+
)
69+
}
70+
71+
static def invalidStatuses() {
72+
return #[
73+
1000,
74+
600,
75+
-10,
76+
0,
77+
99
78+
]
79+
}
80+
81+
static def validStatuses() {
82+
return #[
83+
100, 201, 404, 599
84+
]
85+
}
86+
}

0 commit comments

Comments
 (0)