diff --git a/.run/Reformat Tests.run.xml b/.run/Reformat Tests.run.xml
new file mode 100644
index 00000000..ed6f4681
--- /dev/null
+++ b/.run/Reformat Tests.run.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/test/kotlin/org/neo4j/graphql/TranslatorExceptionTests.kt b/core/src/test/kotlin/org/neo4j/graphql/TranslatorExceptionTests.kt
index d2fbee80..551b618a 100644
--- a/core/src/test/kotlin/org/neo4j/graphql/TranslatorExceptionTests.kt
+++ b/core/src/test/kotlin/org/neo4j/graphql/TranslatorExceptionTests.kt
@@ -1,5 +1,7 @@
package org.neo4j.graphql
+import demo.org.neo4j.graphql.utils.asciidoc.ast.CodeBlock
+import demo.org.neo4j.graphql.utils.asciidoc.ast.Section
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.DynamicNode
import org.junit.jupiter.api.DynamicTest
@@ -7,41 +9,44 @@ import org.junit.jupiter.api.TestFactory
import org.neo4j.graphql.utils.AsciiDocTestSuite
import java.util.stream.Stream
-class TranslatorExceptionTests : AsciiDocTestSuite("translator-tests1.adoc") {
+class TranslatorExceptionTests : AsciiDocTestSuite("translator-tests1.adoc", emptyList()) {
- @TestFactory
- fun createTests(): Stream {
- return generateTests()
+ override fun createTestCase(section: Section): CodeBlock? {
+ return findSetupCodeBlocks(section, "graphql", mapOf("schema" to "true")).firstOrNull() ?: return null
}
- override fun schemaTestFactory(schema: String): List {
- val translator = Translator(SchemaBuilder.buildSchema(schema))
+ override fun createTests(testCase: CodeBlock, section: Section, ignoreReason: String?): List {
+ if (section.title != "Tests") {
+ return emptyList()
+ }
return listOf(
DynamicTest.dynamicTest("unknownType") {
Assertions.assertThrows(InvalidQueryException::class.java) {
- translator.translate(
- """
- {
- company {
- name
- }
- }
+ Translator(SchemaBuilder.buildSchema(testCase.content)).translate(
"""
+ {
+ company {
+ name
+ }
+ }
+ """
)
}
},
DynamicTest.dynamicTest("mutation") {
Assertions.assertThrows(InvalidQueryException::class.java) {
- translator.translate(
+ Translator(SchemaBuilder.buildSchema(testCase.content)).translate(
"""
- {
- createPerson()
- }
- """.trimIndent()
+ {
+ createPerson()
+ }
+ """.trimIndent()
)
}
}
-
)
}
+
+ @TestFactory
+ fun createTests(): Stream = generateTests()
}
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/AsciiDocTestSuite.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/AsciiDocTestSuite.kt
index 58219385..038bee9e 100644
--- a/core/src/test/kotlin/org/neo4j/graphql/utils/AsciiDocTestSuite.kt
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/AsciiDocTestSuite.kt
@@ -3,206 +3,133 @@ package org.neo4j.graphql.utils
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.intellij.rt.execution.junit.FileComparisonFailure
+import demo.org.neo4j.graphql.utils.asciidoc.AsciiDocParser
+import demo.org.neo4j.graphql.utils.asciidoc.ast.*
import org.junit.jupiter.api.DynamicContainer
import org.junit.jupiter.api.DynamicNode
import org.junit.jupiter.api.DynamicTest
import java.io.File
import java.io.FileWriter
-import java.net.URI
import java.util.*
-import java.util.regex.Pattern
import java.util.stream.Stream
-import javax.ws.rs.core.UriBuilder
+import kotlin.reflect.KMutableProperty1
/**
* @param fileName the name of the test file
- * @param testCaseMarkers the markers for the test case
- * @param globalMarkers the markers for global blocks
+ * @param relevantBlocks a list of pairs of filter functions and properties to set the found code blocks
*/
-open class AsciiDocTestSuite(
+abstract class AsciiDocTestSuite(
private val fileName: String,
- private val testCaseMarkers: List = emptyList(),
- private val globalMarkers: List = listOf(SCHEMA_MARKER)
+ private val relevantBlocks: List>,
) {
+ abstract class CodeBlockMatcher(
+ val language: String,
+ val filter: Map = emptyMap(),
+ val exactly: Boolean = false
+ ) {
+ abstract fun set(testData: T, codeBlock: CodeBlock)
+ }
+
+
private val srcLocation = File("src/test/resources/", fileName).toURI()
- private val fileContent: StringBuilder = StringBuilder()
+ private val document = AsciiDocParser(fileName).parse()
/**
- * all parsed blocks of the test file
+ * all parsed code blocks of the test file
*/
- private val knownBlocks: MutableList = mutableListOf()
+ private val knownBlocks = collectBlocks(document).toMutableList()
fun generateTests(): Stream {
- val stream = FileParser().parse()
- return if (FLATTEN_TESTS) flatten(stream, "$fileName:") else stream
- }
-
- private fun flatten(stream: Stream, name: String): Stream {
- return stream.flatMap {
- when (it) {
- is DynamicContainer -> flatten(it.children, "$name[${it.displayName}]")
- is DynamicTest -> Stream.of(DynamicTest.dynamicTest("$name[${it.displayName}]", it.executable))
- else -> throw IllegalArgumentException("unknown type ${it.javaClass.name}")
- }
+ val tests = createTestsOfSection(document).toMutableList()
+
+ if (UPDATE_TEST_FILE) {
+ // this test prints out the adjusted test file
+ tests += DynamicTest.dynamicTest(
+ "Write updated Testfile",
+ srcLocation,
+ this@AsciiDocTestSuite::writeAdjustedTestFile
+ )
+ } else if (REFORMAT_TEST_FILE) {
+ tests += DynamicTest.dynamicTest("Reformat Testfile", srcLocation, this@AsciiDocTestSuite::reformatTestFile)
+ } else if (GENERATE_TEST_FILE_DIFF) {
+ // this test prints out the adjusted test file
+ tests += DynamicTest.dynamicTest(
+ "Adjusted Tests",
+ srcLocation,
+ this@AsciiDocTestSuite::printAdjustedTestFile
+ )
}
- }
- class ParsedBlock(
- val marker: String,
- val uri: URI,
- var headline: String? = null
- ) {
- var start: Int? = null
- var end: Int? = null
- var adjustedCode: String? = null
- var reformattedCode: String? = null
- val code: StringBuilder = StringBuilder()
-
- fun code() = code.trim().toString()
+ return if (FLATTEN_TESTS) flatten(tests.stream(), "$fileName:") else tests.stream()
}
- private inner class FileParser {
-
- private var root: DocumentLevel? = null
- private var currentDocumentLevel: DocumentLevel? = null
- private var currentDepth = 0
-
- private val globalCodeBlocks = mutableMapOf>()
- private var codeBlocksOfTest = mutableMapOf>()
-
- fun parse(): Stream {
- val file = File(AsciiDocTestSuite::class.java.getResource("/$fileName")?.toURI()!!)
- val lines = file.readLines()
-
- var title: String? = null
- var currentBlock: ParsedBlock? = null
- var globalDone = false
+ private fun createTestsOfSection(section: Section, parentIgnoreReason: String? = null): List {
+
+ val tests = mutableListOf()
+ var testCase = createTestCase(section)
+ var ignoreReason: String? = null
+ for (node in section.blocks) {
+ when (node) {
+ is CodeBlock -> {
+ for (matcher in relevantBlocks) {
+ if (testCase != null && node.matches(matcher.language, matcher.filter, matcher.exactly)) {
+ matcher.set(testCase, node)
+ }
+ }
- var ignore = false
- var inside = false
- var offset = 0
- loop@ for ((lineNr, line) in lines.withIndex()) {
- fileContent.append(line).append('\n')
- if (line.startsWith("#") || line.startsWith("//")) {
- offset += line.length + 1
- continue
}
- val headlineMatcher = HEADLINE_PATTERN.matcher(line)
-
- when {
- !globalDone && globalMarkers.contains(line) -> currentBlock =
- startBlock(line, lineNr, globalCodeBlocks)
- testCaseMarkers.contains(line) -> {
- globalDone = true
- currentBlock = startBlock(line, lineNr, codeBlocksOfTest)
+ is Block -> {
+ val blockContent = node.content.trim()
+ if (blockContent.startsWith("CAUTION:")) {
+ ignoreReason = blockContent.substring("CAUTION:".length).trim()
}
+ }
- line == "'''" -> {
- createTests(title, lineNr, ignore)
- currentBlock = null
- ignore = false
- }
-
- line == "----" -> {
- inside = !inside
- if (inside) {
-
- currentBlock?.start = offset + line.length + 1
-
- } else if (currentBlock != null) {
-
- currentBlock.end = offset
- when (currentBlock.marker) {
-
- SCHEMA_MARKER -> {
- val schemaTests = schemaTestFactory(currentBlock.code())
- currentDocumentLevel?.tests?.add(schemaTests)
- if (testCaseMarkers.isEmpty()) {
- break@loop
- }
- }
- }
-
- }
+ is ThematicBreak -> {
+ if (testCase != null) {
+ tests += createTests(testCase, section, ignoreReason ?: parentIgnoreReason)
}
+ ignoreReason = null
+ testCase = createTestCase(section) ?: continue
+ }
- headlineMatcher.matches() -> {
- val depth = headlineMatcher.group(1).length
- title = headlineMatcher.group(2)
- val uri = UriBuilder.fromUri(srcLocation).queryParam("line", lineNr + 1).build()
- handleHeadline(title, uri, depth)
+ is Section -> {
+ val nestedTests = createTestsOfSection(node, ignoreReason ?: parentIgnoreReason)
+ if (nestedTests.isNotEmpty()) {
+ tests += DynamicContainer.dynamicContainer(node.title, node.uri, nestedTests.stream())
}
-
- line.startsWith("CAUTION:") -> ignore = true
-
- inside -> currentBlock?.code?.append(line)?.append("\n")
-
}
- offset += line.length + 1 // +1 b/c of newline
}
-
- if (UPDATE_TEST_FILE) {
- // this test prints out the adjusted test file
- root?.afterTests?.add(
- DynamicTest.dynamicTest(
- "Write updated Testfile",
- srcLocation,
- this@AsciiDocTestSuite::writeAdjustedTestFile
- )
- )
- } else if (REFORMAT_TEST_FILE) {
- root?.afterTests?.add(
- DynamicTest.dynamicTest("Reformat Testfile", srcLocation, this@AsciiDocTestSuite::reformatTestFile)
- )
- } else if (GENERATE_TEST_FILE_DIFF) {
- // this test prints out the adjusted test file
- root?.afterTests?.add(
- DynamicTest.dynamicTest(
- "Adjusted Tests",
- srcLocation,
- this@AsciiDocTestSuite::printAdjustedTestFile
- )
- )
- }
- return root?.generateTests() ?: Stream.empty()
}
-
- private fun createTests(title: String?, lineNr: Int, ignore: Boolean) {
- if (codeBlocksOfTest.isEmpty()) {
- throw IllegalStateException("no code blocks for tests (line $lineNr)")
- }
- val tests = testFactory(
- title ?: throw IllegalStateException("Title should be defined (line $lineNr)"),
- globalCodeBlocks,
- codeBlocksOfTest,
- ignore
- )
- currentDocumentLevel?.tests?.add(tests)
- codeBlocksOfTest = mutableMapOf()
+ if (testCase != null) {
+ tests += createTests(testCase, section, ignoreReason ?: parentIgnoreReason)
}
+ return tests
+ }
- private fun handleHeadline(title: String, uri: URI, depth: Int) {
- if (root == null) {
- root = DocumentLevel(null, title, uri)
- currentDocumentLevel = root
- } else {
- val parent = when {
- depth > currentDepth -> currentDocumentLevel
- depth == currentDepth -> currentDocumentLevel?.parent
- ?: throw IllegalStateException("cannot create sub-level on null")
-
- else -> currentDocumentLevel?.parent?.parent
- ?: throw IllegalStateException("cannot create sub-level on null")
- }
- currentDocumentLevel = DocumentLevel(parent, title, uri)
+ abstract fun createTestCase(section: Section): T?
+
+ abstract fun createTests(testCase: T, section: Section, ignoreReason: String?): List
+
+ private fun flatten(stream: Stream, name: String): Stream {
+ return stream.flatMap {
+ when (it) {
+ is DynamicContainer -> flatten(it.children, "$name[${it.displayName}]")
+ is DynamicTest -> Stream.of(DynamicTest.dynamicTest("$name[${it.displayName}]", it.executable))
+ else -> throw IllegalArgumentException("unknown type ${it.javaClass.name}")
}
- currentDepth = depth
}
+ }
+ private fun collectBlocks(node: StructuralNode): List {
+ return when (node) {
+ is CodeBlock -> listOf(node)
+ else -> node.blocks.flatMap { collectBlocks(it) }
+ }
}
private fun writeAdjustedTestFile() {
@@ -213,7 +140,7 @@ open class AsciiDocTestSuite(
}
private fun reformatTestFile() {
- val content = generateAdjustedFileContent { it.reformattedCode }
+ val content = generateAdjustedFileContent { it.reformattedContent }
FileWriter(File("src/test/resources/", fileName)).use {
it.write(content)
}
@@ -221,26 +148,25 @@ open class AsciiDocTestSuite(
private fun printAdjustedTestFile() {
val rebuildTest = generateAdjustedFileContent()
- if (!Objects.equals(rebuildTest, fileContent.toString())) {
+ if (!Objects.equals(rebuildTest, document.content)) {
// This special exception will be handled by intellij so that you can diff directly with the file
throw FileComparisonFailure(
- null, fileContent.toString(), rebuildTest,
+ null, document.content, rebuildTest,
File("src/test/resources/", fileName).absolutePath, null
)
}
}
- private fun generateAdjustedFileContent(extractor: (ParsedBlock) -> String? = { it.adjustedCode }): String {
- knownBlocks.sortWith(compareByDescending { it.start }
- .thenByDescending { testCaseMarkers.indexOf(it.marker) })
- val rebuildTest = StringBuffer(fileContent)
+ private fun generateAdjustedFileContent(extractor: (CodeBlock) -> String? = { it.generatedContent }): String {
+ knownBlocks.sortWith(compareByDescending { it.start })
+ val rebuildTest = StringBuffer(document.content)
knownBlocks.filter { extractor(it) != null }
.forEach { block ->
- val start = block.start ?: throw IllegalArgumentException("unknown start position")
+ val start = block.start ?: error("unknown start position")
if (block.end == null) {
rebuildTest.insert(
start,
- ".${block.headline}\n${block.marker}\n----\n${extractor(block)}\n----\n\n"
+ ".${block.caption}\n${block.marker}\n----\n${extractor(block)}\n----\n\n"
)
} else {
rebuildTest.replace(start, block.end!!, extractor(block) + "\n")
@@ -249,43 +175,23 @@ open class AsciiDocTestSuite(
return rebuildTest.toString()
}
- fun startBlock(marker: String, lineIndex: Int, blocks: MutableMap>): ParsedBlock {
- val uri = UriBuilder.fromUri(srcLocation).queryParam("line", lineIndex + 1).build()
- val block = ParsedBlock(marker, uri)
- knownBlocks += block
- blocks.computeIfAbsent(marker) { mutableListOf() }.add(block)
- return block
- }
-
- protected open fun testFactory(
- title: String,
- globalBlocks: Map>,
- codeBlocks: Map>,
- ignore: Boolean
- ): List {
- return emptyList()
- }
-
- protected open fun schemaTestFactory(schema: String): List {
- return emptyList()
- }
-
- protected fun getOrCreateBlocks(
- codeBlocks: Map>,
- marker: String,
- headline: String
- ): List {
- val blocks = codeBlocks[marker]?.toMutableList() ?: mutableListOf()
- if (blocks.isEmpty() && (GENERATE_TEST_FILE_DIFF || UPDATE_TEST_FILE)) {
- val insertPoints = testCaseMarkers.indexOf(marker).let { testCaseMarkers.subList(0, it).asReversed() }
- val insertPoint = insertPoints.mapNotNull { codeBlocks[it]?.firstOrNull() }.firstOrNull()
- ?: throw IllegalArgumentException("none of the insert points $insertPoints found in $fileName")
- val block = ParsedBlock(marker, insertPoint.uri, headline)
- block.start = (insertPoint.end ?: throw IllegalStateException("no start for block defined")) + 6
- knownBlocks += blocks
- blocks += block
+ fun createCodeBlock(
+ insertPoint: CodeBlock,
+ language: String,
+ headline: String,
+ attributes: Map = emptyMap()
+ ): CodeBlock? {
+ if (!GENERATE_TEST_FILE_DIFF && !UPDATE_TEST_FILE) {
+ return null
}
- return blocks
+ val codeBlock = CodeBlock(insertPoint.uri, language, insertPoint.parent, attributes)
+ .apply {
+ caption = headline
+ content = ""
+ }
+ codeBlock.start = (insertPoint.end ?: error("no start for block defined")) + 6
+ knownBlocks += codeBlock
+ return codeBlock
}
companion object {
@@ -297,67 +203,66 @@ open class AsciiDocTestSuite(
val REFORMAT_TEST_FILE = System.getProperty("neo4j-graphql-java.reformat", "false") == "true"
val UPDATE_TEST_FILE = System.getProperty("neo4j-graphql-java.update-test-file", "false") == "true"
val MAPPER = ObjectMapper().registerKotlinModule()
- val HEADLINE_PATTERN: Pattern = Pattern.compile("^(=+) (.*)$")
-
- const val SCHEMA_MARKER = "[source,graphql,schema=true]"
- const val SCHEMA_CONFIG_MARKER = "[source,json,schema-config=true]"
-
- class DocumentLevel(
- val parent: DocumentLevel?,
- val name: String,
- private val testSourceUri: URI
- ) {
- private val children = mutableListOf()
- val tests = mutableListOf>()
- val afterTests = mutableListOf()
-
- init {
- parent?.children?.add(this)
- }
-
- fun generateTests(): Stream {
- val streamBuilder = Stream.builder()
- if (tests.size > 1) {
- if (children.isNotEmpty()) {
- streamBuilder.add(
- DynamicContainer.dynamicContainer(
- name,
- testSourceUri,
- children.stream().flatMap { it.generateTests() })
- )
- }
- for ((index, test) in tests.withIndex()) {
- streamBuilder.add(
- DynamicContainer.dynamicContainer(
- name + " " + (index + 1),
- testSourceUri,
- test.stream()
- )
- )
- }
- } else {
- val nodes = Stream.concat(
- tests.stream().flatMap { it.stream() },
- children.stream().flatMap { it.generateTests() }
- )
- streamBuilder.add(DynamicContainer.dynamicContainer(name, testSourceUri, nodes))
- }
- afterTests.forEach { streamBuilder.add(it) }
- return streamBuilder.build()
- }
- }
fun String.parseJsonMap(): Map = this.let {
@Suppress("UNCHECKED_CAST")
MAPPER.readValue(this, Map::class.java) as Map
}
- fun String.normalize(): String = this
- .replace(Regex("\\s+"), " ")
- .replace(Regex(",(\\S)"), ", $1")
- .replace(Regex("\\{(\\S)"), "{ $1")
- .replace(Regex("(\\S)}"), "$1 }")
- .replace(Regex(":(\\S)"), ": $1")
+
+ /**
+ * Find all directly nested code blocks of a given section matching the language and filter
+ */
+ private fun findCodeBlocks(
+ section: Section,
+ language: String,
+ filter: Map = emptyMap()
+ ): List =
+ section.blocks
+ .filterIsInstance()
+ .filter { it.matches(language, filter) }
+
+ /**
+ * Find all setup blocks for a given section, including the setup blocks of the parent sections
+ */
+ fun findSetupCodeBlocks(
+ section: Section,
+ language: String,
+ fiter: Map = emptyMap()
+ ): List {
+ val result = mutableListOf()
+ var currentSection: Section? = section
+ while (currentSection != null) {
+ result.addAll(findCodeBlocks(currentSection, language, fiter))
+ currentSection.blocks
+ .filterIsInstance()
+ .filter { it.title == "Setup" }
+ .forEach { result.addAll(findCodeBlocks(it, language, fiter)) }
+ currentSection = currentSection.parent
+ }
+ return result
+ }
+
+ fun matcher(
+ language: String,
+ filter: Map = emptyMap(),
+ exactly: Boolean = false,
+ setter: KMutableProperty1
+ ): CodeBlockMatcher =
+ matcher(language, filter, exactly) { testData, codeBlock -> setter.set(testData, codeBlock) }
+
+ fun matcher(
+ language: String,
+ filter: Map = emptyMap(),
+ exactly: Boolean = false,
+ setter: (T, CodeBlock) -> Unit
+ ): CodeBlockMatcher =
+ object : CodeBlockMatcher(language, filter, exactly) {
+ override fun set(testData: T, codeBlock: CodeBlock) {
+ setter(testData, codeBlock)
+ }
+ }
+
}
}
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/CypherTestSuite.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/CypherTestSuite.kt
index f43fdd3f..e79aa0cc 100644
--- a/core/src/test/kotlin/org/neo4j/graphql/utils/CypherTestSuite.kt
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/CypherTestSuite.kt
@@ -1,5 +1,7 @@
package org.neo4j.graphql.utils
+import demo.org.neo4j.graphql.utils.asciidoc.ast.CodeBlock
+import demo.org.neo4j.graphql.utils.asciidoc.ast.Section
import graphql.ExecutionInput
import graphql.GraphQL
import graphql.schema.DataFetcher
@@ -32,27 +34,49 @@ import java.util.function.Consumer
import java.util.regex.Matcher
import java.util.regex.Pattern
-class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTestSuite(
+class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTestSuite(
fileName,
- TEST_CASE_MARKERS,
- GLOBAL_MARKERS
+ listOf(
+ matcher("cypher", exactly = true) { t, c -> t.cypher.add(c) },
+ matcher("json", exactly = true) { t, c -> t.cypherParams.add(c) },
+ matcher("graphql", exactly = true, setter = TestCase::graphqlRequest),
+ matcher("json", mapOf("request" to "true"), setter = TestCase::graphqlRequestVariables),
+ matcher("json", mapOf("response" to "true"), setter = TestCase::graphqlResponse),
+ matcher("json", mapOf("query-config" to "true"), setter = TestCase::queryConfig),
+ )
) {
- override fun testFactory(
- title: String,
- globalBlocks: Map>,
- codeBlocks: Map>,
- ignore: Boolean
- ): List {
- val cypherBlocks = getOrCreateBlocks(codeBlocks, CYPHER_MARKER, "Cypher")
-
- if (ignore) {
- return Collections.singletonList(DynamicTest.dynamicTest("Test Cypher", cypherBlocks.firstOrNull()?.uri) {
- Assumptions.assumeFalse(true)
+ data class TestCase(
+ var schema: CodeBlock,
+ var schemaConfig: CodeBlock?,
+ var testData: List,
+ var cypher: MutableList = mutableListOf(),
+ var cypherParams: MutableList = mutableListOf(),
+ var graphqlRequest: CodeBlock? = null,
+ var graphqlRequestVariables: CodeBlock? = null,
+ var graphqlResponse: CodeBlock? = null,
+ var queryConfig: CodeBlock? = null,
+ )
+
+ override fun createTestCase(section: Section): TestCase? {
+ val schema = findSetupCodeBlocks(section, "graphql", mapOf("schema" to "true")).firstOrNull() ?: return null
+ val schemaConfig = findSetupCodeBlocks(section, "json", mapOf("schema-config" to "true")).firstOrNull()
+ val testData = findSetupCodeBlocks(section, "cypher", mapOf("test-data" to "true"))
+
+ return TestCase(schema, schemaConfig, testData)
+ }
+
+ override fun createTests(testCase: TestCase, section: Section, ignoreReason: String?): List {
+ if (testCase.graphqlRequest == null) {
+ return emptyList()
+ }
+ if (ignoreReason != null) {
+ return listOf(DynamicTest.dynamicTest("Test Cypher", testCase.cypher.firstOrNull()?.uri) {
+ Assumptions.assumeFalse(true) { ignoreReason }
})
}
- val result = createTransformationTask(title, globalBlocks, codeBlocks)
+ val result = createTransformationTask(testCase)
val tests = mutableListOf()
if (DEBUG) {
@@ -60,21 +84,20 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
tests.add(printReplacedParameter(result))
}
if (neo4j != null) {
- val testData = globalBlocks[TEST_DATA_MARKER]?.firstOrNull()
- var response = codeBlocks[GRAPHQL_RESPONSE_IGNORE_ORDER_MARKER]?.firstOrNull()
- var ignoreOrder = false
- if (response != null) {
- ignoreOrder = true
- } else {
- response = getOrCreateBlocks(codeBlocks, GRAPHQL_RESPONSE_MARKER, "GraphQL-Response").firstOrNull()
+ val testData = testCase.testData.firstOrNull()
+ var response = testCase.graphqlResponse
+ if (response == null) {
+ response =
+ createCodeBlock(testCase.graphqlRequest!!, "json", "GraphQL-Response", mapOf("response" to "true"))
+ testCase.graphqlResponse = response
}
if (testData != null && response != null) {
- tests.add(integrationTest(title, globalBlocks, codeBlocks, testData, response, ignoreOrder))
+ tests.add(integrationTest(section.title, testCase))
}
}
if (REFORMAT_TEST_FILE) {
- cypherBlocks.forEach {
- val statement = CypherParser.parse(it.code(), Options.defaultOptions())
+ testCase.cypher.forEach { cypher ->
+ val statement = CypherParser.parse(cypher.content, Options.defaultOptions())
val query = Renderer.getRenderer(
Configuration
.newConfig()
@@ -82,53 +105,50 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
.withPrettyPrint(true)
.build()
).render(statement)
- it.reformattedCode = query
- }
- getOrCreateBlocks(codeBlocks, CYPHER_PARAMS_MARKER, "Cypher Params").forEach {
- val cypherParams = it.code().parseJsonMap()
- it.reformattedCode = MAPPER
- .writerWithDefaultPrettyPrinter()
- .writeValueAsString(cypherParams.toSortedMap())
+ cypher.reformattedContent = query
}
+ (testCase.cypherParams.takeIf { it.isNotEmpty() }
+ ?: createCodeBlock(testCase.cypher.first(), "json", "Cypher Params")?.let { listOf(it) }
+ ?: emptyList())
+ .filter { it.content.isNotBlank() }
+ .forEach { params ->
+ val cypherParams = params.content.parseJsonMap()
+ params.reformattedContent = MAPPER
+ .writerWithDefaultPrettyPrinter()
+ .writeValueAsString(cypherParams.toSortedMap())
+ }
}
- tests.addAll(testCypher(title, cypherBlocks, result))
- tests.addAll(testCypherParams(codeBlocks, result))
+ tests.addAll(testCypher(section.title, testCase.cypher, result))
+ tests.addAll(testCypherParams(testCase.cypher, testCase.cypherParams, result))
return tests
}
private fun createSchema(
- globalBlocks: Map>,
- codeBlocks: Map>,
+ schemaBlock: CodeBlock,
+ schemaConfigBlock: CodeBlock?,
dataFetchingInterceptor: DataFetchingInterceptor? = null
): GraphQLSchema {
- val schemaString = globalBlocks[SCHEMA_MARKER]?.firstOrNull()?.code()
- ?: throw IllegalStateException("Schema should be defined")
- val schemaConfig = (codeBlocks[SCHEMA_CONFIG_MARKER]?.firstOrNull()
- ?: globalBlocks[SCHEMA_CONFIG_MARKER]?.firstOrNull())?.code()
+ val schemaString = schemaBlock.content
+ val schemaConfig = schemaConfigBlock?.content
?.let { return@let MAPPER.readValue(it, SchemaConfig::class.java) }
?: SchemaConfig()
return SchemaBuilder.buildSchema(schemaString, schemaConfig, dataFetchingInterceptor)
}
- private fun createTransformationTask(
- title: String,
- globalBlocks: Map>,
- codeBlocks: Map>
- ): () -> List {
+ private fun createTransformationTask(testCase: TestCase): () -> List {
val transformationTask = FutureTask {
- val schema = createSchema(globalBlocks, codeBlocks)
+ val schema = createSchema(testCase.schema, testCase.schemaConfig)
- val request = codeBlocks[GRAPHQL_MARKER]?.firstOrNull()?.code()
- ?: throw IllegalStateException("missing graphql for $title")
+ val request = testCase.graphqlRequest!!.content
- val requestParams = codeBlocks[GRAPHQL_VARIABLES_MARKER]?.firstOrNull()?.code()?.parseJsonMap()
+ val requestParams = testCase.graphqlRequestVariables?.content?.parseJsonMap()
?: emptyMap()
- val queryContext = codeBlocks[QUERY_CONFIG_MARKER]?.firstOrNull()?.code()
+ val queryContext = testCase.queryConfig?.content
?.let { config -> return@let MAPPER.readValue(config, QueryContext::class.java) }
?: QueryContext()
@@ -163,7 +183,7 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
private fun testCypher(
title: String,
- cypherBlocks: List,
+ cypherBlocks: List,
result: () -> List
): List = cypherBlocks.mapIndexed { index, cypherBlock ->
var name = "Test Cypher"
@@ -177,22 +197,22 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
.build()
val renderer = Renderer.getRenderer(cfg)
- val cypher = cypherBlock.code()
+ val cypher = cypherBlock.content
val expectedNormalized = renderer.render(CypherParser.parse(cypher, PARSE_OPTIONS))
val actual = (result().getOrNull(index)?.query
?: throw IllegalStateException("missing cypher query for $title ($index)"))
val actualNormalized = renderer.render(CypherParser.parse(actual, PARSE_OPTIONS))
if (!Objects.equals(expectedNormalized, actual)) {
- cypherBlock.adjustedCode = actual
+ cypherBlock.generatedContent = actual
}
if (actualNormalized != expectedNormalized) {
- val SPLITTER =
+ val splitter =
"\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n~ source query\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n"
throw AssertionFailedError(
"Cypher does not match",
- expectedNormalized + SPLITTER + cypher,
- actualNormalized + SPLITTER + actual
+ expectedNormalized + splitter + cypher,
+ actualNormalized + splitter + actual
)
// TODO
// throw AssertionFailedError("Cypher does not match", cypher, actual)
@@ -201,11 +221,10 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
}
private fun testCypherParams(
- codeBlocks: Map>,
+ cypherBlocks: List,
+ cypherParamsBlocks: List,
result: () -> List
): List {
- val cypherParamsBlocks = getOrCreateBlocks(codeBlocks, CYPHER_PARAMS_MARKER, "Cypher Params")
-
return cypherParamsBlocks.mapIndexed { index, cypherParamsBlock ->
var name = "Test Cypher Params"
if (cypherParamsBlocks.size > 1) {
@@ -216,21 +235,21 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
?: throw IllegalStateException("Expected a cypher query with index $index")
val actualParamsJson = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(params)
- if (cypherParamsBlock.code().isBlank()) {
+ if (cypherParamsBlock.content.isBlank()) {
if (params.isNotEmpty()) {
- cypherParamsBlock.adjustedCode = actualParamsJson
+ cypherParamsBlock.generatedContent = actualParamsJson
Assertions.fail("No params defined")
}
return@dynamicTest
}
- val expectedCypherParams = cypherParamsBlock.code().parseJsonMap()
+ val expectedCypherParams = cypherParamsBlock.content.parseJsonMap()
val expected = fixNumbers(expectedCypherParams)
val actual = fixNumbers(actualParamsJson.parseJsonMap())
if (!Objects.equals(expected, actual)) {
- cypherParamsBlock.adjustedCode = actualParamsJson
+ cypherParamsBlock.generatedContent = actualParamsJson
}
- val expectedRenamedParameters = codeBlocks[CYPHER_MARKER]?.get(index)?.code()
+ val expectedRenamedParameters = cypherBlocks.getOrNull(index)?.content
?.let { CypherParser.parse(it, PARSE_OPTIONS).catalog.renamedParameters }
if (expectedRenamedParameters != null) {
@@ -249,17 +268,15 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
}
}
- private fun setupDataFetchingInterceptor(testData: ParsedBlock): DataFetchingInterceptor {
+ private fun setupDataFetchingInterceptor(testData: CodeBlock?): DataFetchingInterceptor {
return object : DataFetchingInterceptor {
override fun fetchData(env: DataFetchingEnvironment, delegate: DataFetcher): Any? = neo4j
?.defaultDatabaseService()?.let { db ->
db.executeTransactionally("MATCH (n) DETACH DELETE n")
- if (testData.code().isNotBlank()) {
- testData.code()
- .split(";")
- .filter { it.isNotBlank() }
- .forEach { db.executeTransactionally(it) }
- }
+ testData?.content
+ ?.split(";")
+ ?.filter { it.isNotBlank() }
+ ?.forEach { db.executeTransactionally(it) }
val (cypher, params, type, variable) = delegate.get(env)
return db.executeTransactionally(cypher, params) { result ->
result.stream().map { it[variable] }.let {
@@ -276,51 +293,51 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
private fun integrationTest(
title: String,
- globalBlocks: Map>,
- codeBlocks: Map>,
- testData: ParsedBlock,
- response: ParsedBlock,
- ignoreOrder: Boolean
- ): DynamicNode = DynamicTest.dynamicTest("Integration Test", response.uri) {
- val dataFetchingInterceptor = setupDataFetchingInterceptor(testData)
- val request = codeBlocks[GRAPHQL_MARKER]?.firstOrNull()?.code()
- ?: throw IllegalStateException("missing graphql for $title")
-
-
- val requestParams = codeBlocks[GRAPHQL_VARIABLES_MARKER]?.firstOrNull()?.code()?.parseJsonMap() ?: emptyMap()
-
- val queryContext = codeBlocks[QUERY_CONFIG_MARKER]?.firstOrNull()?.code()
- ?.let { config -> return@let MAPPER.readValue(config, QueryContext::class.java) }
- ?: QueryContext()
-
-
- val schema = createSchema(globalBlocks, codeBlocks, dataFetchingInterceptor)
- val graphql = GraphQL.newGraphQL(schema).build()
- val result = graphql.execute(
- ExecutionInput.newExecutionInput()
- .query(request)
- .variables(requestParams)
- .graphQLContext(mapOf(QueryContext.KEY to queryContext))
- .build()
- )
- Assertions.assertThat(result.errors).isEmpty()
-
- val values = result?.getData()
-
- if (response.code.isEmpty()) {
- val actualCode = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(values)
- response.adjustedCode = actualCode
- } else {
- val expected = fixNumbers(response.code().parseJsonMap())
- val actual = fixNumber(values)
- if (!Objects.equals(expected, actual)) {
+ testCase: TestCase,
+ ): DynamicNode {
+ val graphqlResponse = testCase.graphqlResponse
+ ?: error("missing graphql response for $title")
+
+ return DynamicTest.dynamicTest("Integration Test", graphqlResponse.uri) {
+ val dataFetchingInterceptor = setupDataFetchingInterceptor(testCase.testData.firstOrNull())
+ val request = testCase.graphqlRequest?.content
+ ?: error("missing graphql for $title")
+
+ val requestParams = testCase.graphqlRequestVariables?.content?.parseJsonMap() ?: emptyMap()
+
+ val queryContext = testCase.queryConfig?.content
+ ?.let { config -> return@let MAPPER.readValue(config, QueryContext::class.java) }
+ ?: QueryContext()
+
+
+ val schema = createSchema(testCase.schema, testCase.schemaConfig, dataFetchingInterceptor)
+ val graphql = GraphQL.newGraphQL(schema).build()
+ val result = graphql.execute(
+ ExecutionInput.newExecutionInput()
+ .query(request)
+ .variables(requestParams)
+ .graphQLContext(mapOf(QueryContext.KEY to queryContext))
+ .build()
+ )
+ Assertions.assertThat(result.errors).isEmpty()
+
+ val values = result?.getData()
+
+ if (graphqlResponse.content.isEmpty()) {
val actualCode = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(values)
- response.adjustedCode = actualCode
- }
- if (ignoreOrder) {
- assertEqualIgnoreOrder(expected, actual)
+ graphqlResponse.generatedContent = actualCode
} else {
- Assertions.assertThat(actual).isEqualTo(expected)
+ val expected = fixNumbers(graphqlResponse.content.parseJsonMap())
+ val actual = fixNumber(values)
+ if (!Objects.equals(expected, actual)) {
+ val actualCode = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(values)
+ graphqlResponse.generatedContent = actualCode
+ }
+ if (graphqlResponse.attributes.containsKey("ignore-order")) {
+ assertEqualIgnoreOrder(expected, actual)
+ } else {
+ Assertions.assertThat(actual).isEqualTo(expected)
+ }
}
}
}
@@ -348,27 +365,6 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
private val DEBUG = System.getProperty("neo4j-graphql-java.debug", "false") == "true"
private val CONVERT_NUMBER = System.getProperty("neo4j-graphql-java.convert-number", "true") == "true"
- private const val TEST_DATA_MARKER = "[source,cypher,test-data=true]"
- private const val CYPHER_MARKER = "[source,cypher]"
- private const val GRAPHQL_MARKER = "[source,graphql]"
- private const val GRAPHQL_VARIABLES_MARKER = "[source,json,request=true]"
- private const val GRAPHQL_RESPONSE_MARKER = "[source,json,response=true]"
- private const val GRAPHQL_RESPONSE_IGNORE_ORDER_MARKER = "[source,json,response=true,ignore-order]"
- private const val QUERY_CONFIG_MARKER = "[source,json,query-config=true]"
- private const val CYPHER_PARAMS_MARKER = "[source,json]"
-
- private val TEST_CASE_MARKERS: List = listOf(
- SCHEMA_CONFIG_MARKER,
- GRAPHQL_MARKER,
- GRAPHQL_VARIABLES_MARKER,
- GRAPHQL_RESPONSE_MARKER,
- GRAPHQL_RESPONSE_IGNORE_ORDER_MARKER,
- QUERY_CONFIG_MARKER,
- CYPHER_PARAMS_MARKER,
- CYPHER_MARKER
- )
- private val GLOBAL_MARKERS: List = listOf(SCHEMA_MARKER, SCHEMA_CONFIG_MARKER, TEST_DATA_MARKER)
-
private val DURATION_PATTERN: Pattern = Pattern.compile("^P(.*?)(?:T(.*))?$")
private val PARSE_OPTIONS = Options.newOptions()
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/GraphQLSchemaTestSuite.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/GraphQLSchemaTestSuite.kt
index 694fc2a8..13a6c780 100644
--- a/core/src/test/kotlin/org/neo4j/graphql/utils/GraphQLSchemaTestSuite.kt
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/GraphQLSchemaTestSuite.kt
@@ -1,5 +1,7 @@
package org.neo4j.graphql.utils
+import demo.org.neo4j.graphql.utils.asciidoc.ast.CodeBlock
+import demo.org.neo4j.graphql.utils.asciidoc.ast.Section
import graphql.language.InterfaceTypeDefinition
import graphql.language.UnionTypeDefinition
import graphql.schema.GraphQLScalarType
@@ -9,6 +11,7 @@ import graphql.schema.diff.SchemaDiffSet
import graphql.schema.diff.reporting.CapturingReporter
import graphql.schema.idl.*
import org.assertj.core.api.Assertions.assertThat
+import org.bouncycastle.asn1.x500.style.RFC4519Style.title
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Assumptions
import org.junit.jupiter.api.DynamicNode
@@ -19,48 +22,61 @@ import org.neo4j.graphql.SchemaConfig
import org.opentest4j.AssertionFailedError
import java.util.*
-class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(fileName, TEST_CASE_MARKERS) {
+class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(
+ fileName,
+ listOf(
+ matcher("graphql", exactly = true, setter = TestCase::augmentedSchema),
+ )
+) {
- override fun testFactory(
- title: String,
- globalBlocks: Map>,
- codeBlocks: Map>,
- ignore: Boolean
- ): List {
- val targetSchemaBlock = codeBlocks[GRAPHQL_MARKER]?.first()
+ data class TestCase(
+ var schema: CodeBlock,
+ var schemaConfig: CodeBlock?,
+ var augmentedSchema: CodeBlock? = null,
+ )
+
+ override fun createTestCase(section: Section): TestCase? {
+ val schema = findSetupCodeBlocks(section, "graphql", mapOf("schema" to "true")).firstOrNull() ?: return null
+ val schemaConfig = findSetupCodeBlocks(section, "json", mapOf("schema-config" to "true")).firstOrNull()
+ return TestCase(schema, schemaConfig)
+ }
+
+ override fun createTests(testCase: TestCase, section: Section, ignoreReason: String?): List {
+ val targetSchemaBlock = testCase.augmentedSchema
targetSchemaBlock?.let {
try {
- it.reformattedCode = SCHEMA_PRINTER.print(createMockSchema(it.code()))
+ it.reformattedContent = SCHEMA_PRINTER.print(createMockSchema(it.content))
} catch (ignore: Exception) {
}
}
+ if (targetSchemaBlock == null) {
+ return emptyList()
+ }
val compareSchemaTest = DynamicTest.dynamicTest("compare schema", targetSchemaBlock?.uri) {
- val configBlock = codeBlocks[SCHEMA_CONFIG_MARKER]?.first()
- val config = configBlock?.code()?.let { MAPPER.readValue(it, SchemaConfig::class.java) } ?: SchemaConfig()
+ val configBlock = testCase.schemaConfig
+ val config = configBlock?.content?.let { MAPPER.readValue(it, SchemaConfig::class.java) } ?: SchemaConfig()
- val targetSchema = targetSchemaBlock?.code()
- ?: throw IllegalStateException("missing graphql for $title")
+ val targetSchema = targetSchemaBlock.content
var augmentedSchema: GraphQLSchema? = null
var expectedSchema: GraphQLSchema? = null
try {
- val schema = globalBlocks[SCHEMA_MARKER]?.first()?.code()
- ?: throw IllegalStateException("Schema should be defined")
+ val schema = testCase.schema.content
augmentedSchema = SchemaBuilder.buildSchema(schema, config)
expectedSchema = createMockSchema(targetSchema)
diff(expectedSchema, augmentedSchema)
diff(augmentedSchema, expectedSchema)
- targetSchemaBlock.adjustedCode = SCHEMA_PRINTER.print(augmentedSchema)
+ targetSchemaBlock.generatedContent = SCHEMA_PRINTER.print(augmentedSchema)
} catch (e: Throwable) {
- if (ignore) {
- Assumptions.assumeFalse(true, e.message)
+ if (ignoreReason != null) {
+ Assumptions.assumeFalse(true) { "$ignoreReason ${e.message}" }
} else {
if (augmentedSchema == null) {
Assertions.fail(e)
}
val actualSchema = SCHEMA_PRINTER.print(augmentedSchema)
- targetSchemaBlock.adjustedCode = actualSchema
+ targetSchemaBlock.generatedContent = actualSchema
throw AssertionFailedError("augmented schema differs for '$title'",
expectedSchema?.let { SCHEMA_PRINTER.print(it) } ?: targetSchema,
actualSchema,
@@ -72,6 +88,7 @@ class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(fileName, TES
return Collections.singletonList(compareSchemaTest)
}
+
private fun createMockSchema(targetSchema: String): GraphQLSchema {
val schemaParser = SchemaParser()
@@ -97,8 +114,6 @@ class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(fileName, TES
}
companion object {
- private const val GRAPHQL_MARKER = "[source,graphql]"
- private val TEST_CASE_MARKERS: List = listOf(SCHEMA_CONFIG_MARKER, GRAPHQL_MARKER)
private val SCHEMA_PRINTER = SchemaPrinter(
SchemaPrinter.Options.defaultOptions()
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/AsciiDocParser.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/AsciiDocParser.kt
new file mode 100644
index 00000000..800362ec
--- /dev/null
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/AsciiDocParser.kt
@@ -0,0 +1,142 @@
+package demo.org.neo4j.graphql.utils.asciidoc
+
+import demo.org.neo4j.graphql.utils.asciidoc.ast.*
+import java.io.File
+import java.net.URI
+import java.util.regex.Pattern
+import javax.ws.rs.core.UriBuilder
+
+class AsciiDocParser(
+ fileName: String
+) {
+
+ private val file = File(AsciiDocParser::class.java.getResource("/$fileName")?.toURI()!!)
+ private val srcLocation = File("src/test/resources/", fileName).toURI()
+
+ private var root = Document(srcLocation)
+ private var currentSection: Section = root
+ private var currentDepth: Int = 0
+
+
+ fun parse(): Document {
+ val lines = file.readLines()
+ var title: String?
+
+ var insideCodeblock = false
+ var offset = 0
+
+ val fileContent = StringBuilder()
+
+ root = Document(srcLocation)
+ currentSection = root
+ currentDepth = 0
+ var caption: String? = null
+
+ var currentCodeBlock: CodeBlock? = null
+ var content = StringBuilder()
+
+
+ loop@ for ((lineNr, line) in lines.withIndex()) {
+ fileContent.append(line).append('\n')
+
+ if (line.startsWith("#") || line.startsWith("//")) {
+ offset += line.length + 1
+ continue
+ }
+
+ val headlineMatcher = HEADLINE_PATTERN.matcher(line)
+
+ when {
+
+ headlineMatcher.matches() -> {
+ addBlock(content)
+ val depth = headlineMatcher.group(1).length
+ title = headlineMatcher.group(2)
+ val uri = UriBuilder.fromUri(srcLocation).queryParam("line", lineNr + 1).build()
+ startSection(title, uri, depth)
+ }
+
+ line.startsWith(".") && !insideCodeblock -> {
+ caption = line.substring(1).trim()
+ }
+
+ line.startsWith("[source,") -> {
+ addBlock(content)
+ val uri = UriBuilder.fromUri(srcLocation).queryParam("line", lineNr + 1).build()
+
+ val parts = line.substring(8, line.indexOf("]")).trim().split(",")
+ val language = parts[0]
+ val attributes = parts.slice(1.. {
+ addBlock(content)
+ currentSection.blocks.add(ThematicBreak())
+ }
+
+ line == "----" -> {
+ insideCodeblock = !insideCodeblock
+ if (insideCodeblock) {
+ currentCodeBlock?.start = offset + line.length + 1
+ content = StringBuilder()
+ } else if (currentCodeBlock != null) {
+ currentCodeBlock.end = offset
+ currentCodeBlock.content = content.toString().trim()
+ currentCodeBlock = null
+ content = StringBuilder()
+ }
+ }
+
+ else -> {
+ content.append(line).append("\n")
+ }
+ }
+ offset += line.length + 1 // +1 b/c of newline
+ }
+ addBlock(content)
+ root.content = fileContent.toString()
+ return root
+ }
+
+ private fun addBlock(content: StringBuilder) {
+ val str = content.toString()
+ if (str.trim().isNotEmpty()) {
+ currentSection.let { it.blocks.add(Block(it, str)) }
+ }
+ content.clear()
+ }
+
+ private fun startSection(
+ title: String, uri: URI, depth: Int
+ ) {
+
+ val parent = when {
+ depth > currentDepth -> currentSection
+ depth == currentDepth -> currentSection.parent
+ else -> {
+ var parent = currentSection.parent
+ for (i in 0 until currentDepth - depth) {
+ parent = parent?.parent
+ }
+ parent
+ }
+ } ?: error("cannot create sub-level on null")
+ currentSection = Section(title, uri, parent)
+ .also { parent.blocks.add(it) }
+
+ currentDepth = depth
+ }
+
+ companion object {
+ private val HEADLINE_PATTERN: Pattern = Pattern.compile("^(=+) (.*)$")
+ }
+}
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Block.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Block.kt
new file mode 100644
index 00000000..ed7067d1
--- /dev/null
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Block.kt
@@ -0,0 +1,11 @@
+package demo.org.neo4j.graphql.utils.asciidoc.ast
+
+class Block(
+ parent: StructuralNode,
+ val content: String
+) : StructuralNode(parent) {
+
+ override fun toString(): String {
+ return "Block(content='$content')"
+ }
+}
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/CodeBlock.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/CodeBlock.kt
new file mode 100644
index 00000000..d2253973
--- /dev/null
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/CodeBlock.kt
@@ -0,0 +1,39 @@
+package demo.org.neo4j.graphql.utils.asciidoc.ast
+
+import java.net.URI
+
+class CodeBlock(
+ val uri: URI,
+ val language: String,
+ override val parent: Section,
+ val attributes: Map
+) : StructuralNode(parent) {
+
+ var caption: String? = null
+
+ var start: Int? = null
+ var end: Int? = null
+
+ lateinit var content: String
+
+ /**
+ * The content that was generated but diffs to the current content
+ */
+ var generatedContent: String? = null
+
+ /**
+ * The original content reformatted
+ */
+ var reformattedContent: String? = null
+
+ val marker: String
+ get() = "[source,$language${attributes.map { ",${it.key}${it.value?.let { "=${it}" } ?: ""}" }.joinToString()}]"
+
+ override fun toString(): String {
+ return "CodeBlock(language='$language', attributes=$attributes)"
+ }
+
+ fun matches(language: String, filter: Map = emptyMap(), exactly: Boolean = false) =
+ this.language == language && filter.all { (k, v) -> attributes[k] == v } && (!exactly || attributes.size == filter.size)
+
+}
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Document.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Document.kt
new file mode 100644
index 00000000..de9b67a2
--- /dev/null
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Document.kt
@@ -0,0 +1,11 @@
+package demo.org.neo4j.graphql.utils.asciidoc.ast
+
+import java.net.URI
+
+class Document(
+ uri: URI,
+) : Section(uri.path.substringAfterLast('/'), uri, null) {
+
+ lateinit var content: String
+
+}
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Section.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Section.kt
new file mode 100644
index 00000000..1e09e814
--- /dev/null
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/Section.kt
@@ -0,0 +1,14 @@
+package demo.org.neo4j.graphql.utils.asciidoc.ast
+
+import java.net.URI
+
+open class Section(
+ val title: String,
+ val uri: URI,
+ override val parent: Section?,
+) : StructuralNode(parent) {
+
+ override fun toString(): String {
+ return "Section(title='$title')"
+ }
+}
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/StructuralNode.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/StructuralNode.kt
new file mode 100644
index 00000000..61c89c28
--- /dev/null
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/StructuralNode.kt
@@ -0,0 +1,7 @@
+package demo.org.neo4j.graphql.utils.asciidoc.ast
+
+sealed class StructuralNode(
+ open val parent: StructuralNode?
+) {
+ val blocks = mutableListOf()
+}
diff --git a/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/ThematicBreak.kt b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/ThematicBreak.kt
new file mode 100644
index 00000000..7199db15
--- /dev/null
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/asciidoc/ast/ThematicBreak.kt
@@ -0,0 +1,3 @@
+package demo.org.neo4j.graphql.utils.asciidoc.ast
+
+class ThematicBreak: StructuralNode(null)
diff --git a/core/src/test/resources/augmentation-tests.adoc b/core/src/test/resources/augmentation-tests.adoc
index fea89c52..8c9c708c 100644
--- a/core/src/test/resources/augmentation-tests.adoc
+++ b/core/src/test/resources/augmentation-tests.adoc
@@ -2,8 +2,9 @@
= Augmentation Tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
interface HasMovies { movies:[Movie] }
diff --git a/core/src/test/resources/custom-fields.adoc b/core/src/test/resources/custom-fields.adoc
index 232e6f4b..04b35704 100644
--- a/core/src/test/resources/custom-fields.adoc
+++ b/core/src/test/resources/custom-fields.adoc
@@ -2,8 +2,9 @@
= Custom queries and mutations
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
@@ -41,8 +42,7 @@ type MutationType {
}
----
-== Schema Configuration
-
+.Schema Configuration
[source,json,schema-config=true]
----
{
@@ -50,8 +50,7 @@ type MutationType {
}
----
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE (:Person {name:'Jane'}), (:Person {name:'John'})
@@ -97,8 +96,7 @@ RETURN createPerson {
'''
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE (:Person {name:'Jane'}), (:Person {name:'John'})
diff --git a/core/src/test/resources/cypher-directive-tests.adoc b/core/src/test/resources/cypher-directive-tests.adoc
index 5d1f1d81..b5b02b3e 100644
--- a/core/src/test/resources/cypher-directive-tests.adoc
+++ b/core/src/test/resources/cypher-directive-tests.adoc
@@ -2,8 +2,9 @@
= Cypher Directive Test
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
diff --git a/core/src/test/resources/dynamic-property-tests.adoc b/core/src/test/resources/dynamic-property-tests.adoc
index 85f9b51d..0818d7fb 100644
--- a/core/src/test/resources/dynamic-property-tests.adoc
+++ b/core/src/test/resources/dynamic-property-tests.adoc
@@ -2,8 +2,9 @@
= Property Tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
diff --git a/core/src/test/resources/filter-tests.adoc b/core/src/test/resources/filter-tests.adoc
index 28860110..fbce4d35 100644
--- a/core/src/test/resources/filter-tests.adoc
+++ b/core/src/test/resources/filter-tests.adoc
@@ -2,8 +2,9 @@
= Filter Test TCK
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
enum Gender { female, male }
@@ -36,8 +37,7 @@ type PersonSkills @relation(name: "HAS_SKILL", from: "person", to: "skill") {
}
----
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE (c:Company {name: 'ACME'})
diff --git a/core/src/test/resources/issues/gh-112.adoc b/core/src/test/resources/issues/gh-112.adoc
index bfee67a9..2bf81149 100644
--- a/core/src/test/resources/issues/gh-112.adoc
+++ b/core/src/test/resources/issues/gh-112.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #112: deleting bidirectional relationships
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type User
@@ -14,8 +15,7 @@ type User
}
----
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE
diff --git a/core/src/test/resources/issues/gh-147.adoc b/core/src/test/resources/issues/gh-147.adoc
index cbe97d69..448bfea9 100644
--- a/core/src/test/resources/issues/gh-147.adoc
+++ b/core/src/test/resources/issues/gh-147.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #147: Filtering on Directive in Combination with Filtering on Type Field
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
interface Person {
@@ -35,8 +36,7 @@ enum Genre {
}
----
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE
diff --git a/core/src/test/resources/issues/gh-149.adoc b/core/src/test/resources/issues/gh-149.adoc
index 4beac522..befa0c96 100644
--- a/core/src/test/resources/issues/gh-149.adoc
+++ b/core/src/test/resources/issues/gh-149.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #149: OptimizationStrategy FILTER_AS_MATCH breaks offset/first input attributes for queries
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
diff --git a/core/src/test/resources/issues/gh-160.adoc b/core/src/test/resources/issues/gh-160.adoc
index 4a505971..1faf1602 100644
--- a/core/src/test/resources/issues/gh-160.adoc
+++ b/core/src/test/resources/issues/gh-160.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #160: Incorrect query translation for @property
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type User {
diff --git a/core/src/test/resources/issues/gh-163.adoc b/core/src/test/resources/issues/gh-163.adoc
index a0ff80b1..bccb86b6 100644
--- a/core/src/test/resources/issues/gh-163.adoc
+++ b/core/src/test/resources/issues/gh-163.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #163: problem with optimized FILTER_AS_MATCH strategy
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
diff --git a/core/src/test/resources/issues/gh-169.adoc b/core/src/test/resources/issues/gh-169.adoc
index 97ab6595..3339f7d0 100644
--- a/core/src/test/resources/issues/gh-169.adoc
+++ b/core/src/test/resources/issues/gh-169.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #169: Default values for sorting and paging on fields should be respected
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
diff --git a/core/src/test/resources/issues/gh-170.adoc b/core/src/test/resources/issues/gh-170.adoc
index 98be9989..f58c9de5 100644
--- a/core/src/test/resources/issues/gh-170.adoc
+++ b/core/src/test/resources/issues/gh-170.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #170: wrong mapping starting query from rich relationship
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -24,6 +25,7 @@ type Rated @relation(name:"RATED", from: "user", to: "movie") {
}
----
+.Test Data
[source,cypher,test-data=true]
----
CREATE
diff --git a/core/src/test/resources/issues/gh-190-cypher-directive-with-passThrough.adoc b/core/src/test/resources/issues/gh-190-cypher-directive-with-passThrough.adoc
index d47a8869..0e4f0ec2 100644
--- a/core/src/test/resources/issues/gh-190-cypher-directive-with-passThrough.adoc
+++ b/core/src/test/resources/issues/gh-190-cypher-directive-with-passThrough.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #190: cypher directive with passThrough
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Query {
@@ -23,6 +24,7 @@ type MapsCreated {
}
----
+.Test Data
[source,cypher,test-data=true]
----
CREATE
diff --git a/core/src/test/resources/issues/gh-210.adoc b/core/src/test/resources/issues/gh-210.adoc
index f389c270..11415d23 100644
--- a/core/src/test/resources/issues/gh-210.adoc
+++ b/core/src/test/resources/issues/gh-210.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #210: Nested filters are not working
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
interface Period {
@@ -19,8 +20,6 @@ type Week implements Period {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/issues/gh-245-cypher-directive-on-relationship.adoc b/core/src/test/resources/issues/gh-245-cypher-directive-on-relationship.adoc
index 76d00b99..11b98943 100644
--- a/core/src/test/resources/issues/gh-245-cypher-directive-on-relationship.adoc
+++ b/core/src/test/resources/issues/gh-245-cypher-directive-on-relationship.adoc
@@ -2,8 +2,9 @@
= Cypher Directive Computing Relationship Type To Field Test
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Role @relation(name:"ACTED_IN", from:"actor", to:"movie") {
diff --git a/core/src/test/resources/issues/gh-265-querying-multiple-root-fields.adoc b/core/src/test/resources/issues/gh-265-querying-multiple-root-fields.adoc
index 31d288e1..f88d765f 100644
--- a/core/src/test/resources/issues/gh-265-querying-multiple-root-fields.adoc
+++ b/core/src/test/resources/issues/gh-265-querying-multiple-root-fields.adoc
@@ -2,12 +2,11 @@
= Querying multiple root fields
-== Issue
-
https://github.com/neo4j-graphql/neo4j-graphql-java/issues/265
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
diff --git a/core/src/test/resources/issues/gh-267-field-aliasing-does-not-work-if-using-datafetchinginterceptor.adoc b/core/src/test/resources/issues/gh-267-field-aliasing-does-not-work-if-using-datafetchinginterceptor.adoc
index b05fbc97..9994f9fc 100644
--- a/core/src/test/resources/issues/gh-267-field-aliasing-does-not-work-if-using-datafetchinginterceptor.adoc
+++ b/core/src/test/resources/issues/gh-267-field-aliasing-does-not-work-if-using-datafetchinginterceptor.adoc
@@ -2,12 +2,11 @@
= Field aliasing does not work if using DataFetchingInterceptor
-== Issue
-
https://github.com/neo4j-graphql/neo4j-graphql-java/issues/267
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
diff --git a/core/src/test/resources/issues/gh-27.adoc b/core/src/test/resources/issues/gh-27.adoc
index 4497a529..6c5eef92 100644
--- a/core/src/test/resources/issues/gh-27.adoc
+++ b/core/src/test/resources/issues/gh-27.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #27: Filtering on multi-relationship existence
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
diff --git a/core/src/test/resources/issues/gh-295-wrong-target-node-alias.adoc b/core/src/test/resources/issues/gh-295-wrong-target-node-alias.adoc
index 39a3976a..8aea45f7 100644
--- a/core/src/test/resources/issues/gh-295-wrong-target-node-alias.adoc
+++ b/core/src/test/resources/issues/gh-295-wrong-target-node-alias.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #295: Wrong node name used for end node in rich relationship
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person{
@@ -24,8 +25,6 @@ type Person_HAS_Target_Book @relation(name: "HAS", from: "source", to: "target",
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/issues/gh-299-incorrect-mutation-translation-for-IDs-with-property-aliases.adoc b/core/src/test/resources/issues/gh-299-incorrect-mutation-translation-for-IDs-with-property-aliases.adoc
index 4d93fbb2..ae7c197c 100644
--- a/core/src/test/resources/issues/gh-299-incorrect-mutation-translation-for-IDs-with-property-aliases.adoc
+++ b/core/src/test/resources/issues/gh-299-incorrect-mutation-translation-for-IDs-with-property-aliases.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #299: Incorrect mutation translation for IDs with @property
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
diff --git a/core/src/test/resources/issues/gh-45.adoc b/core/src/test/resources/issues/gh-45.adoc
index eb54ce6e..5ea1f04a 100644
--- a/core/src/test/resources/issues/gh-45.adoc
+++ b/core/src/test/resources/issues/gh-45.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #45: A schema for tree-like structure fails with duplicate fields
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Category {
diff --git a/core/src/test/resources/issues/gh-47.adoc b/core/src/test/resources/issues/gh-47.adoc
index 57fa04cc..cae81524 100644
--- a/core/src/test/resources/issues/gh-47.adoc
+++ b/core/src/test/resources/issues/gh-47.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #47: lack of filtering for null values
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Company {
diff --git a/core/src/test/resources/issues/gh-65.adoc b/core/src/test/resources/issues/gh-65.adoc
index 1ee6bd31..42705b48 100644
--- a/core/src/test/resources/issues/gh-65.adoc
+++ b/core/src/test/resources/issues/gh-65.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #65: Filtering on children through parent fields generates logically invalid cypher
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type SurveyTemplate{
@@ -17,8 +18,7 @@ type SurveyResponse{
}
----
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE (tA:SurveyTemplate{ uid: 'a' })
diff --git a/core/src/test/resources/issues/gh-85.adoc b/core/src/test/resources/issues/gh-85.adoc
index 3df19b78..f8af45f1 100644
--- a/core/src/test/resources/issues/gh-85.adoc
+++ b/core/src/test/resources/issues/gh-85.adoc
@@ -2,8 +2,9 @@
= GitHub Issue #85: not-supported cypher directive with scalar result
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -28,8 +29,7 @@ type Mutation {
}
----
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE (:User:Person{ name: 'Andreas' });
diff --git a/core/src/test/resources/movie-tests.adoc b/core/src/test/resources/movie-tests.adoc
index 6f763cf1..7c3a78d7 100644
--- a/core/src/test/resources/movie-tests.adoc
+++ b/core/src/test/resources/movie-tests.adoc
@@ -2,8 +2,9 @@
= Movie Test TCK
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
diff --git a/core/src/test/resources/optimized-query-for-filter.adoc b/core/src/test/resources/optimized-query-for-filter.adoc
index c13c10a4..5fc680b1 100644
--- a/core/src/test/resources/optimized-query-for-filter.adoc
+++ b/core/src/test/resources/optimized-query-for-filter.adoc
@@ -2,8 +2,9 @@
= Translator Tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
diff --git a/core/src/test/resources/property-tests.adoc b/core/src/test/resources/property-tests.adoc
index 16250f24..ca96216e 100644
--- a/core/src/test/resources/property-tests.adoc
+++ b/core/src/test/resources/property-tests.adoc
@@ -2,8 +2,9 @@
= Property Tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
diff --git a/core/src/test/resources/relationship-tests.adoc b/core/src/test/resources/relationship-tests.adoc
index 3df5352b..e2efa37c 100644
--- a/core/src/test/resources/relationship-tests.adoc
+++ b/core/src/test/resources/relationship-tests.adoc
@@ -2,8 +2,9 @@
= Relationship Tests TCK
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Team {
diff --git a/core/src/test/resources/schema-operations-tests.adoc b/core/src/test/resources/schema-operations-tests.adoc
index 91fa1707..583f0d18 100644
--- a/core/src/test/resources/schema-operations-tests.adoc
+++ b/core/src/test/resources/schema-operations-tests.adoc
@@ -2,8 +2,9 @@
= Schema operations tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person { name: String }
diff --git a/core/src/test/resources/tck-test-files/cypher/advanced-filtering.adoc b/core/src/test/resources/tck-test-files/cypher/advanced-filtering.adoc
index a966411a..1be3f8eb 100644
--- a/core/src/test/resources/tck-test-files/cypher/advanced-filtering.adoc
+++ b/core/src/test/resources/tck-test-files/cypher/advanced-filtering.adoc
@@ -4,8 +4,9 @@
Tests advanced filtering.
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -24,9 +25,7 @@ type Genre {
}
----
-== Configuration
-
-.Configuration
+.Schema Configuration
[source,json,schema-config=true]
----
{
diff --git a/core/src/test/resources/tck-test-files/cypher/directives/ignore.adoc b/core/src/test/resources/tck-test-files/cypher/directives/ignore.adoc
index fb0b9d71..fb7ffc2b 100644
--- a/core/src/test/resources/tck-test-files/cypher/directives/ignore.adoc
+++ b/core/src/test/resources/tck-test-files/cypher/directives/ignore.adoc
@@ -4,8 +4,9 @@
Tests that the @ignore directive works as expected.
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type User {
@@ -16,8 +17,6 @@ type User {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/tck-test-files/cypher/pagination.adoc b/core/src/test/resources/tck-test-files/cypher/pagination.adoc
index f99b82ab..f26cab02 100644
--- a/core/src/test/resources/tck-test-files/cypher/pagination.adoc
+++ b/core/src/test/resources/tck-test-files/cypher/pagination.adoc
@@ -4,8 +4,9 @@
Tests for queries including reserved arguments `skip` and `limit`.
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -26,8 +27,6 @@ input ActorOptions {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/tck-test-files/cypher/sort.adoc b/core/src/test/resources/tck-test-files/cypher/sort.adoc
index 20f050b0..45617bae 100644
--- a/core/src/test/resources/tck-test-files/cypher/sort.adoc
+++ b/core/src/test/resources/tck-test-files/cypher/sort.adoc
@@ -4,8 +4,9 @@
Tests for queries including reserved arguments `skip` and `limit`.
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -31,8 +32,6 @@ input GenreSort {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/tck-test-files/cypher/types/datetime.adoc b/core/src/test/resources/tck-test-files/cypher/types/datetime.adoc
index ef9f8155..3287c41a 100644
--- a/core/src/test/resources/tck-test-files/cypher/types/datetime.adoc
+++ b/core/src/test/resources/tck-test-files/cypher/types/datetime.adoc
@@ -4,8 +4,9 @@
Tests DateTime operations.
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -14,8 +15,6 @@ type Movie {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
@@ -27,8 +26,7 @@ type Movie {
}
----
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE
diff --git a/core/src/test/resources/tck-test-files/cypher/where.adoc b/core/src/test/resources/tck-test-files/cypher/where.adoc
index 04031c71..b5b2c8a2 100644
--- a/core/src/test/resources/tck-test-files/cypher/where.adoc
+++ b/core/src/test/resources/tck-test-files/cypher/where.adoc
@@ -4,8 +4,9 @@
Tests for queries using `options::useWhereFilter`
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Actor {
@@ -21,8 +22,6 @@ type Movie {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/tck-test-files/schema/directives/ignore.adoc b/core/src/test/resources/tck-test-files/schema/directives/ignore.adoc
index a4c25cad..844b5ff1 100644
--- a/core/src/test/resources/tck-test-files/schema/directives/ignore.adoc
+++ b/core/src/test/resources/tck-test-files/schema/directives/ignore.adoc
@@ -4,8 +4,9 @@
Tests that the @ignore directive works as expected.
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type User {
@@ -16,8 +17,6 @@ type User {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/tck-test-files/schema/relationship.adoc b/core/src/test/resources/tck-test-files/schema/relationship.adoc
index ba3b68ce..46893427 100644
--- a/core/src/test/resources/tck-test-files/schema/relationship.adoc
+++ b/core/src/test/resources/tck-test-files/schema/relationship.adoc
@@ -4,8 +4,9 @@
Tests that the provided typeDefs return the correct schema (with relationships).
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Actor {
@@ -18,8 +19,6 @@ type Movie {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/tck-test-files/schema/simple.adoc b/core/src/test/resources/tck-test-files/schema/simple.adoc
index 21f82b3f..ce90be9b 100644
--- a/core/src/test/resources/tck-test-files/schema/simple.adoc
+++ b/core/src/test/resources/tck-test-files/schema/simple.adoc
@@ -4,8 +4,9 @@
Tests that the provided typeDefs return the correct schema.
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -16,8 +17,6 @@ type Movie {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/tck-test-files/schema/types/arrays.adoc b/core/src/test/resources/tck-test-files/schema/types/arrays.adoc
index ff5b12e2..bf9cd9d1 100644
--- a/core/src/test/resources/tck-test-files/schema/types/arrays.adoc
+++ b/core/src/test/resources/tck-test-files/schema/types/arrays.adoc
@@ -4,8 +4,9 @@
Tests that the provided typeDefs return the correct schema.
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -14,8 +15,6 @@ type Movie {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/tck-test-files/schema/types/datetime.adoc b/core/src/test/resources/tck-test-files/schema/types/datetime.adoc
index e8757cc2..48b7e731 100644
--- a/core/src/test/resources/tck-test-files/schema/types/datetime.adoc
+++ b/core/src/test/resources/tck-test-files/schema/types/datetime.adoc
@@ -4,8 +4,9 @@
Tests that the provided typeDefs return the correct schema.
-== Inputs
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Movie {
@@ -14,8 +15,6 @@ type Movie {
}
----
-== Configuration
-
.Configuration
[source,json,schema-config=true]
----
diff --git a/core/src/test/resources/translator-tests-custom-scalars.adoc b/core/src/test/resources/translator-tests-custom-scalars.adoc
index f74dd131..d1b7c97b 100644
--- a/core/src/test/resources/translator-tests-custom-scalars.adoc
+++ b/core/src/test/resources/translator-tests-custom-scalars.adoc
@@ -2,8 +2,9 @@
= Translator Tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
scalar Date
diff --git a/core/src/test/resources/translator-tests1.adoc b/core/src/test/resources/translator-tests1.adoc
index 6c1437b4..f6d3ca88 100644
--- a/core/src/test/resources/translator-tests1.adoc
+++ b/core/src/test/resources/translator-tests1.adoc
@@ -2,8 +2,9 @@
= Translator Tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type Person {
diff --git a/core/src/test/resources/translator-tests2.adoc b/core/src/test/resources/translator-tests2.adoc
index 9d7f94ee..9d3bea61 100644
--- a/core/src/test/resources/translator-tests2.adoc
+++ b/core/src/test/resources/translator-tests2.adoc
@@ -2,8 +2,9 @@
= Translator Tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type User {
diff --git a/core/src/test/resources/translator-tests3.adoc b/core/src/test/resources/translator-tests3.adoc
index 91195fba..bb68545a 100644
--- a/core/src/test/resources/translator-tests3.adoc
+++ b/core/src/test/resources/translator-tests3.adoc
@@ -2,8 +2,9 @@
= Translator Tests
-== Schema
+== Setup
+.Schema
[source,graphql,schema=true]
----
type User {
@@ -18,8 +19,7 @@ type Referral @relation (name:"REFERRED_BY", from:"referredBy", to: "user", dire
}
----
-== Test Data
-
+.Test Data
[source,cypher,test-data=true]
----
CREATE