diff --git a/core/pom.xml b/core/pom.xml
index 1b62676b..08036cb5 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -48,7 +48,13 @@
org.neo4j
neo4j-cypher-dsl
- 2024.0.3
+ ${neo4j-cypher-dsl.version}
+
+
+ org.neo4j
+ neo4j-cypher-dsl-parser
+ ${neo4j-cypher-dsl.version}
+ test
com.graphql-java
@@ -94,6 +100,17 @@
${junit-jupiter.version}
test
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.17.2
+
+
+ com.fasterxml.jackson.module
+ jackson-module-kotlin
+ 2.17.2
+ test
+
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 d11a12fc..58219385 100644
--- a/core/src/test/kotlin/org/neo4j/graphql/utils/AsciiDocTestSuite.kt
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/AsciiDocTestSuite.kt
@@ -1,13 +1,13 @@
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 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.math.BigInteger
import java.net.URI
import java.util.*
import java.util.regex.Pattern
@@ -57,6 +57,7 @@ open class AsciiDocTestSuite(
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()
@@ -153,6 +154,10 @@ open class AsciiDocTestSuite(
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(
@@ -207,29 +212,40 @@ open class AsciiDocTestSuite(
}
}
+ private fun reformatTestFile() {
+ val content = generateAdjustedFileContent { it.reformattedCode }
+ FileWriter(File("src/test/resources/", fileName)).use {
+ it.write(content)
+ }
+ }
+
private fun printAdjustedTestFile() {
val rebuildTest = generateAdjustedFileContent()
if (!Objects.equals(rebuildTest, fileContent.toString())) {
// This special exception will be handled by intellij so that you can diff directly with the file
throw FileComparisonFailure(
- null, rebuildTest, fileContent.toString(),
- null, File("src/test/resources/", fileName).absolutePath
+ null, fileContent.toString(), rebuildTest,
+ File("src/test/resources/", fileName).absolutePath, null
)
}
}
- private fun generateAdjustedFileContent(): String {
+ private fun generateAdjustedFileContent(extractor: (ParsedBlock) -> String? = { it.adjustedCode }): String {
knownBlocks.sortWith(compareByDescending { it.start }
.thenByDescending { testCaseMarkers.indexOf(it.marker) })
val rebuildTest = StringBuffer(fileContent)
- knownBlocks.filter { it.adjustedCode != null }.forEach { block ->
- val start = block.start ?: throw IllegalArgumentException("unknown start position")
- if (block.end == null) {
- rebuildTest.insert(start, ".${block.headline}\n${block.marker}\n----\n${block.adjustedCode}\n----\n\n")
- } else {
- rebuildTest.replace(start, block.end!!, block.adjustedCode + "\n")
+ knownBlocks.filter { extractor(it) != null }
+ .forEach { block ->
+ val start = block.start ?: throw IllegalArgumentException("unknown start position")
+ if (block.end == null) {
+ rebuildTest.insert(
+ start,
+ ".${block.headline}\n${block.marker}\n----\n${extractor(block)}\n----\n\n"
+ )
+ } else {
+ rebuildTest.replace(start, block.end!!, extractor(block) + "\n")
+ }
}
- }
return rebuildTest.toString()
}
@@ -278,8 +294,9 @@ open class AsciiDocTestSuite(
*/
val FLATTEN_TESTS = System.getProperty("neo4j-graphql-java.flatten-tests", "false") == "true"
val GENERATE_TEST_FILE_DIFF = System.getProperty("neo4j-graphql-java.generate-test-file-diff", "true") == "true"
+ 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()
+ val MAPPER = ObjectMapper().registerKotlinModule()
val HEADLINE_PATTERN: Pattern = Pattern.compile("^(=+) (.*)$")
const val SCHEMA_MARKER = "[source,graphql,schema=true]"
@@ -330,18 +347,6 @@ open class AsciiDocTestSuite(
}
}
- fun fixNumber(v: Any?): Any? = when (v) {
- is Float -> v.toDouble()
- is Int -> v.toLong()
- is BigInteger -> v.toLong()
- is Iterable<*> -> v.map { fixNumber(it) }
- is Sequence<*> -> v.map { fixNumber(it) }
- is Map<*, *> -> v.mapValues { fixNumber(it.value) }
- else -> v
- }
-
- fun fixNumbers(params: Map) = params.mapValues { (_, v) -> fixNumber(v) }
-
fun String.parseJsonMap(): Map = this.let {
@Suppress("UNCHECKED_CAST")
MAPPER.readValue(this, Map::class.java) as Map
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 8892a77e..f43fdd3f 100644
--- a/core/src/test/kotlin/org/neo4j/graphql/utils/CypherTestSuite.kt
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/CypherTestSuite.kt
@@ -10,26 +10,32 @@ import org.assertj.core.api.InstanceOfAssertFactories
import org.junit.jupiter.api.Assumptions
import org.junit.jupiter.api.DynamicNode
import org.junit.jupiter.api.DynamicTest
+import org.neo4j.cypherdsl.core.renderer.Configuration
+import org.neo4j.cypherdsl.core.renderer.Renderer
+import org.neo4j.cypherdsl.parser.CypherParser
+import org.neo4j.cypherdsl.parser.Options
+import org.neo4j.driver.internal.InternalIsoDuration
+import org.neo4j.driver.types.IsoDuration
import org.neo4j.graphql.*
import org.neo4j.harness.Neo4j
import org.opentest4j.AssertionFailedError
+import java.math.BigInteger
+import java.time.Duration
+import java.time.LocalTime
+import java.time.Period
+import java.time.ZonedDateTime
+import java.time.format.DateTimeFormatter
+import java.time.format.DateTimeParseException
import java.util.*
import java.util.concurrent.FutureTask
import java.util.function.Consumer
+import java.util.regex.Matcher
+import java.util.regex.Pattern
class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTestSuite(
fileName,
- 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
- ),
- listOf(SCHEMA_MARKER, SCHEMA_CONFIG_MARKER, TEST_DATA_MARKER)
+ TEST_CASE_MARKERS,
+ GLOBAL_MARKERS
) {
override fun testFactory(
@@ -66,6 +72,26 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
tests.add(integrationTest(title, globalBlocks, codeBlocks, testData, response, ignoreOrder))
}
}
+ if (REFORMAT_TEST_FILE) {
+ cypherBlocks.forEach {
+ val statement = CypherParser.parse(it.code(), Options.defaultOptions())
+ val query = Renderer.getRenderer(
+ Configuration
+ .newConfig()
+ .withIndentStyle(Configuration.IndentStyle.TAB)
+ .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())
+ }
+
+ }
tests.addAll(testCypher(title, cypherBlocks, result))
tests.addAll(testCypherParams(codeBlocks, result))
@@ -145,17 +171,31 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
name += " (${index + 1})"
}
DynamicTest.dynamicTest(name, cypherBlock.uri) {
+ val cfg = Configuration.newConfig()
+ .withPrettyPrint(true)
+ .withGeneratedNames(true)
+ .build()
+ val renderer = Renderer.getRenderer(cfg)
+
val cypher = cypherBlock.code()
- val expected = cypher.normalize()
+ 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 = actual.normalize()
+ val actualNormalized = renderer.render(CypherParser.parse(actual, PARSE_OPTIONS))
- if (!Objects.equals(expected, actual)) {
+ if (!Objects.equals(expectedNormalized, actual)) {
cypherBlock.adjustedCode = actual
}
- if (actualNormalized != expected) {
- throw AssertionFailedError("Cypher does not match", cypher, actual)
+ if (actualNormalized != expectedNormalized) {
+ val SPLITTER =
+ "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n~ source query\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n"
+ throw AssertionFailedError(
+ "Cypher does not match",
+ expectedNormalized + SPLITTER + cypher,
+ actualNormalized + SPLITTER + actual
+ )
+ // TODO
+ // throw AssertionFailedError("Cypher does not match", cypher, actual)
}
}
}
@@ -172,24 +212,39 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
name += " (${index + 1})"
}
DynamicTest.dynamicTest(name, cypherParamsBlock.uri) {
- val resultParams = result().getOrNull(index)?.params
+ val (cypher, params) = result().getOrNull(index)
?: throw IllegalStateException("Expected a cypher query with index $index")
- val actualParams = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(resultParams)
+ val actualParamsJson = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(params)
if (cypherParamsBlock.code().isBlank()) {
- if (resultParams.isNotEmpty()) {
- cypherParamsBlock.adjustedCode = actualParams
+ if (params.isNotEmpty()) {
+ cypherParamsBlock.adjustedCode = actualParamsJson
Assertions.fail("No params defined")
}
return@dynamicTest
}
- val cypherParams = cypherParamsBlock.code().parseJsonMap()
- val expected = fixNumbers(cypherParams)
- val actual = fixNumbers(resultParams)
+ val expectedCypherParams = cypherParamsBlock.code().parseJsonMap()
+ val expected = fixNumbers(expectedCypherParams)
+ val actual = fixNumbers(actualParamsJson.parseJsonMap())
if (!Objects.equals(expected, actual)) {
- cypherParamsBlock.adjustedCode = actualParams
+ cypherParamsBlock.adjustedCode = actualParamsJson
+ }
+
+ val expectedRenamedParameters = codeBlocks[CYPHER_MARKER]?.get(index)?.code()
+ ?.let { CypherParser.parse(it, PARSE_OPTIONS).catalog.renamedParameters }
+
+ if (expectedRenamedParameters != null) {
+ val actualRenamedParameters = CypherParser.parse(cypher, PARSE_OPTIONS).catalog
+ .renamedParameters
+ .map { (k, v) -> v to k }
+ .toMap()
+ val remappedExpectedCypherParams = expectedCypherParams.mapKeys { (k, _) ->
+ actualRenamedParameters[expectedRenamedParameters[k]] ?: k
+ }
+ assertCypherParams(remappedExpectedCypherParams, params)
+ } else {
+ assertCypherParams(expectedCypherParams, params)
}
- Assertions.assertThat(actual).isEqualTo(expected)
}
}
}
@@ -245,7 +300,7 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
ExecutionInput.newExecutionInput()
.query(request)
.variables(requestParams)
- .context(queryContext)
+ .graphQLContext(mapOf(QueryContext.KEY to queryContext))
.build()
)
Assertions.assertThat(result.errors).isEmpty()
@@ -291,6 +346,7 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
companion object {
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]"
@@ -300,5 +356,160 @@ class CypherTestSuite(fileName: String, val neo4j: Neo4j? = null) : AsciiDocTest
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()
+ .createSortedMaps(true)
+ // TODO enable after https://github.com/neo4j/cypher-dsl/issues/1059 is solved
+ // .alwaysCreateRelationshipsLTR(true)
+ .build()
+
+ private fun assertCypherParams(expected: Map, actual: Map) {
+ Assertions.assertThat(actual).asInstanceOf(InstanceOfAssertFactories.MAP)
+ .hasSize(expected.size)
+ .containsOnlyKeys(*expected.keys.toTypedArray())
+ .allSatisfy({ key, value -> assertCypherParam(expected[key], value) })
+ }
+
+ private fun assertCypherParam(expected: Any?, actual: Any?) {
+ when (expected) {
+ is Int -> when (actual) {
+ is Double -> {
+ Assertions.assertThat(actual).isEqualTo(expected.toDouble())
+ return
+ }
+
+ is Long -> {
+ Assertions.assertThat(actual).isEqualTo(expected.toLong())
+ return
+ }
+
+ is BigInteger -> {
+ Assertions.assertThat(actual).isEqualTo(expected.toBigInteger())
+ return
+ }
+ }
+
+ is String -> {
+ try {
+ val expectedDate = ZonedDateTime.parse(expected)
+ val actualDate = ZonedDateTime.parse(actual as String)
+ Assertions.assertThat(actualDate).isEqualTo(expectedDate)
+ return
+ } catch (ignore: DateTimeParseException) {
+ }
+ try {
+ val expectedTime = LocalTime.parse(expected, DateTimeFormatter.ISO_TIME)
+ val actualTime = LocalTime.parse(actual as String)
+ Assertions.assertThat(actualTime).isEqualTo(expectedTime)
+ return
+ } catch (ignore: DateTimeParseException) {
+ }
+ try {
+ val expectedTime = LocalTime.parse(expected, DateTimeFormatter.ISO_TIME)
+ val actualTime = LocalTime.parse(actual as String)
+ Assertions.assertThat(actualTime).isEqualTo(expectedTime)
+ return
+ } catch (ignore: DateTimeParseException) {
+ }
+ try {
+ parseDuration(expected)?.let { expectedDuration ->
+ parseDuration(actual as String)?.let { actualDuration ->
+ Assertions.assertThat(actualDuration).isEqualTo(expectedDuration)
+ return
+ }
+ }
+ } catch (ignore: DateTimeParseException) {
+ }
+ }
+
+ is Map<*, *> -> {
+ if (actual is Number) {
+ val low = expected["low"] as? Number
+ val high = expected["high"] as? Number
+ if (low != null && high != null && expected.size == 2) {
+ // this is to convert the js bigint into a java long
+ val highLong = high.toLong() shl 32
+ val lowLong = low.toLong() and 0xFFFFFFFFL
+ val expectedLong = highLong or lowLong
+ when (actual) {
+ is BigInteger -> Assertions.assertThat(actual.toLong()).isEqualTo(expectedLong)
+ is Int -> Assertions.assertThat(actual.toLong()).isEqualTo(expectedLong)
+ is Long -> Assertions.assertThat(actual).isEqualTo(expectedLong)
+ else -> Assertions.fail("Unexpected type ${actual::class.java}")
+ }
+ return
+ }
+ }
+ }
+
+ is Iterable<*> -> {
+ if (actual is Iterable<*>) {
+ Assertions.assertThat(actual).hasSize(expected.count())
+ expected.forEachIndexed { index, expectedValue ->
+ assertCypherParam(expectedValue, actual.elementAt(index))
+ }
+ return
+ }
+ }
+ }
+ Assertions.assertThat(actual).isEqualTo(expected)
+ }
+
+ private fun fixNumber(v: Any?): Any? = when (v) {
+ is Double -> v.toDouble().convertNumber()
+ is Float -> v.toDouble().convertNumber()
+ is Int -> v.toLong()
+ is BigInteger -> v.toLong()
+ is Iterable<*> -> v.map { fixNumber(it) }
+ is Sequence<*> -> v.map { fixNumber(it) }
+ is Map<*, *> -> {
+ val low = v["low"] as? Number
+ val high = v["high"] as? Number
+ if (low != null && high != null && v.size == 2) {
+ // this is to convert th js bigint into a java long
+ val highLong = high.toLong() shl 32
+ val lowLong = low.toLong() and 0xFFFFFFFFL
+ highLong or lowLong
+ } else {
+ v.mapValues { fixNumber(it.value) }
+ }
+ }
+
+ else -> v
+ }
+
+ private fun fixNumbers(params: Map) = params.mapValues { (_, v) -> fixNumber(v) }
+ private fun Double.convertNumber() = when {
+ CONVERT_NUMBER && this == toLong().toDouble() -> toLong()
+ else -> this
+ }
+
+ private fun parseDuration(text: String): IsoDuration? {
+ val matcher: Matcher = DURATION_PATTERN.matcher(text)
+ if (!matcher.find()) {
+ return null
+ }
+ val periodString = matcher.group(1)
+ val timeString = matcher.group(2)
+ val period = if (!periodString.isNullOrBlank()) Period.parse("P$periodString") else Period.ZERO
+ val duration = if (!timeString.isNullOrBlank()) Duration.parse("PT$timeString") else Duration.ZERO
+ return InternalIsoDuration(period.toTotalMonths(), period.days.toLong(), duration.seconds, duration.nano)
+ }
+
+
}
}
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 8f1c4ae0..694fc2a8 100644
--- a/core/src/test/kotlin/org/neo4j/graphql/utils/GraphQLSchemaTestSuite.kt
+++ b/core/src/test/kotlin/org/neo4j/graphql/utils/GraphQLSchemaTestSuite.kt
@@ -1,9 +1,9 @@
package org.neo4j.graphql.utils
import graphql.language.InterfaceTypeDefinition
+import graphql.language.UnionTypeDefinition
import graphql.schema.GraphQLScalarType
import graphql.schema.GraphQLSchema
-import graphql.schema.GraphQLType
import graphql.schema.diff.SchemaDiff
import graphql.schema.diff.SchemaDiffSet
import graphql.schema.diff.reporting.CapturingReporter
@@ -16,15 +16,10 @@ import org.junit.jupiter.api.DynamicTest
import org.neo4j.graphql.NoOpCoercing
import org.neo4j.graphql.SchemaBuilder
import org.neo4j.graphql.SchemaConfig
-import org.neo4j.graphql.requiredName
import org.opentest4j.AssertionFailedError
import java.util.*
-import java.util.regex.Pattern
-class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(
- fileName,
- listOf(SCHEMA_CONFIG_MARKER, GRAPHQL_MARKER)
-) {
+class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(fileName, TEST_CASE_MARKERS) {
override fun testFactory(
title: String,
@@ -33,6 +28,12 @@ class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(
ignore: Boolean
): List {
val targetSchemaBlock = codeBlocks[GRAPHQL_MARKER]?.first()
+ targetSchemaBlock?.let {
+ try {
+ it.reformattedCode = SCHEMA_PRINTER.print(createMockSchema(it.code()))
+ } catch (ignore: Exception) {
+ }
+ }
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()
@@ -46,27 +47,7 @@ class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(
val schema = globalBlocks[SCHEMA_MARKER]?.first()?.code()
?: throw IllegalStateException("Schema should be defined")
augmentedSchema = SchemaBuilder.buildSchema(schema, config)
- val schemaParser = SchemaParser()
-
- val reg = schemaParser.parse(targetSchema)
- val schemaGenerator = SchemaGenerator()
- val runtimeWiring = RuntimeWiring.newRuntimeWiring()
- reg
- .getTypes(InterfaceTypeDefinition::class.java)
- .forEach { typeDefinition -> runtimeWiring.type(typeDefinition.name) { it.typeResolver { null } } }
- reg
- .scalars()
- .filterNot { entry -> ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(entry.key) }
- .forEach { (name, definition) ->
- runtimeWiring.scalar(
- GraphQLScalarType.newScalar()
- .name(name)
- .definition(definition)
- .coercing(NoOpCoercing)
- .build()
- )
- }
- expectedSchema = schemaGenerator.makeExecutableSchema(reg, runtimeWiring.build())
+ expectedSchema = createMockSchema(targetSchema)
diff(expectedSchema, augmentedSchema)
diff(augmentedSchema, expectedSchema)
@@ -91,9 +72,33 @@ class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(
return Collections.singletonList(compareSchemaTest)
}
+ private fun createMockSchema(targetSchema: String): GraphQLSchema {
+ val schemaParser = SchemaParser()
+
+ val reg = schemaParser.parse(targetSchema)
+ val schemaGenerator = SchemaGenerator()
+ val runtimeWiring = RuntimeWiring.newRuntimeWiring()
+ (reg.getTypes(InterfaceTypeDefinition::class.java)
+ + reg.getTypes(UnionTypeDefinition::class.java))
+ .forEach { typeDefinition -> runtimeWiring.type(typeDefinition.name) { it.typeResolver { null } } }
+ reg
+ .scalars()
+ .filterNot { entry -> ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(entry.key) }
+ .forEach { (name, definition) ->
+ runtimeWiring.scalar(
+ GraphQLScalarType.newScalar()
+ .name(name)
+ .definition(definition)
+ .coercing(NoOpCoercing)
+ .build()
+ )
+ }
+ return schemaGenerator.makeExecutableSchema(reg, runtimeWiring.build())
+ }
+
companion object {
private const val GRAPHQL_MARKER = "[source,graphql]"
- private val METHOD_PATTERN = Pattern.compile("(add|delete|update|merge|create)(.*)")
+ private val TEST_CASE_MARKERS: List = listOf(SCHEMA_CONFIG_MARKER, GRAPHQL_MARKER)
private val SCHEMA_PRINTER = SchemaPrinter(
SchemaPrinter.Options.defaultOptions()
@@ -103,15 +108,6 @@ class GraphQLSchemaTestSuite(fileName: String) : AsciiDocTestSuite(
.includeIntrospectionTypes(false)
)
- fun GraphQLType.splitName(): Pair {
- val m = METHOD_PATTERN.matcher(this.requiredName())
- return if (m.find()) {
- m.group(1) to m.group(2).lowercase()
- } else {
- null to this.requiredName().lowercase()
- }
- }
-
fun diff(augmentedSchema: GraphQLSchema, expected: GraphQLSchema) {
val diffSet = SchemaDiffSet.diffSetFromIntrospection(augmentedSchema, expected)
val capture = CapturingReporter()
diff --git a/core/src/test/resources/cypher-directive-tests.adoc b/core/src/test/resources/cypher-directive-tests.adoc
index f35f4963..5d1f1d81 100644
--- a/core/src/test/resources/cypher-directive-tests.adoc
+++ b/core/src/test/resources/cypher-directive-tests.adoc
@@ -17,7 +17,7 @@ type Query {
person : [Person]
p2: [Person] @cypher(statement:"MATCH (p:Person) RETURN p")
p3(name:String): Person @cypher(statement:"MATCH (p:Person) WHERE p.name = name RETURN p")
- getUser(userId: ID): UserData @cypher(statement: "MATCH (u:User{id: {userId}})-[:CREATED_MAP]->(m:Map) WITH collect({id: m.id, name: m.name}) AS mapsCreated, u RETURN {firstName: u.firstName, lastName: u.lastName, organization: u.organization, mapsCreated: mapsCreated}", passThrough:true)
+ getUser(userId: ID): UserData @cypher(statement: "MATCH (u:User{id: userId})-[:CREATED_MAP]->(m:Map) WITH collect({id: m.id, name: m.name}) AS mapsCreated, u RETURN {firstName: u.firstName, lastName: u.lastName, organization: u.organization, mapsCreated: mapsCreated}", passThrough:true)
}
type Mutation {
createPerson(name:String): Person @cypher(statement:"CREATE (p:Person) SET p.name = name RETURN p")
@@ -408,7 +408,7 @@ query queriesRootQuery {
----
CALL {
WITH $userUserId AS userId
- MATCH (u:User{id: {userId}})-[:CREATED_MAP]->(m:Map) WITH collect({id: m.id, name: m.name}) AS mapsCreated, u RETURN {firstName: u.firstName, lastName: u.lastName, organization: u.organization, mapsCreated: mapsCreated} AS user LIMIT 1
+ MATCH (u:User{id: userId})-[:CREATED_MAP]->(m:Map) WITH collect({id: m.id, name: m.name}) AS mapsCreated, u RETURN {firstName: u.firstName, lastName: u.lastName, organization: u.organization, mapsCreated: mapsCreated} AS user LIMIT 1
}
RETURN user AS user
----
diff --git a/pom.xml b/pom.xml
index f74bfce2..8b9e9fe2 100755
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,7 @@
5.23.0
5.23.0
5.11.0
+ 2024.0.3