Skip to content

Commit

Permalink
feat(dsl): support expect property statement
Browse files Browse the repository at this point in the history
  • Loading branch information
tpluscode committed Jul 9, 2019
1 parent beb80e3 commit 1362bce
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ define(["ace/lib/oop", "ace/mode/text", "ace/mode/text_highlight_rules"], functi
};
};
oop.inherits(HighlightRules, mTextHighlightRules.TextHighlightRules);

var Mode = function() {
this.HighlightRules = HighlightRules;
};
Expand All @@ -28,7 +28,7 @@ define(["ace/lib/oop", "ace/mode/text", "ace/mode/text_highlight_rules"], functi
Mode.prototype.getCompletions = function(state, session, pos, prefix) {
return [];
}

return {
Mode: Mode
};
Expand Down
7 changes: 7 additions & 0 deletions app.hypermedia.testing.dsl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -246,5 +246,12 @@
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<!-- use 2.9.1 for Java 7 projects -->
<version>3.11.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,33 @@ grammar app.hypermedia.testing.dsl.Core with org.eclipse.xtext.common.Terminals
generate core "http://www.zazuko.com/apitesting/dsl/ApiTestingDsl"

Model:
(elements+=Element)*;
(steps+=Element)*;

Element:
ClassBlock;

ClassLevelAssertion:
PropertyAssertion;
PropertyBlock |
PropertyStatement;

ClassBlock:
'With' 'Class' name=STRING '{'
(assertions+=ClassLevelAssertion)*
(children+=ClassLevelAssertion)*
hatch=HATCH?
'}';

PropertyAssertion:
'Expect' 'Property' name=STRING
(
'{'
(assertions+=ClassLevelAssertion)*
hatch=HATCH?
'}'
)?
PropertyBlock:
('Expect' | 'With') 'Property' name=STRING
(
'{'
(children+=ClassLevelAssertion)*
hatch=HATCH?
'}'
)
;

PropertyStatement:
'Expect' 'Property' name=STRING (value=STRING)?
;

terminal HATCH: '++' -> '++';
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ package app.hypermedia.testing.dsl.generator

import app.hypermedia.testing.dsl.core.ClassBlock
import app.hypermedia.testing.dsl.core.ClassLevelAssertion
import app.hypermedia.testing.dsl.core.PropertyAssertion
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.AbstractGenerator
import org.eclipse.xtext.generator.IFileSystemAccess2
import org.eclipse.xtext.generator.IGeneratorContext
import app.hypermedia.testing.dsl.core.PropertyBlock
import app.hypermedia.testing.dsl.core.PropertyStatement

/**
* Generates code from your model files on save.
Expand Down Expand Up @@ -44,27 +45,34 @@ class CoreGenerator extends AbstractGenerator {
"type": "Class",
"classId": "«name»",
"children": [
«FOR assertion:assertions SEPARATOR ","»
«FOR assertion:children SEPARATOR ","»
«assertion.child»
«ENDFOR»
]
«hatch»
}
'''
def dispatch CharSequence child(PropertyAssertion it) '''
def dispatch CharSequence child(PropertyBlock it) '''
{
"type": "Property",
"propertyId": "«name»",
"children": [
«FOR assertion:assertions SEPARATOR ","»
«FOR assertion:children SEPARATOR ","»
«assertion.child»
«ENDFOR»
]
«hatch»
}
'''
def dispatch CharSequence child(PropertyStatement it) '''
{
"type": "Property",
"propertyId": "«name»"
}
'''
def dispatch child(ClassLevelAssertion it) '''
# TODO: implementation missing for child(«class.name»)
'''
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* generated by Xtext 2.18.0
*/
package app.hypermedia.testing.dsl.tests

import app.hypermedia.testing.dsl.core.ClassBlock
import app.hypermedia.testing.dsl.core.Model
import com.google.inject.Inject
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.extensions.InjectionExtension
import org.eclipse.xtext.testing.util.ParseHelper
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.^extension.ExtendWith
import static org.junit.Assert.assertEquals

@ExtendWith(InjectionExtension)
@InjectWith(CoreInjectorProvider)
class ClassParsingTest {
@Inject
ParseHelper<Model> parseHelper

@Test
def void withClass_ParsesName() {
// when
val result = parseHelper.parse('''
With Class "Foo" {
}
''')

// then
TestHelpers.assertModelParsedSuccessfully(result)

val classBlock = result.steps.get(0) as ClassBlock
assertEquals(classBlock.name, "Foo")
}

@Test
def void withClass_shouldNotAllowNestingItself() {
// when
val result = parseHelper.parse('''
With Class "Foo" {
With Class "Bar" {
}
}
''')

// then
TestHelpers.assertModelParsingFailed(result)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,12 @@
*/
package app.hypermedia.testing.dsl.tests

import com.google.inject.Inject
import app.hypermedia.testing.dsl.core.Model
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.extensions.InjectionExtension
import org.eclipse.xtext.testing.util.ParseHelper
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.^extension.ExtendWith
import static org.junit.Assert.assertEquals
import app.hypermedia.testing.dsl.core.ClassBlock

@ExtendWith(InjectionExtension)
@InjectWith(CoreInjectorProvider)
class CoreParsingTest {
@Inject
ParseHelper<Model> parseHelper

@Test
def void withClass_ParsesName() {
// when
val result = parseHelper.parse('''
With Class "Foo" {
}
''')

// then
TestHelpers.assertModelParsedSuccessfully(result)

val classBlock = result.elements.get(0) as ClassBlock
assertEquals(classBlock.name, "Foo")
}
// keep this around because it's regenerated by mwe2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* generated by Xtext 2.18.0
*/
package app.hypermedia.testing.dsl.tests

import app.hypermedia.testing.dsl.core.ClassBlock
import app.hypermedia.testing.dsl.core.Model
import com.google.inject.Inject
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.extensions.InjectionExtension
import org.eclipse.xtext.testing.util.ParseHelper
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.^extension.ExtendWith

import static org.junit.Assert.assertEquals
import app.hypermedia.testing.dsl.core.PropertyBlock
import app.hypermedia.testing.dsl.core.PropertyStatement
import static org.assertj.core.api.Assertions.*;

@ExtendWith(InjectionExtension)
@InjectWith(CoreInjectorProvider)
class PropertyParsingTest {
@Inject
ParseHelper<Model> parseHelper

@Test
def void withProperty_parsesName() {
// when
val result = parseHelper.parse('''
With Class "Person" {
With Property "name" {
}
}
''')

// then
TestHelpers.assertModelParsedSuccessfully(result)

val classBlock = result.steps.get(0) as ClassBlock
val propertyBlock = classBlock.children.get(0) as PropertyBlock
assertEquals(propertyBlock.name, "name")
}

@Test
def void expectProperty_parsesWithoutChildren() {
// when
val result = parseHelper.parse('''
With Class "Person" {
Expect Property "name"
}
''')

// then
TestHelpers.assertModelParsedSuccessfully(result)

val classBlock = result.steps.get(0) as ClassBlock
val propertyStmt = classBlock.children.get(0) as PropertyStatement
assertEquals(propertyStmt.name, "name")
}

@Test
def void expectProperty_parsesOptionalValueToAssert() {
// when
val result = parseHelper.parse('''
With Class "Person" {
Expect Property "name" "TOMASZ"
}
''')

// then
TestHelpers.assertModelParsedSuccessfully(result)

val classBlock = result.steps.get(0) as ClassBlock
val propertyStmt = classBlock.children.get(0) as PropertyStatement
assertEquals(propertyStmt.value, "TOMASZ")
}

@Test
def void withProperty_parsedSuccessfullyWithChildren() {
// when
val result = parseHelper.parse('''
With Class "Book" {
With Property "author" {
Expect Property "name"
}
}
''')

// then
TestHelpers.assertModelParsedSuccessfully(result)

val classBlock = result.steps.get(0) as ClassBlock
val propertyBlock = classBlock.children.get(0) as PropertyBlock
assertEquals(propertyBlock.children.length, 1)
assertThat(propertyBlock.children.get(0)).isInstanceOf(PropertyStatement)
}

@Test
def void withProperty_parsingFailsWhenItHasNoChildren() {
// when
val result = parseHelper.parse('''
With Class "Book" {
With Property "author"
}
''')

// then
TestHelpers.assertModelParsingFailed(result)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ class TestHelpers {
val errors = result.eResource.errors
Assertions.assertTrue(errors.isEmpty, '''Unexpected errors: «errors.join(", ")»''')
}

static def assertModelParsingFailed(Model result) {
Assertions.assertNotNull(result)
val errors = result.eResource.errors
Assertions.assertFalse(errors.isEmpty)
}
}

0 comments on commit 1362bce

Please sign in to comment.