From 2b68de4bdf40332694a6d66b25ac9d0bb201cc98 Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 16 Jun 2025 19:55:52 -0700 Subject: [PATCH 1/3] wip: migrate tests to ktor2 --- build.gradle.kts | 1 + .../org/openmbee/flexo/mms/ArtifactAny.kt | 131 ++++---- .../org/openmbee/flexo/mms/BranchCreate.kt | 140 ++++---- .../org/openmbee/flexo/mms/BranchDelete.kt | 12 +- .../org/openmbee/flexo/mms/BranchRead.kt | 43 ++- .../org/openmbee/flexo/mms/BranchUpdate.kt | 18 +- .../org/openmbee/flexo/mms/CommitLdpDc.kt | 11 +- .../kotlin/org/openmbee/flexo/mms/GroupAny.kt | 5 +- .../org/openmbee/flexo/mms/GroupCreate.kt | 118 ------- .../org/openmbee/flexo/mms/GroupLdpDc.kt | 3 +- .../org/openmbee/flexo/mms/LockCreate.kt | 42 +-- .../org/openmbee/flexo/mms/LockLdpDc.kt | 9 - .../org/openmbee/flexo/mms/LockQuery.kt | 86 +++-- .../kotlin/org/openmbee/flexo/mms/LockRead.kt | 52 +-- .../org/openmbee/flexo/mms/LockWrite.kt | 22 +- .../org/openmbee/flexo/mms/ModelCommit.kt | 34 +- .../org/openmbee/flexo/mms/ModelLoad.kt | 92 +++--- .../org/openmbee/flexo/mms/ModelQuery.kt | 158 +++++---- .../org/openmbee/flexo/mms/ModelRead.kt | 45 ++- .../kotlin/org/openmbee/flexo/mms/OrgAny.kt | 5 +- .../kotlin/org/openmbee/flexo/mms/OrgLdpDc.kt | 12 +- .../org/openmbee/flexo/mms/PolicyCreate.kt | 40 +-- .../kotlin/org/openmbee/flexo/mms/RefAny.kt | 11 +- .../kotlin/org/openmbee/flexo/mms/RepoAny.kt | 14 +- .../org/openmbee/flexo/mms/RepoLdpDc.kt | 3 +- .../org/openmbee/flexo/mms/RepoQuery.kt | 35 +- .../org/openmbee/flexo/mms/ScratchAny.kt | 10 +- .../org/openmbee/flexo/mms/ScratchLdpDc.kt | 4 +- .../org/openmbee/flexo/mms/ScratchLoad.kt | 30 +- .../org/openmbee/flexo/mms/ScratchQuery.kt | 99 +++--- .../org/openmbee/flexo/mms/ScratchRead.kt | 22 +- .../org/openmbee/flexo/mms/ScratchUpdate.kt | 30 +- .../flexo/mms/util/BlazegraphBackend.kt | 106 ------ .../org/openmbee/flexo/mms/util/Common.kt | 5 - .../openmbee/flexo/mms/util/Environment.kt | 23 -- .../openmbee/flexo/mms/util/FusekiBackend.kt | 66 ---- .../org/openmbee/flexo/mms/util/Helper.kt | 171 ++++------ .../openmbee/flexo/mms/util/JsonAssertions.kt | 6 +- .../openmbee/flexo/mms/util/KtorAssertions.kt | 136 -------- .../flexo/mms/util/LinkedDataPlatform.kt | 306 +++++++++--------- .../openmbee/flexo/mms/util/RdfAssertions.kt | 13 +- .../org/openmbee/flexo/mms/util/Requests.kt | 110 +++---- 42 files changed, 885 insertions(+), 1394 deletions(-) delete mode 100644 src/test/kotlin/org/openmbee/flexo/mms/GroupCreate.kt delete mode 100644 src/test/kotlin/org/openmbee/flexo/mms/util/BlazegraphBackend.kt delete mode 100644 src/test/kotlin/org/openmbee/flexo/mms/util/FusekiBackend.kt delete mode 100644 src/test/kotlin/org/openmbee/flexo/mms/util/KtorAssertions.kt diff --git a/build.gradle.kts b/build.gradle.kts index b813a441..ca3cdaa7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -71,6 +71,7 @@ dependencies { implementation("io.ktor:ktor-server-netty:$ktorVersion") implementation("io.ktor:ktor-server-status-pages:$ktorVersion") testImplementation("io.ktor:ktor-server-tests:$ktorVersion") + testImplementation("io.kotest.extensions:kotest-assertions-ktor:2.0.0") val logbackVersion = "1.5.18" implementation("ch.qos.logback:logback-classic:$logbackVersion") diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ArtifactAny.kt b/src/test/kotlin/org/openmbee/flexo/mms/ArtifactAny.kt index 46ed81e9..e61f06b1 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ArtifactAny.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ArtifactAny.kt @@ -1,11 +1,16 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.equals.shouldBeEqual -import io.kotest.matchers.nulls.shouldBeNull import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldBeEmpty +import io.kotest.matchers.string.shouldContain import io.kotest.matchers.string.shouldStartWith +import io.ktor.client.request.* +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* +import io.ktor.util.* import org.openmbee.flexo.mms.util.* import org.slf4j.LoggerFactory import java.io.ByteArrayInputStream @@ -13,6 +18,7 @@ import java.util.zip.ZipEntry import java.util.zip.ZipInputStream +@OptIn(InternalAPI::class) open class ArtifactAny : RefAny() { override val logger = LoggerFactory.getLogger(LockAny::class.java) @@ -21,14 +27,14 @@ open class ArtifactAny : RefAny() { init { "post artifact text/plain" { - withTest { + testApplication { httpPost(artifactsPath) { - addHeader("Content-Type", "text/plain") + header("Content-Type", "text/plain") setBody("foo") }.apply { - response shouldHaveStatus HttpStatusCode.Created - response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) - response.contentType() shouldBe ContentType.Text.Plain + this shouldHaveStatus HttpStatusCode.Created + this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) + this.contentType() shouldBe ContentType.Text.Plain } } } @@ -36,46 +42,46 @@ open class ArtifactAny : RefAny() { // Set a content-type with parameters (like utf-8 on text/plain) and assert that parameters have // been removed on returned content type "post artifact text/plain with parameter" { - withTest{ + testApplication { httpPost(artifactsPath) { - addHeader("Content-Type", "text/plain; charset=utf-8") + header("Content-Type", "text/plain; charset=utf-8") setBody("foo") }.apply { - response shouldHaveStatus HttpStatusCode.Created - response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) - response.contentType() shouldBe ContentType.Text.Plain + this shouldHaveStatus HttpStatusCode.Created + this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) + this.contentType() shouldBe ContentType.Text.Plain } } } "get all artifacts empty" { - withTest{ + testApplication { httpGet("$artifactsPath?download") { }.apply { - response shouldHaveStatus HttpStatusCode.NoContent - response.content.shouldBeNull() + this shouldHaveStatus HttpStatusCode.NoContent + this.bodyAsText().shouldBeEmpty() } } } "get all artifacts two artifacts" { - withTest{ + testApplication { httpPost(artifactsPath) { - addHeader("Content-Type", "text/plain") + header("Content-Type", "text/plain") setBody("foo") }.apply { - val locationFile1 = getURI(response.headers[HttpHeaders.Location].toString()) + val locationFile1 = getURI(this.headers[HttpHeaders.Location].toString()) httpPost(artifactsPath) { - addHeader("Content-Type", "application/octet-stream") + header("Content-Type", "application/octet-stream") setBody("bar".toByteArray()) }.apply { - val locationFile2 = getURI(response.headers[HttpHeaders.Location].toString()) + val locationFile2 = getURI(this.headers[HttpHeaders.Location].toString()) httpGet("$artifactsPath?download") {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response.contentType() shouldBe ContentType.Application.Zip + this shouldHaveStatus HttpStatusCode.OK + this.contentType() shouldBe ContentType.Application.Zip - val zipBytes = response.byteContent ?: throw IllegalStateException("Response byteContent is null") + val zipBytes = this.content.toByteArray() val contents = readZipContents(zipBytes) contents.size shouldBe 2 contents["$locationFile1.txt"] shouldBe "foo" @@ -88,7 +94,7 @@ open class ArtifactAny : RefAny() { // Not used http methods that should fail "artifact rejects other methods" { - withTest { + testApplication { onlyAllowsMethods(artifactsPath, setOf( HttpMethod.Head, HttpMethod.Get, @@ -102,79 +108,78 @@ open class ArtifactAny : RefAny() { *********************************************/ "get an artifact by id - turtle" { - withTest{ + testApplication { httpPost(artifactsPath) { - addHeader("Content-Type", "text/plain") + header("Content-Type", "text/plain") setBody("foo".toByteArray()) }.apply { - response shouldHaveStatus HttpStatusCode.Created - response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) - - val uri = getLocation(response.headers[HttpHeaders.Location].toString()) - httpGet(uri) { - }.apply { - response shouldHaveStatus HttpStatusCode.OK - response.contentType() shouldBe ContentType.Text.Plain - response shouldHaveContent "foo" + this shouldHaveStatus HttpStatusCode.Created + this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) + + val uri = getLocation(this.headers[HttpHeaders.Location].toString()) + httpGet(uri) {}.apply { + this shouldHaveStatus HttpStatusCode.OK + this.contentType() shouldBe ContentType.Text.Plain + this.bodyAsText() shouldContain "foo" } } } } "download an artifact by id - text" { - withTest{ + testApplication { httpPost(artifactsPath) { - addHeader("Content-Type", "text/plain") + header("Content-Type", "text/plain") setBody("foo") }.apply { - response shouldHaveStatus HttpStatusCode.Created - response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) + this shouldHaveStatus HttpStatusCode.Created + this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) - val uri = getLocation(response.headers[HttpHeaders.Location].toString()) + val uri = getLocation(this.headers[HttpHeaders.Location].toString()) httpGet("$uri?download") { }.apply { - response shouldHaveStatus HttpStatusCode.OK - response.contentType() shouldBe ContentType.Text.Plain - response shouldHaveContent "foo" + this shouldHaveStatus HttpStatusCode.OK + this.contentType() shouldBe ContentType.Text.Plain + this.bodyAsText() shouldContain "foo" } } } } "download an artifact by id - binary" { - withTest{ + testApplication { httpPost(artifactsPath) { - addHeader("Content-Type", "application/octet-stream") + header("Content-Type", "application/octet-stream") setBody("foo".toByteArray()) }.apply { - response shouldHaveStatus HttpStatusCode.Created - response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) + this shouldHaveStatus HttpStatusCode.Created + this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) - val uri = getLocation(response.headers[HttpHeaders.Location].toString()) + val uri = getLocation(this.headers[HttpHeaders.Location].toString()) httpGet("$uri?download") { }.apply { - response shouldHaveStatus HttpStatusCode.OK - response.contentType() shouldBe ContentType.Application.OctetStream - response shouldHaveContent "foo" + this shouldHaveStatus HttpStatusCode.OK + this.contentType() shouldBe ContentType.Application.OctetStream + this.bodyAsText() shouldContain "foo" } } } } "get an artifact by id - URI" { - withTest{ + testApplication { httpPost(artifactsPath) { - addHeader("Content-Type", "text/turtle") + header("Content-Type", "text/turtle") setBody(" .") }.apply { - response shouldHaveStatus HttpStatusCode.Created - response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) + this shouldHaveStatus HttpStatusCode.Created + this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) - val uri = getLocation(response.headers[HttpHeaders.Location].toString()) + val uri = getLocation(this.headers[HttpHeaders.Location].toString()) httpGet("$uri?download") {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response.contentType().toString() shouldBeEqual "text/turtle" - response shouldHaveContent " ." + this shouldHaveStatus HttpStatusCode.OK + this.contentType().toString() shouldBeEqual "text/turtle" + this.bodyAsText() shouldBeEqual " ." } } } @@ -182,15 +187,15 @@ open class ArtifactAny : RefAny() { // Not used http methods that should fail "artifact/{id} rejects other methods" { - withTest { + testApplication { httpPost(artifactsPath) { - addHeader("Content-Type", "text/plain") + header("Content-Type", "text/plain") setBody("foo") }.apply { - response shouldHaveStatus HttpStatusCode.Created - response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) + this shouldHaveStatus HttpStatusCode.Created + this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath) - val uri = getLocation(response.headers[HttpHeaders.Location].toString()) + val uri = getLocation(this.headers[HttpHeaders.Location].toString()) onlyAllowsMethods( uri, setOf( HttpMethod.Head, diff --git a/src/test/kotlin/org/openmbee/flexo/mms/BranchCreate.kt b/src/test/kotlin/org/openmbee/flexo/mms/BranchCreate.kt index 54fddf5a..910e4f33 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/BranchCreate.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/BranchCreate.kt @@ -1,21 +1,26 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.shouldBe +import io.ktor.client.request.* +import io.ktor.client.statement.* import io.ktor.http.* +import io.ktor.server.testing.* import kotlinx.coroutines.delay import org.apache.jena.rdf.model.ResourceFactory +import org.apache.jena.vocabulary.SchemaDO.application import org.openmbee.flexo.mms.util.* import java.util.* class BranchCreate : RefAny() { init { - "reject invalid branch id".config(tags=setOf(NoAuth)) { - withTest { - httpPut("/orgs/$demoOrgId/repos/$demoRepoId/branches/bad branch id") { + "reject invalid branch id" { + testApplication { + httpPut("/orgs/$demoOrgId/repos/$demoRepoId/branches/bad branch id", true) { setTurtleBody(withAllTestPrefixes(validBranchBodyFromMaster)) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } @@ -26,9 +31,9 @@ class BranchCreate : RefAny() { "mms:etag" to "\"${UUID.randomUUID()}\"", "mms:ref" to "<./nosuchbranch>" ).forEach { (pred, obj) -> - "reject wrong $pred".config(tags=setOf(NoAuth)) { - withTest { - httpPut(demoBranchPath) { + "reject wrong $pred" { + testApplication { + httpPut(demoBranchPath, true) { var ref = "<> mms:ref <./master> ." if (pred == "mms:ref") ref = "" @@ -38,22 +43,21 @@ class BranchCreate : RefAny() { $ref """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } } "create branch from master after a commit to master" { - val update = commitModel(masterBranchPath, """ - insert data { - 5 . - } - """.trimIndent()) - - val commit = update.response.headers[HttpHeaders.ETag] + testApplication { + val update = commitModel(masterBranchPath, """ + insert data { + 5 . + } + """.trimIndent()) - withTest { + val commit = update.headers[HttpHeaders.ETag] httpPut(demoBranchPath) { setTurtleBody(withAllTestPrefixes(validBranchBodyFromMaster)) }.apply { @@ -63,7 +67,7 @@ class BranchCreate : RefAny() { } "create branch from empty master" { - withTest { + testApplication { httpPut(demoBranchPath) { setTurtleBody(withAllTestPrefixes(validBranchBodyFromMaster)) }.apply { @@ -73,45 +77,36 @@ class BranchCreate : RefAny() { } "insert, replace x 4, branch on 2nd" { - val init = commitModel(masterBranchPath, """ - insert data { - 1 . - } - """.trimIndent()) - - val initCommitId = init.response.headers[HttpHeaders.ETag] - - val commitIds = mutableListOf(); - - suspend fun replaceCounterValue(value: Int): String { - val update = commitModel(masterBranchPath, """ - delete where { - ?previous . - } ; + testApplication { + commitModel(masterBranchPath, """ insert data { - $value . + 1 . } - """.trimIndent() - ) - - val commitId = update.response.headers[HttpHeaders.ETag]!! - - commitIds.add(commitId) - - // wait for interim lock to be deleted - delay(2_000L) - - return commitId; - } - - val restoredValue = 2 - val restoreCommitId = replaceCounterValue(restoredValue) + """.trimIndent()) + val commitIds = mutableListOf(); + suspend fun replaceCounterValue(value: Int): String { + val update = commitModel(masterBranchPath, """ + delete where { + ?previous . + } ; + insert data { + $value . + } + """.trimIndent() + ) + val commitId = update.headers[HttpHeaders.ETag]!! + commitIds.add(commitId) + // wait for interim lock to be deleted + delay(2_000L) + return commitId; + } - for(index in 3..5) { - replaceCounterValue(index) - } + val restoredValue = 2 + val restoreCommitId = replaceCounterValue(restoredValue) - withTest { + for(index in 3..5) { + replaceCounterValue(index) + } // create branch and validate httpPut(demoBranchPath) { setTurtleBody(withAllTestPrefixes(""" @@ -125,11 +120,11 @@ class BranchCreate : RefAny() { // assert the resultant model is in the correct state val refPath = "$demoBranchPath/graph" httpGet(refPath) { - addHeader(HttpHeaders.Accept, RdfContentTypes.Turtle.toString()) + header(HttpHeaders.Accept, RdfContentTypes.Turtle.toString()) }.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK val model = KModel() - parseTurtle(response.content!!, model, demoBranchPath) + parseTurtle(this.bodyAsText(), model, demoBranchPath) val s = ResourceFactory.createResource("urn:mms:s") val p = ResourceFactory.createProperty("urn:mms:p") @@ -142,27 +137,26 @@ class BranchCreate : RefAny() { } "model load x 3, branch on 2" { - val load1 = loadModel(masterBranchPath, """ - 1 . - """.trimIndent()) - - delay(500L) + testApplication { + val load1 = loadModel(masterBranchPath, """ + 1 . + """.trimIndent()) - val load2 = loadModel(masterBranchPath, """ - 2 . - """.trimIndent()) + delay(500L) - val commitId2 = load2.response.headers[HttpHeaders.ETag]!! + val load2 = loadModel(masterBranchPath, """ + 2 . + """.trimIndent()) - delay(500L) + val commitId2 = load2.headers[HttpHeaders.ETag]!! - val load3 = loadModel(masterBranchPath, """ - 3 . - """.trimIndent()) + delay(500L) - delay(500L) + val load3 = loadModel(masterBranchPath, """ + 3 . + """.trimIndent()) - withTest { + delay(500L) httpPut(demoBranchPath) { setTurtleBody(withAllTestPrefixes(""" ${title(demoBranchName)} @@ -175,11 +169,11 @@ class BranchCreate : RefAny() { val refPath = "$demoBranchPath/graph" httpGet(refPath) { - addHeader(HttpHeaders.Accept, RdfContentTypes.Turtle.toString()) + header(HttpHeaders.Accept, RdfContentTypes.Turtle.toString()) }.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK val model = KModel() - parseTurtle(response.content!!, model, demoBranchPath) + parseTurtle(this.bodyAsText(), model, demoBranchPath) val s = ResourceFactory.createResource("urn:mms:s") val p = ResourceFactory.createProperty("urn:mms:p") diff --git a/src/test/kotlin/org/openmbee/flexo/mms/BranchDelete.kt b/src/test/kotlin/org/openmbee/flexo/mms/BranchDelete.kt index 7f085036..3a683529 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/BranchDelete.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/BranchDelete.kt @@ -1,25 +1,25 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.ktor.http.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.httpDelete import org.openmbee.flexo.mms.util.httpGet -import org.openmbee.flexo.mms.util.withTest import org.openmbee.flexo.mms.util.* class BranchDelete : RefAny() { init { "delete branch".config(enabled=false) { - createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) - - withTest { + testApplication { + createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) // delete branch should work httpDelete(demoBranchPath) {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK } // get deleted branch should 404 httpGet(demoBranchPath) {}.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/BranchRead.kt b/src/test/kotlin/org/openmbee/flexo/mms/BranchRead.kt index 4a798271..f1dfe20e 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/BranchRead.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/BranchRead.kt @@ -2,7 +2,10 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveHeader +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.ktor.http.* +import io.ktor.server.testing.* import org.apache.jena.vocabulary.DCTerms import org.apache.jena.vocabulary.RDF import org.openmbee.flexo.mms.util.* @@ -10,37 +13,35 @@ import org.openmbee.flexo.mms.util.* class BranchRead : RefAny() { init { "head non-existent branch" { - withTest { + testApplication { httpHead(demoBranchPath) {}.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } "get non-existent branch" { - withTest { + testApplication { httpGet(demoBranchPath) {}.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } "create and head new branch" { - val create = createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) - - withTest { + testApplication { + val create = createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) httpHead(demoBranchPath) {}.apply { - response shouldHaveStatus HttpStatusCode.NoContent - - response.shouldHaveHeader(HttpHeaders.ETag, create.response.headers[HttpHeaders.ETag]!!) + this shouldHaveStatus HttpStatusCode.NoContent + this.shouldHaveHeader(HttpHeaders.ETag, create.headers[HttpHeaders.ETag]!!) } } } "get master branch" { - withTest { + testApplication { httpGet(masterBranchPath) {}.apply { - response includesTriples { + this includesTriples { val branchiri = localIri(masterBranchPath) subject(branchiri) { @@ -56,17 +57,15 @@ class BranchRead : RefAny() { } "create from committed master then get all branches" { - val update = commitModel(masterBranchPath, """ - insert data { - 5 . - } - """.trimIndent()) - - val create = createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) - - withTest { + testApplication { + val update = commitModel(masterBranchPath, """ + insert data { + 5 . + } + """.trimIndent()) + val create = createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) httpGet("$demoRepoPath/branches") {}.apply { - response includesTriples { + this includesTriples { subject(localIri(demoBranchPath)) { includes( RDF.type exactly MMS.Branch, diff --git a/src/test/kotlin/org/openmbee/flexo/mms/BranchUpdate.kt b/src/test/kotlin/org/openmbee/flexo/mms/BranchUpdate.kt index ae85cccc..d2e190a3 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/BranchUpdate.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/BranchUpdate.kt @@ -2,6 +2,7 @@ package org.openmbee.flexo.mms import io.ktor.http.* +import io.ktor.server.testing.* import org.apache.jena.sparql.vocabulary.FOAF import org.apache.jena.vocabulary.DCTerms import org.apache.jena.vocabulary.RDF @@ -10,9 +11,8 @@ import org.openmbee.flexo.mms.util.* class BranchUpdate : RefAny() { init { "patch branch" { - createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) - - withTest { + testApplication { + createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) httpPatch(demoBranchPath) { setSparqlUpdateBody( withAllTestPrefixes( @@ -27,7 +27,7 @@ class BranchUpdate : RefAny() { ) ) }.apply { - response includesTriples { + this includesTriples { subject(localIri(demoBranchPath)) { includes( RDF.type exactly MMS.Branch, @@ -42,9 +42,8 @@ class BranchUpdate : RefAny() { } "all branches rejects other methods" { - createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) - - withTest { + testApplication { + createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) onlyAllowsMethods("$demoRepoPath/branches", setOf( HttpMethod.Head, HttpMethod.Get, @@ -54,9 +53,8 @@ class BranchUpdate : RefAny() { } "branch rejects other methods" { - createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) - - withTest { + testApplication { + createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) onlyAllowsMethods(demoBranchPath, setOf( HttpMethod.Head, HttpMethod.Get, diff --git a/src/test/kotlin/org/openmbee/flexo/mms/CommitLdpDc.kt b/src/test/kotlin/org/openmbee/flexo/mms/CommitLdpDc.kt index 5c4f9a65..aff38184 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/CommitLdpDc.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/CommitLdpDc.kt @@ -1,6 +1,7 @@ package org.openmbee.flexo.mms import io.ktor.http.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.* @@ -21,7 +22,7 @@ class CommitLdpDc : CommitAny() { insert data { . } """.trimIndent())} ) { bundle -> - if(bundle.createdOthers.isEmpty()) { + if (bundle.createdOthers.isEmpty()) { bundle.response includesTriples { validateCommitTriples(basePathCommits, bundle.createdBase.headers[HttpHeaders.Location]!!) } @@ -39,11 +40,11 @@ class CommitLdpDc : CommitAny() { } "commit path only allow head get and patch" { - val call = commitModel("$demoRepoPath/branches/master", """ + testApplication { + val call = commitModel("$demoRepoPath/branches/master", """ insert data { . } """.trimIndent()) - val path = call.response.headers[HttpHeaders.Location]!!.removePrefix(ROOT_CONTEXT) - withTest { + val path = call.headers[HttpHeaders.Location]!!.removePrefix(ROOT_CONTEXT) onlyAllowsMethods(path, setOf( HttpMethod.Head, HttpMethod.Get, @@ -53,7 +54,7 @@ class CommitLdpDc : CommitAny() { } "base path only allow head get" { - withTest { + testApplication { onlyAllowsMethods(basePathCommits, setOf( HttpMethod.Head, HttpMethod.Get, diff --git a/src/test/kotlin/org/openmbee/flexo/mms/GroupAny.kt b/src/test/kotlin/org/openmbee/flexo/mms/GroupAny.kt index 02770b1f..fb19533a 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/GroupAny.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/GroupAny.kt @@ -1,5 +1,6 @@ package org.openmbee.flexo.mms +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.apache.jena.vocabulary.DCTerms @@ -9,7 +10,7 @@ import org.slf4j.LoggerFactory import java.net.URLEncoder fun TriplesAsserter.validateGroupTriples( - createResponse: TestApplicationResponse, + createResponse: HttpResponse, groupId: String, groupName: String, extraPatterns: List = listOf() @@ -29,7 +30,7 @@ fun TriplesAsserter.validateGroupTriples( } fun TriplesAsserter.validateCreatedGroupTriples( - createResponse: TestApplicationResponse, + createResponse: HttpResponse, groupId: String, groupName: String, extraPatterns: List = listOf() diff --git a/src/test/kotlin/org/openmbee/flexo/mms/GroupCreate.kt b/src/test/kotlin/org/openmbee/flexo/mms/GroupCreate.kt deleted file mode 100644 index d6e840aa..00000000 --- a/src/test/kotlin/org/openmbee/flexo/mms/GroupCreate.kt +++ /dev/null @@ -1,118 +0,0 @@ -//package org.openmbee.flexo.mms -// -//import io.kotest.assertions.withClue -//import io.kotest.matchers.string.shouldNotBeBlank -//import io.ktor.http.* -//import io.ktor.server.testing.* -//import org.apache.jena.vocabulary.DCTerms -//import org.apache.jena.vocabulary.RDF -//import org.openmbee.flexo.mms.util.* -//import org.slf4j.LoggerFactory -//import java.net.URLEncoder -// -//fun TriplesAsserter.validateGroupTriples( -// createResponse: TestApplicationResponse, -// groupId: String, -// extraPatterns: List = listOf() -//) { -// val groupIri = localIri("/groups/$groupId") -// -// // org triples -// subject(groupIri) { -// exclusivelyHas( -// RDF.type exactly MMS.Group, -// MMS.id exactly groupId, -// MMS.etag startsWith "", -// *extraPatterns.toTypedArray() -// ) -// } -//} -// -//fun TriplesAsserter.validateCreatedGroupTriples( -// createResponse: TestApplicationResponse, -// groupId: String, -// extraPatterns: List = listOf() -//) { -// validateGroupTriples(createResponse, groupId, extraPatterns) -// -// // transaction -// validateTransaction() -// -// // inspect -// subject(MMS_URNS.SUBJECT.inspect) { ignoreAll() } -//} -// -// -//class GroupCreate : CommonSpec() { -// open val logger = LoggerFactory.getLogger(GroupCreate::class.java) -// -// val groupId = "ldap/cn=all.personnel,ou=personnel" -// val groupPath = "/groups/${URLEncoder.encode(groupId, "UTF-8")}" -// -// val groupTitle = "Test Group" -// val validGroupBody = withAllTestPrefixes(""" -// <> -// dct:title "${groupTitle}"@en ; -// . -// """.trimIndent()) -// -// init { -// "group id with slash".config(tags=setOf(NoAuth)) { -// withTest { -// httpPut("$groupPath/non-existant-path/foobar") { -// setTurtleBody(validGroupBody) -// }.apply { -// response shouldHaveStatus HttpStatusCode.NotFound -// } -// } -// } -// -// "reject invalid group id".config(tags=setOf(NoAuth)) { -// withTest { -// httpPut("$groupPath with invalid id") { -// setTurtleBody(validGroupBody) -// }.apply { -// response shouldHaveStatus HttpStatusCode.BadRequest -// } -// } -// } -// -// mapOf( -// "rdf:type" to "mms:NotGroup", -// "mms:id" to "\"not-$groupId\"", -// ).forEach { (pred, obj) -> -// "reject wrong $pred".config(tags=setOf(NoAuth)) { -// withTest { -// httpPut(groupPath) { -// setTurtleBody(""" -// $validGroupBody -// <> $pred $obj . -// """.trimIndent()) -// }.apply { -// response shouldHaveStatus HttpStatusCode.BadRequest -// } -// } -// } -// } -// -// "create valid group".config(tags=setOf(NoAuth)) { -// withTest { -// httpPut(groupPath) { -// setTurtleBody(validGroupBody) -// }.apply { -// withClue("Checking that ETag is present in response") { -// response.headers[HttpHeaders.ETag].shouldNotBeBlank() -// } -// -// response includesTriples { -// modelName = it -// -// validateCreatedGroupTriples(response, groupId, listOf( -// DCTerms.title exactly groupTitle.en -// )) -// } -// } -// } -// } -// } -//} \ No newline at end of file diff --git a/src/test/kotlin/org/openmbee/flexo/mms/GroupLdpDc.kt b/src/test/kotlin/org/openmbee/flexo/mms/GroupLdpDc.kt index c0efeb75..a8544e22 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/GroupLdpDc.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/GroupLdpDc.kt @@ -1,5 +1,6 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.ktor.http.* import org.openmbee.flexo.mms.util.* @@ -16,7 +17,7 @@ class GroupLdpDc : GroupAny() { } postWithPrecondition { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } read { diff --git a/src/test/kotlin/org/openmbee/flexo/mms/LockCreate.kt b/src/test/kotlin/org/openmbee/flexo/mms/LockCreate.kt index 0de7aebf..86ae5134 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/LockCreate.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/LockCreate.kt @@ -1,21 +1,23 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.string.shouldNotBeBlank import io.ktor.http.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.* class LockCreate : LockAny() { fun createAndValidateLock(_lockId: String=demoLockId, lockBody: String=validLockBodyfromMaster) { - withTest { + testApplication { httpPut("$demoRepoPath/locks/$_lockId") { setTurtleBody(withAllTestPrefixes(lockBody)) }.apply { - val etag = response.headers[HttpHeaders.ETag] + val etag = this.headers[HttpHeaders.ETag] etag.shouldNotBeBlank() - response shouldHaveStatus HttpStatusCode.Created - response.exclusivelyHasTriples { + this shouldHaveStatus HttpStatusCode.Created + this.exclusivelyHasTriples { modelName = "ValidateLock" validateCreatedLockTriples(_lockId, etag!!, demoOrgPath) } @@ -24,12 +26,12 @@ class LockCreate : LockAny() { } init { - "reject invalid lock id".config(tags=setOf(NoAuth)) { - withTest { - httpPut("$demoLockPath with invalid id") { + "reject invalid lock id" { + testApplication { + httpPut("$demoLockPath with invalid id", true) { setTurtleBody(withAllTestPrefixes(validLockBodyfromMaster)) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } @@ -39,21 +41,25 @@ class LockCreate : LockAny() { } "create lock on committed master" { - commitModel(masterBranchPath, """ - insert data { - . - } - """.trimIndent()) + testApplication { + commitModel(masterBranchPath, """ + insert data { + . + } + """.trimIndent()) + } createAndValidateLock() } "create lock on existing lock" { - commitModel(masterBranchPath, """ - insert data { - . - } - """.trimIndent()) + testApplication { + commitModel(masterBranchPath, """ + insert data { + . + } + """.trimIndent()) + } createAndValidateLock() diff --git a/src/test/kotlin/org/openmbee/flexo/mms/LockLdpDc.kt b/src/test/kotlin/org/openmbee/flexo/mms/LockLdpDc.kt index 2917c547..2e9b05a9 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/LockLdpDc.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/LockLdpDc.kt @@ -13,15 +13,6 @@ class LockLdpDc : LockAny() { validBodyForCreate = validLockBodyfromMaster, resourceCreator = { createLock(demoRepoPath, masterBranchPath, demoLockId) } ) { - -// create { -// // extract etag -// val etag = it.headers[HttpHeaders.ETag]!! -// -// // validate -// validateCreatedLockTriples(demoLockId, etag, demoOrgPath) -// } - patch() } } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/LockQuery.kt b/src/test/kotlin/org/openmbee/flexo/mms/LockQuery.kt index 3cbaf57a..e72bc50e 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/LockQuery.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/LockQuery.kt @@ -1,7 +1,10 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.string.shouldContain +import io.ktor.client.statement.* import io.ktor.http.* +import io.ktor.server.testing.* import kotlinx.serialization.json.Json import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject @@ -11,10 +14,9 @@ import org.openmbee.flexo.mms.util.* class LockQuery : LockAny() { init { "query lock" { - commitModel(masterBranchPath, insertLock) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertLock) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPost("$demoLockPath/query") { setSparqlQueryBody(""" select ?o { @@ -22,8 +24,8 @@ class LockQuery : LockAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { binding( "o" to "urn:mms:o".bindingUri ) @@ -33,10 +35,9 @@ class LockQuery : LockAny() { } "query lock with graph var" { - commitModel(masterBranchPath, insertLock) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertLock) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPost("$demoLockPath/query") { setSparqlQueryBody(""" select ?g ?o { @@ -46,14 +47,14 @@ class LockQuery : LockAny() { } """.trimIndent()) }.apply { - val graphVal = Json.parseToJsonElement(response.content!!).jsonObject["results"]!! + val graphVal = Json.parseToJsonElement(this.bodyAsText()).jsonObject["results"]!! .jsonObject["bindings"]!!.jsonArray[0].jsonObject["g"]!!.jsonObject["value"]!! .jsonPrimitive.content; graphVal shouldContain "/graphs/Model." - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { binding( "g" to graphVal.bindingUri, "o" to "urn:mms:o".bindingUri @@ -64,10 +65,9 @@ class LockQuery : LockAny() { } "ask lock: true" { - commitModel(masterBranchPath, insertLock) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertLock) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPost("$demoLockPath/query") { setSparqlQueryBody(""" ask { @@ -75,8 +75,8 @@ class LockQuery : LockAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson """ + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson """ { "head": {}, "boolean": true @@ -87,10 +87,9 @@ class LockQuery : LockAny() { } "ask lock: false" { - commitModel(masterBranchPath, insertLock) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertLock) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPost("$demoLockPath/query") { setSparqlQueryBody(""" ask { @@ -98,8 +97,8 @@ class LockQuery : LockAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson """ + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson """ { "head": {}, "boolean": false @@ -110,17 +109,16 @@ class LockQuery : LockAny() { } "describe lock explicit" { - commitModel(masterBranchPath, insertLock) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertLock) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPost("$demoLockPath/query") { setSparqlQueryBody(""" describe """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { subject("urn:mms:s") { ignoreAll() } @@ -130,10 +128,9 @@ class LockQuery : LockAny() { } "describe lock where" { - commitModel(masterBranchPath, insertLock) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertLock) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPost("$demoLockPath/query") { setSparqlQueryBody(""" describe ?s { @@ -141,8 +138,8 @@ class LockQuery : LockAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { subject("urn:mms:s") { ignoreAll() } @@ -152,10 +149,11 @@ class LockQuery : LockAny() { } "construct lock" { - commitModel(masterBranchPath, insertLock) - createLock(demoRepoPath, masterBranchPath, demoLockId) - withTest { + + testApplication { + commitModel(masterBranchPath, insertLock) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPost("$demoLockPath/query") { setSparqlQueryBody(""" construct { @@ -165,8 +163,8 @@ class LockQuery : LockAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response exclusivelyHasTriples { + this shouldHaveStatus HttpStatusCode.OK + this exclusivelyHasTriples { subject("urn:mms:o") { exclusivelyHas( "urn:mms:p".toPredicate exactly "urn:mms:s".iri @@ -178,7 +176,7 @@ class LockQuery : LockAny() { } "nothing exists" { - withTest { + testApplication { httpPost("/orgs/not-exists/repos/not-exists/locks/not-exists/query") { setSparqlQueryBody(""" select ?o { @@ -186,7 +184,7 @@ class LockQuery : LockAny() { } """) }.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/LockRead.kt b/src/test/kotlin/org/openmbee/flexo/mms/LockRead.kt index abb718f9..6daedf59 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/LockRead.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/LockRead.kt @@ -1,9 +1,13 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.shouldBe +import io.ktor.client.request.* +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.request.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.* class LockRead : LockAny() { @@ -15,37 +19,35 @@ class LockRead : LockAny() { // "delete", ).forEach { method -> "$method non-existent lock" { - withTest { + testApplication { httpRequest(HttpMethod(method.uppercase()), demoLockPath) { // PATCH request - if(method == "patch") { - addHeader("Content-Type", RdfContentTypes.Turtle.toString()) + if (method == "patch") { + header("Content-Type", RdfContentTypes.Turtle.toString()) } }.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } } "head valid lock" { - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + createLock(demoRepoPath, masterBranchPath, demoLockId) httpHead(demoLockPath) {}.apply { - response shouldHaveStatus HttpStatusCode.NoContent - response.content.shouldBe(null) + this shouldHaveStatus HttpStatusCode.NoContent + this.bodyAsText().shouldBe("") } } } "get valid lock" { - val etag = createLock(demoRepoPath, masterBranchPath, demoLockId).response.headers[HttpHeaders.ETag] - - withTest { + testApplication { + val etag = createLock(demoRepoPath, masterBranchPath, demoLockId).headers[HttpHeaders.ETag] httpGet(demoLockPath) {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { validateLockTriples(demoLockId, etag!!) } } @@ -53,7 +55,7 @@ class LockRead : LockAny() { } "lock other methods not allowed" { - withTest { + testApplication { onlyAllowsMethods(demoLockPath, setOf( HttpMethod.Head, HttpMethod.Get, @@ -65,23 +67,21 @@ class LockRead : LockAny() { } "head all locks" { - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + createLock(demoRepoPath, masterBranchPath, demoLockId) httpHead("$demoRepoPath/locks") {}.apply { - response shouldHaveStatus HttpStatusCode.NoContent - response.content.shouldBe(null) + this shouldHaveStatus HttpStatusCode.NoContent + this.bodyAsText().shouldBe("") } } } "get all locks" { - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + createLock(demoRepoPath, masterBranchPath, demoLockId) httpGet("$demoRepoPath/locks") {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { validateLockTriples(demoLockId) } } @@ -89,7 +89,7 @@ class LockRead : LockAny() { } "all locks other methods not allowed" { - withTest { + testApplication { onlyAllowsMethods("$demoRepoPath/locks", setOf( HttpMethod.Head, HttpMethod.Get, diff --git a/src/test/kotlin/org/openmbee/flexo/mms/LockWrite.kt b/src/test/kotlin/org/openmbee/flexo/mms/LockWrite.kt index b9e0878a..9e3b7928 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/LockWrite.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/LockWrite.kt @@ -1,6 +1,8 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.ktor.http.* +import io.ktor.server.testing.* import org.apache.jena.vocabulary.DCTerms import org.openmbee.flexo.mms.util.* @@ -8,17 +10,15 @@ import org.openmbee.flexo.mms.util.* class LockWrite : LockAny() { init { "patch lock with TTL" { - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPatch(demoLockPath) { setTurtleBody(withAllTestPrefixes(""" <> dct:description "foo" . """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.OK - - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { validateLockTriples(demoLockId, null, listOf( DCTerms.description exactly "foo" )) @@ -28,9 +28,8 @@ class LockWrite : LockAny() { } "patch lock with SPARQL UPDATE" { - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + createLock(demoRepoPath, masterBranchPath, demoLockId) httpPatch(demoLockPath) { setSparqlUpdateBody(withAllTestPrefixes(""" insert data { @@ -38,9 +37,8 @@ class LockWrite : LockAny() { } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.OK - - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { validateLockTriples(demoLockId, null, listOf( DCTerms.description exactly "foo" )) diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ModelCommit.kt b/src/test/kotlin/org/openmbee/flexo/mms/ModelCommit.kt index 55fe513b..76cd1b6f 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ModelCommit.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ModelCommit.kt @@ -1,24 +1,26 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.string.shouldNotBeBlank +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.apache.jena.rdf.model.ResourceFactory import org.openmbee.flexo.mms.util.* class ModelCommit: ModelAny() { - fun TestApplicationCall.validateCommitResult(branchPath: String) { - response shouldHaveStatus HttpStatusCode.Created - val etag = response.headers[HttpHeaders.ETag] + suspend fun HttpResponse.validateCommitResult(branchPath: String) { + this shouldHaveStatus HttpStatusCode.Created + val etag = this.headers[HttpHeaders.ETag] etag.shouldNotBeBlank() - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { validateModelCommitResponse(branchPath, etag!!) } } init { "insert data on master" { val updateBody = mutableListOf(insertAliceRex, insertBobFluffy).joinToString(";\n") - withTest { + testApplication { httpPost("$masterBranchPath/update") { setSparqlUpdateBody(updateBody) }.apply { @@ -26,7 +28,7 @@ class ModelCommit: ModelAny() { } httpGet("$masterBranchPath/graph") {}.apply { - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { val people = demoPrefixes.get("") subject("${people}Alice") { ignoreAll() @@ -85,7 +87,7 @@ class ModelCommit: ModelAny() { } """.trimIndent() ).joinToString(";\n") - withTest { + testApplication { httpPost("$masterBranchPath/update") { setSparqlUpdateBody(updateBody) }.apply { @@ -93,7 +95,7 @@ class ModelCommit: ModelAny() { } httpGet("$masterBranchPath/graph") {}.apply { - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { subject("urn:these") { exclusivelyHas(ResourceFactory.createProperty("urn:more") exactly ResourceFactory.createResource("urn:inserts")) } @@ -106,14 +108,14 @@ class ModelCommit: ModelAny() { } "commit model on non-empty branch" { - commitModel(masterBranchPath, insertAliceRex) - createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) val updateBody = """ insert data { . } """.trimIndent() - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) + createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) httpPost("$demoBranchPath/update") { setSparqlUpdateBody(updateBody) }.apply { @@ -121,7 +123,7 @@ class ModelCommit: ModelAny() { } httpGet("$demoBranchPath/graph") {}.apply { - response.includesTriples { + this.includesTriples { subject("urn:this") { exclusivelyHas(ResourceFactory.createProperty("urn:is") exactly ResourceFactory.createResource("urn:inserted")) } @@ -134,11 +136,11 @@ class ModelCommit: ModelAny() { //manually add a transaction into backend val updateUrl = backend.getUpdateUrl() addDummyTransaction(updateUrl, masterBranchPath) - withTest { + testApplication { httpPost("$masterBranchPath/update") { setSparqlUpdateBody("""insert data { .}""") }.apply { - response shouldHaveStatus HttpStatusCode.Conflict + this shouldHaveStatus HttpStatusCode.Conflict } } } @@ -157,7 +159,7 @@ class ModelCommit: ModelAny() { . } """.trimIndent() - withTest { + testApplication { httpPost("$masterBranchPath/update") { setSparqlUpdateBody(updateBody) }.apply { @@ -165,7 +167,7 @@ class ModelCommit: ModelAny() { } httpGet("$masterBranchPath/graph") {}.apply { - response.includesTriples { + this.includesTriples { subject("urn:this") { exclusivelyHas(ResourceFactory.createProperty("urn:is") exactly ResourceFactory.createResource("urn:inserted")) } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ModelLoad.kt b/src/test/kotlin/org/openmbee/flexo/mms/ModelLoad.kt index e3a19f18..ee810460 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ModelLoad.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ModelLoad.kt @@ -1,8 +1,10 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldNotBeBlank import io.kotest.matchers.string.shouldStartWith +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.apache.jena.vocabulary.DCTerms @@ -11,13 +13,13 @@ import org.apache.jena.vocabulary.XSD import org.openmbee.flexo.mms.util.* class ModelLoad : ModelAny() { - fun TestApplicationCall.validateModelLoadResponse() { - response shouldHaveStatus HttpStatusCode.OK - val commit = response.headers[HttpHeaders.Location] + suspend fun HttpResponse.validateModelLoadResponse() { + this shouldHaveStatus HttpStatusCode.OK + val commit = this.headers[HttpHeaders.Location] commit.shouldNotBeBlank() - val etag = response.headers[HttpHeaders.ETag] + val etag = this.headers[HttpHeaders.ETag] etag.shouldNotBeBlank() - response includesTriples { + this includesTriples { subject(commit!!) { includes( RDF.type exactly MMS.Commit, @@ -30,15 +32,15 @@ class ModelLoad : ModelAny() { } } - fun TestApplicationCall.validateModelLoadNoChangeResponse() { - response shouldHaveStatus HttpStatusCode.OK - val etag = response.headers[HttpHeaders.ETag] + fun HttpResponse.validateModelLoadNoChangeResponse() { + this shouldHaveStatus HttpStatusCode.OK + val etag = this.headers[HttpHeaders.ETag] etag.shouldNotBeBlank() } init { "load all inserts on empty model" { - withTest { + testApplication { httpPut("$masterBranchPath/graph") { setTurtleBody(loadAliceRex) }.apply { @@ -48,7 +50,7 @@ class ModelLoad : ModelAny() { } "load no change on empty model" { - withTest { + testApplication { httpPut("$masterBranchPath/graph") { setTurtleBody("") }.apply { @@ -58,9 +60,8 @@ class ModelLoad : ModelAny() { } "load all inserts on non-empty model" { - loadModel(masterBranchPath, loadAliceRex) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) httpPut("$masterBranchPath/graph") { setTurtleBody(""" $loadAliceRex @@ -75,9 +76,8 @@ class ModelLoad : ModelAny() { } "load all deletes on non-empty model" { - loadModel(masterBranchPath, loadAliceRex) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) httpPut("$masterBranchPath/graph") { setTurtleBody("") }.apply { @@ -87,9 +87,8 @@ class ModelLoad : ModelAny() { } "load no change on non-empty model" { - loadModel(masterBranchPath, loadAliceRex) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) httpPut("$masterBranchPath/graph") { setTurtleBody(loadAliceRex) }.apply { @@ -99,9 +98,8 @@ class ModelLoad : ModelAny() { } "load both inserts and deletes on non-empty model" { - loadModel(masterBranchPath, loadAliceRex) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) httpPut("$masterBranchPath/graph") { setTurtleBody(""" @prefix : @@ -120,20 +118,19 @@ class ModelLoad : ModelAny() { //manually add a transaction into backend val updateUrl = backend.getUpdateUrl() addDummyTransaction(updateUrl, masterBranchPath) - withTest { + testApplication { httpPut("$masterBranchPath/graph") { setTurtleBody(loadAliceRex) }.apply { - response shouldHaveStatus HttpStatusCode.Conflict + this shouldHaveStatus HttpStatusCode.Conflict } } } "lock graph rejects other methods" { - commitModel(masterBranchPath, insertAliceRex) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) + createLock(demoRepoPath, masterBranchPath, demoLockId) onlyAllowsMethods("$demoLockPath/graph", setOf( HttpMethod.Head, HttpMethod.Get, @@ -142,24 +139,21 @@ class ModelLoad : ModelAny() { } "head branch graph" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) httpHead("$masterBranchPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK -// response.content shouldBe null + this shouldHaveStatus HttpStatusCode.OK } } } "get branch graph" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) httpGet("$masterBranchPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { subjectTerse(":Alice") { ignoreAll() } @@ -173,26 +167,24 @@ class ModelLoad : ModelAny() { } "head lock graph" { - commitModel(masterBranchPath, insertAliceRex) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpHead("$demoLockPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response.content shouldBe null + this shouldHaveStatus HttpStatusCode.OK + this.bodyAsText() shouldBe "" } } } "get lock graph" { - commitModel(masterBranchPath, insertAliceRex) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpGet("$demoLockPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { subjectTerse(":Alice") { ignoreAll() } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ModelQuery.kt b/src/test/kotlin/org/openmbee/flexo/mms/ModelQuery.kt index 9ced2a48..3800cb7f 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ModelQuery.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ModelQuery.kt @@ -1,7 +1,10 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.string.shouldContain +import io.ktor.client.statement.* import io.ktor.http.* +import io.ktor.server.testing.* import kotlinx.serialization.json.Json import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject @@ -11,21 +14,20 @@ import org.openmbee.flexo.mms.util.* class ModelQuery : ModelAny() { init { "query data from model" { - val update = commitModel(masterBranchPath, insertAliceRex) - withTest { + testApplication { + val update = commitModel(masterBranchPath, insertAliceRex) httpPost("$masterBranchPath/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson queryNamesAliceResult + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson queryNamesAliceResult } } } "query model with graph var" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) // master model is updated httpPost("$masterBranchPath/query") { setSparqlQueryBody(""" @@ -36,14 +38,12 @@ class ModelQuery : ModelAny() { } """.trimIndent()) }.apply { - val graphVal = Json.parseToJsonElement(response.content!!).jsonObject["results"]!! + val graphVal = Json.parseToJsonElement(this.bodyAsText()).jsonObject["results"]!! .jsonObject["bindings"]!!.jsonArray[0].jsonObject["g"]!!.jsonObject["value"]!! .jsonPrimitive.content - graphVal shouldContain "/graphs/Model." - - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { binding( "g" to graphVal.bindingUri ) @@ -53,9 +53,8 @@ class ModelQuery : ModelAny() { } "query model with from default not authorized" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) // master model is updated httpPost("$masterBranchPath/query") { setSparqlQueryBody(withAllTestPrefixes(""" @@ -66,15 +65,14 @@ class ModelQuery : ModelAny() { } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.Forbidden + this shouldHaveStatus HttpStatusCode.Forbidden } } } "query model with from named not authorized" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) // master model is updated httpPost("$masterBranchPath/query") { setSparqlQueryBody(withAllTestPrefixes(""" @@ -87,15 +85,14 @@ class ModelQuery : ModelAny() { } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.Forbidden + this shouldHaveStatus HttpStatusCode.Forbidden } } } "query model graph not there" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) // master model is updated httpPost("$masterBranchPath/query") { setSparqlQueryBody(withAllTestPrefixes(""" @@ -106,8 +103,8 @@ class ModelQuery : ModelAny() { } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { varsExpect.addAll(listOf( "s", "p", "o" )) @@ -117,9 +114,8 @@ class ModelQuery : ModelAny() { } "ask model: true" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) httpPost("$masterBranchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -129,8 +125,8 @@ class ModelQuery : ModelAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson """ + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson """ { "head": {}, "boolean": true @@ -141,9 +137,8 @@ class ModelQuery : ModelAny() { } "ask model: false" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) httpPost("$masterBranchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -153,8 +148,8 @@ class ModelQuery : ModelAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson """ + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson """ { "head": {}, "boolean": false @@ -165,9 +160,8 @@ class ModelQuery : ModelAny() { } "describe model explicit" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) httpPost("$masterBranchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -175,8 +169,8 @@ class ModelQuery : ModelAny() { describe :Alice """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { subjectTerse(":Alice") { ignoreAll() } @@ -186,9 +180,8 @@ class ModelQuery : ModelAny() { } "describe model where" { - commitModel(masterBranchPath, insertAliceRex) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) httpPost("$masterBranchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -198,8 +191,8 @@ class ModelQuery : ModelAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { subjectTerse(":Rex") { ignoreAll() } @@ -209,72 +202,69 @@ class ModelQuery : ModelAny() { } "query result is different between master and branch" { - commitModel(masterBranchPath, insertAliceRex) - createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) - commitModel(masterBranchPath, insertBobFluffy) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) + createBranch(demoRepoPath, "master", demoBranchId, demoBranchName) + commitModel(masterBranchPath, insertBobFluffy) // branch model does not have second updates httpPost("$demoBranchPath/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson queryNamesAliceResult + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson queryNamesAliceResult } // master model is updated httpPost("$masterBranchPath/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson queryNamesAliceBobResult + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson queryNamesAliceBobResult } } } "query result is different between master and lock" { - commitModel(masterBranchPath, insertAliceRex) - createLock(demoRepoPath, masterBranchPath, demoLockId) - commitModel(masterBranchPath, insertBobFluffy) - - withTest { + testApplication { + commitModel(masterBranchPath, insertAliceRex) + createLock(demoRepoPath, masterBranchPath, demoLockId) + commitModel(masterBranchPath, insertBobFluffy) // branch model does not have second updates httpPost("$demoLockPath/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson queryNamesAliceResult + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson queryNamesAliceResult } // master model is updated httpPost("$masterBranchPath/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson queryNamesAliceBobResult + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson queryNamesAliceBobResult } } } "query result is different between master and lock from model loads" { - loadModel(masterBranchPath, loadAliceRex) - createLock(demoRepoPath, masterBranchPath, demoLockId) - loadModel(masterBranchPath, loadBobFluffy) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) + createLock(demoRepoPath, masterBranchPath, demoLockId) + loadModel(masterBranchPath, loadBobFluffy) httpPost("$demoLockPath/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson queryNamesAliceResult + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson queryNamesAliceResult } httpPost("$masterBranchPath/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK // the load overwrites, so only bob exists - response equalsSparqlResults { + this equalsSparqlResults { binding( "name" to "Bob".bindingLit ) @@ -284,10 +274,9 @@ class ModelQuery : ModelAny() { } "subquery" { - loadModel(masterBranchPath, loadAliceRex) - loadModel(masterBranchPath, loadBobFluffy) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) + loadModel(masterBranchPath, loadBobFluffy) httpPost("$masterBranchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -304,8 +293,8 @@ class ModelQuery : ModelAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { binding( "personName" to "Bob".bindingLit ) @@ -315,19 +304,18 @@ class ModelQuery : ModelAny() { } "nothing exists" { - withTest { + testApplication { httpPost("/orgs/not-exists/repos/not-exists/branches/not-exists/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } "concat" { - loadModel(masterBranchPath, loadAliceRex) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) httpPost("$masterBranchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -339,8 +327,8 @@ class ModelQuery : ModelAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { binding( "concat" to "test:Alice".bindingLit ) diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ModelRead.kt b/src/test/kotlin/org/openmbee/flexo/mms/ModelRead.kt index 6df6cca3..ad4f6087 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ModelRead.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ModelRead.kt @@ -1,5 +1,8 @@ +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.shouldBe +import io.ktor.client.statement.* import io.ktor.http.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.ModelAny import org.openmbee.flexo.mms.util.* @@ -10,34 +13,32 @@ class ModelRead : ModelAny() { "get" ).forEach { method -> "$method non-existent model graph" { - withTest { + testApplication { httpRequest(HttpMethod(method.uppercase()), "$demoLockPath/graph") { }.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } } "head branch graph" { - loadModel(masterBranchPath, loadAliceRex) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) httpHead("$masterBranchPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK // response.content shouldBe null } } } "get branch graph" { - loadModel(masterBranchPath, loadAliceRex) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) httpGet("$masterBranchPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { subjectTerse(":Alice") { ignoreAll() } @@ -51,26 +52,24 @@ class ModelRead : ModelAny() { } "head lock graph" { - loadModel(masterBranchPath, loadAliceRex) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpHead("$demoLockPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response.content shouldBe null + this shouldHaveStatus HttpStatusCode.OK + this.bodyAsText() shouldBe "" } } } "get lock graph" { - loadModel(masterBranchPath, loadAliceRex) - createLock(demoRepoPath, masterBranchPath, demoLockId) - - withTest { + testApplication { + loadModel(masterBranchPath, loadAliceRex) + createLock(demoRepoPath, masterBranchPath, demoLockId) httpGet("$demoLockPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { subjectTerse(":Alice") { ignoreAll() } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/OrgAny.kt b/src/test/kotlin/org/openmbee/flexo/mms/OrgAny.kt index 74eee873..dcb7dc75 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/OrgAny.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/OrgAny.kt @@ -1,5 +1,6 @@ package org.openmbee.flexo.mms +import io.ktor.client.statement.* import io.ktor.server.testing.* import org.apache.jena.rdf.model.ResourceFactory import org.apache.jena.vocabulary.DCTerms @@ -8,7 +9,7 @@ import org.openmbee.flexo.mms.util.* import org.slf4j.LoggerFactory fun TriplesAsserter.validateOrgTriples( - createResponse: TestApplicationResponse, + createResponse: HttpResponse, orgId: String, orgName: String, extraPatterns: List = listOf() @@ -31,7 +32,7 @@ fun TriplesAsserter.validateOrgTriples( } fun TriplesAsserter.validateCreatedOrgTriples( - createResponse: TestApplicationResponse, + createResponse: HttpResponse, orgId: String, orgName: String, extraPatterns: List = listOf() diff --git a/src/test/kotlin/org/openmbee/flexo/mms/OrgLdpDc.kt b/src/test/kotlin/org/openmbee/flexo/mms/OrgLdpDc.kt index bb03fb0f..95b1055e 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/OrgLdpDc.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/OrgLdpDc.kt @@ -1,7 +1,9 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.ktor.http.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.* import java.util.* @@ -19,7 +21,7 @@ class OrgLdpDc : OrgAny() { } postWithPrecondition { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } replaceExisting { @@ -56,15 +58,15 @@ class OrgLdpDc : OrgAny() { "mms:id" to "\"not-$demoOrgId\"", "mms:etag" to "\"${UUID.randomUUID()}\"", ).forEach { (pred, obj) -> - "reject wrong $pred".config(tags=setOf(NoAuth)) { - withTest { - httpPut(demoOrgPath) { + "reject wrong $pred" { + testApplication { + httpPut(demoOrgPath, true) { setTurtleBody(withAllTestPrefixes(""" $validOrgBody <> $pred $obj . """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/PolicyCreate.kt b/src/test/kotlin/org/openmbee/flexo/mms/PolicyCreate.kt index c233d72e..a2c959fa 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/PolicyCreate.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/PolicyCreate.kt @@ -1,7 +1,9 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.string.shouldNotBeBlank +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.apache.jena.rdf.model.Resource @@ -12,7 +14,7 @@ import org.slf4j.LoggerFactory fun TriplesAsserter.validatePolicyTriples( - createResponse: TestApplicationResponse, + createResponse: HttpResponse, policyId: String, subjectPath: String, scopePath: String, @@ -36,7 +38,7 @@ fun TriplesAsserter.validatePolicyTriples( } fun TriplesAsserter.validateCreatedPolicyTriples( - createResponse: TestApplicationResponse, + createResponse: HttpResponse, policyId: String, subjectPath: String, scopePath: String, @@ -63,7 +65,7 @@ fun TriplesAsserter.validateCreatedPolicyTriples( } class PolicyCreate : CommonSpec() { - open val logger = LoggerFactory.getLogger(PolicyCreate::class.java) + val logger = LoggerFactory.getLogger(PolicyCreate::class.java) val policyId = "TestPolicy" val policyPath = "/policies/$policyId" @@ -83,12 +85,12 @@ class PolicyCreate : CommonSpec() { """.trimIndent() init { - "reject invalid policy id".config(tags=setOf(NoAuth)) { - withTest { - httpPut("$policyPath with invalid id") { + "reject invalid policy id" { + testApplication { + httpPut("$policyPath with invalid id", true) { setTurtleBody(withAllTestPrefixes(validPolicyBody)) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } @@ -97,32 +99,32 @@ class PolicyCreate : CommonSpec() { "rdf:type" to "mms:NotPolicy", "mms:id" to "\"not-$policyId\"", ).forEach { (pred, obj) -> - "reject wrong $pred".config(tags=setOf(NoAuth)) { - withTest { - httpPut(policyPath) { + "reject wrong $pred" { + testApplication { + httpPut(policyPath, true) { setTurtleBody(withAllTestPrefixes(""" $validPolicyBody <> $pred $obj . """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } } - "create valid policy".config(tags=setOf(NoAuth)) { - withTest { - httpPut(policyPath) { + "create valid policy" { + testApplication { + httpPut(policyPath, true) { setTurtleBody(withAllTestPrefixes(validPolicyBody)) }.apply { - response shouldHaveStatus HttpStatusCode.Created - response.headers[HttpHeaders.ETag].shouldNotBeBlank() + this shouldHaveStatus HttpStatusCode.Created + this.headers[HttpHeaders.ETag].shouldNotBeBlank() - response exclusivelyHasTriples { - modelName = it + this exclusivelyHasTriples { + modelName = "create valid policty" - validateCreatedPolicyTriples(response, policyId, testUserPath, clusterScopePath, testRoleNodes) + validateCreatedPolicyTriples(this@apply, policyId, testUserPath, clusterScopePath, testRoleNodes) } } } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/RefAny.kt b/src/test/kotlin/org/openmbee/flexo/mms/RefAny.kt index c89d1a8f..4cea51e9 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/RefAny.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/RefAny.kt @@ -2,6 +2,7 @@ package org.openmbee.flexo.mms import io.kotest.core.test.TestCase import io.kotest.matchers.string.shouldNotBeBlank +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.apache.jena.vocabulary.DCTerms @@ -34,12 +35,14 @@ open class RefAny : RepoAny() { // create a repo before each branch test override suspend fun beforeEach(testCase: TestCase) { super.beforeEach(testCase) - repoEtag = createRepo(demoOrgPath, demoRepoId, demoRepoName).response.headers[HttpHeaders.ETag]!! + testApplication { + repoEtag = createRepo(demoOrgPath, demoRepoId, demoRepoName).headers[HttpHeaders.ETag]!! + } } - fun TestApplicationCall.validateCreateBranchResponse(fromCommit: String) { + suspend fun HttpResponse.validateCreateBranchResponse(fromCommit: String) { // branch-specific validation - response exclusivelyHasTriples { + this exclusivelyHasTriples { modelName = "CreateBranch" subject(localIri(demoBranchPath)) { @@ -47,7 +50,7 @@ open class RefAny : RepoAny() { RDF.type exactly MMS.Branch, MMS.id exactly demoBranchId, DCTerms.title exactly demoBranchName.en, - MMS.etag exactly response.headers[HttpHeaders.ETag]!!, + MMS.etag exactly headers[HttpHeaders.ETag]!!, MMS.commit startsWith localIri("$demoCommitsPath/").iri, // TODO: incorporate fromCommit ? MMS.createdBy exactly userIri("root").iri, MMS.created startsWith "" diff --git a/src/test/kotlin/org/openmbee/flexo/mms/RepoAny.kt b/src/test/kotlin/org/openmbee/flexo/mms/RepoAny.kt index 6201a8ba..776b3ae3 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/RepoAny.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/RepoAny.kt @@ -1,6 +1,7 @@ package org.openmbee.flexo.mms import io.kotest.core.test.TestCase +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.apache.jena.rdf.model.ResourceFactory @@ -70,7 +71,7 @@ fun TriplesAsserter.validateRepoTriplesWithMasterBranch( // validates response triples for a newly created repo fun TriplesAsserter.validateCreatedRepoTriples( - createResponse: TestApplicationResponse, + createResponse: HttpResponse, repoId: String, repoName: String, orgPath: String, @@ -128,11 +129,12 @@ open class RepoAny : OrgAny() { // create an org before each repo test override suspend fun beforeEach(testCase: TestCase) { super.beforeEach(testCase) - - // create base orgs for repo test - createOrg(demoOrgId, demoOrgName) - createOrg(fooOrgId, fooOrgName) - createOrg(barOrgId, barOrgName) + testApplication { + // create base orgs for repo test + createOrg(demoOrgId, demoOrgName) + createOrg(fooOrgId, fooOrgName) + createOrg(barOrgId, barOrgName) + } } // diff --git a/src/test/kotlin/org/openmbee/flexo/mms/RepoLdpDc.kt b/src/test/kotlin/org/openmbee/flexo/mms/RepoLdpDc.kt index cb89f946..39e7fcdd 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/RepoLdpDc.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/RepoLdpDc.kt @@ -1,6 +1,7 @@ package org.openmbee.flexo.mms +import io.ktor.client.statement.* import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.* @@ -16,7 +17,7 @@ class RepoLdpDc : RepoAny() { """.trimIndent()), resourceCreator = { createRepo(demoOrgPath, demoRepoId, demoRepoName) } ) { - fun TriplesAsserter.validCreatedRepo(response: TestApplicationResponse, slug: String) { + fun TriplesAsserter.validCreatedRepo(response: HttpResponse, slug: String) { modelName = "CreateValidRepo" validateCreatedRepoTriples(response, slug, demoRepoName, demoOrgPath, listOf( diff --git a/src/test/kotlin/org/openmbee/flexo/mms/RepoQuery.kt b/src/test/kotlin/org/openmbee/flexo/mms/RepoQuery.kt index fcb5632a..b45c1894 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/RepoQuery.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/RepoQuery.kt @@ -3,8 +3,11 @@ package org.openmbee.flexo.mms import io.kotest.assertions.json.shouldBeJsonObject import io.kotest.assertions.json.shouldContainJsonKey import io.kotest.assertions.json.shouldContainJsonKeyValue +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.string.shouldStartWith +import io.ktor.client.statement.* import io.ktor.http.* +import io.ktor.server.testing.* import org.apache.jena.vocabulary.DCTerms import org.apache.jena.vocabulary.RDF import org.openmbee.flexo.mms.util.* @@ -23,25 +26,25 @@ class RepoQuery : ModelAny() { init { "query time of commit of lock" { - val update = commitModel(masterBranchPath, insertAliceRex) + testApplication { + val update = commitModel(masterBranchPath, insertAliceRex) // val etag = update.response.headers[HttpHeaders.ETag]!! - createLock(demoRepoPath, masterBranchPath, demoLockId) - // lock should be pointing to the commit from update - withTest { + createLock(demoRepoPath, masterBranchPath, demoLockId) + // lock should be pointing to the commit from update httpPost("$demoRepoPath/query") { setSparqlQueryBody(withAllTestPrefixes(lockCommitQuery)) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response.headers["Content-Type"] shouldStartWith "application/sparql-results+json" - response.content!!.shouldBeJsonObject() + this shouldHaveStatus HttpStatusCode.OK + this.headers["Content-Type"] shouldStartWith "application/sparql-results+json" + this.bodyAsText().shouldBeJsonObject() // response.content!!.shouldContainJsonKeyValue("$.results.bindings[0].etag.value", etag) - response.content!!.shouldContainJsonKey("$.results.bindings[0].time.value") + this.bodyAsText().shouldContainJsonKey("$.results.bindings[0].time.value") } } } "nothing exists" { - withTest { + testApplication { httpPost("/orgs/not-exists/repos/not-exists/query") { setSparqlQueryBody(""" select ?o { @@ -49,14 +52,14 @@ class RepoQuery : ModelAny() { } """) }.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } "user query with BASE" { // lock should be pointing to the commit from update - withTest { + testApplication { httpPost("$demoRepoPath/query") { setSparqlQueryBody(""" BASE @@ -64,16 +67,16 @@ class RepoQuery : ModelAny() { ${withAllTestPrefixes(lockCommitQuery)} """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK } } } "get repo metadata graph" { - withTest { + testApplication { httpGet("$demoRepoPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { val branchiri = localIri(masterBranchPath) subject(branchiri) { @@ -89,7 +92,7 @@ class RepoQuery : ModelAny() { } "repo metadata graph only allow head and get" { - withTest { + testApplication { onlyAllowsMethods("$demoRepoPath/graph", setOf( HttpMethod.Head, HttpMethod.Get diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ScratchAny.kt b/src/test/kotlin/org/openmbee/flexo/mms/ScratchAny.kt index 2184f812..c031690e 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ScratchAny.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ScratchAny.kt @@ -3,6 +3,7 @@ package org.openmbee.flexo.mms import org.slf4j.LoggerFactory import org.openmbee.flexo.mms.util.* import io.kotest.core.test.TestCase +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.apache.jena.rdf.model.ResourceFactory @@ -37,9 +38,10 @@ open class ScratchAny: RepoAny() { // create an org before each repo test override suspend fun beforeEach(testCase: TestCase) { super.beforeEach(testCase) - - // creates an empty repo - repoEtag = createRepo(demoOrgPath, demoRepoId, demoRepoName).response.headers[HttpHeaders.ETag]!! + testApplication { + // creates an empty repo + repoEtag = createRepo(demoOrgPath, demoRepoId, demoRepoName).headers[HttpHeaders.ETag]!! + } } } @@ -70,7 +72,7 @@ fun TriplesAsserter.validateScratchTriples( } fun TriplesAsserter.validateCreatedScratchTriples( - createResponse: TestApplicationResponse, + createResponse: HttpResponse, scratchId: String, repoId: String, orgId: String, diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ScratchLdpDc.kt b/src/test/kotlin/org/openmbee/flexo/mms/ScratchLdpDc.kt index c1ec6fdb..561ca86a 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ScratchLdpDc.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ScratchLdpDc.kt @@ -1,5 +1,6 @@ package org.openmbee.flexo.mms +import io.ktor.client.statement.* import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.* @@ -15,8 +16,7 @@ class ScratchLdpDc: ScratchAny() { """.trimIndent()), resourceCreator = { createScratch(demoScratchPath, demoScratchName) } ) { - // FIXME this function needs rewriting - done? - fun TriplesAsserter.validCreatedScratch(response: TestApplicationResponse, slug: String) { + fun TriplesAsserter.validCreatedScratch(response: HttpResponse, slug: String) { modelName = "CreateValidScratch" validateCreatedScratchTriples(response, slug, demoRepoId, demoOrgId, demoScratchName, listOf( diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ScratchLoad.kt b/src/test/kotlin/org/openmbee/flexo/mms/ScratchLoad.kt index 8b998a12..f85a234a 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ScratchLoad.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ScratchLoad.kt @@ -1,8 +1,10 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.core.test.TestCase import io.kotest.matchers.shouldBe import io.ktor.http.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.* @@ -12,34 +14,35 @@ class ScratchLoad: ScratchAny() { // create a scratch before each test override suspend fun beforeEach(testCase: TestCase) { super.beforeEach(testCase) - createScratch(demoScratchPath, demoScratchName) + testApplication { + createScratch(demoScratchPath, demoScratchName) + } } init{ "load nothing on empty graph" { - withTest { + testApplication { httpPut("$demoScratchPath/graph") { setTurtleBody("") }.apply { - response shouldHaveStatus HttpStatusCode.NoContent + this shouldHaveStatus HttpStatusCode.NoContent } } } "load data on empty graph" { - withTest { + testApplication { httpPut("$demoScratchPath/graph") { setTurtleBody(loadAliceRex) }.apply { - response shouldHaveStatus HttpStatusCode.NoContent + this shouldHaveStatus HttpStatusCode.NoContent } } } "load data on non-empty graph" { - loadScratch(demoScratchPath, loadAliceRex) - - withTest { + testApplication { + loadScratch(demoScratchPath, loadAliceRex) httpPut("$demoScratchPath/graph") { setTurtleBody(""" $loadAliceRex @@ -48,19 +51,18 @@ class ScratchLoad: ScratchAny() { foaf:name "Xavier" . """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.NoContent + this shouldHaveStatus HttpStatusCode.NoContent } } } "load clear on non-empty graph" { - loadScratch(demoScratchPath, loadAliceRex) - - withTest { + testApplication { + loadScratch(demoScratchPath, loadAliceRex) httpPut("$demoScratchPath/graph") { setTurtleBody("") }.apply { - response shouldHaveStatus HttpStatusCode.NoContent + this shouldHaveStatus HttpStatusCode.NoContent } } } @@ -96,7 +98,7 @@ class ScratchLoad: ScratchAny() { // } "gsp endpoint for scratches rejects other methods" { - withTest { + testApplication { onlyAllowsMethods( "$demoScratchPath/graph", setOf( HttpMethod.Head, diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ScratchQuery.kt b/src/test/kotlin/org/openmbee/flexo/mms/ScratchQuery.kt index 675b009a..13abe084 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ScratchQuery.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ScratchQuery.kt @@ -1,8 +1,11 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.core.test.TestCase import io.kotest.matchers.string.shouldContain +import io.ktor.client.statement.* import io.ktor.http.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.util.* import kotlinx.serialization.json.Json import kotlinx.serialization.json.jsonArray @@ -14,27 +17,27 @@ class ScratchQuery: ScratchAny() { // create an org before each repo test override suspend fun beforeEach(testCase: TestCase) { super.beforeEach(testCase) - createScratch(demoScratchPath, demoScratchName) + testApplication { + createScratch(demoScratchPath, demoScratchName) + } } init { "query data from scratch" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) httpPost("$demoScratchPath/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson queryNamesAliceResult + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson queryNamesAliceResult } } } "query scratch with graph var" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) // master model is updated httpPost("$demoScratchPath/query") { setSparqlQueryBody(""" @@ -45,14 +48,14 @@ class ScratchQuery: ScratchAny() { } """.trimIndent()) }.apply { - val graphVal = Json.parseToJsonElement(response.content!!).jsonObject["results"]!! + val graphVal = Json.parseToJsonElement(this.bodyAsText()).jsonObject["results"]!! .jsonObject["bindings"]!!.jsonArray[0].jsonObject["g"]!!.jsonObject["value"]!! .jsonPrimitive.content graphVal shouldContain "/graphs/Scratch." - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { binding( "g" to graphVal.bindingUri ) @@ -62,9 +65,8 @@ class ScratchQuery: ScratchAny() { } "query scratch with from default not authorized" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) // scratch is updated?? httpPost("$demoScratchPath/query") { setSparqlQueryBody(withAllTestPrefixes(""" @@ -75,15 +77,14 @@ class ScratchQuery: ScratchAny() { } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.Forbidden + this shouldHaveStatus HttpStatusCode.Forbidden } } } "query scratch with from named not authorized" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) // master model is updated httpPost("$demoScratchPath/query") { setSparqlQueryBody(withAllTestPrefixes(""" @@ -96,15 +97,14 @@ class ScratchQuery: ScratchAny() { } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.Forbidden + this shouldHaveStatus HttpStatusCode.Forbidden } } } "query scratch graph not there" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) // master model is updated httpPost("$demoScratchPath/query") { setSparqlQueryBody(withAllTestPrefixes(""" @@ -115,8 +115,8 @@ class ScratchQuery: ScratchAny() { } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { varsExpect.addAll(listOf( "s", "p", "o" )) @@ -126,9 +126,8 @@ class ScratchQuery: ScratchAny() { } "ask scratch: true" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) httpPost("$demoScratchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -138,8 +137,8 @@ class ScratchQuery: ScratchAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson """ + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson """ { "head": {}, "boolean": true @@ -150,9 +149,8 @@ class ScratchQuery: ScratchAny() { } "ask scratch: false" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) httpPost("$demoScratchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -162,8 +160,8 @@ class ScratchQuery: ScratchAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response shouldEqualSparqlResultsJson """ + this shouldHaveStatus HttpStatusCode.OK + this shouldEqualSparqlResultsJson """ { "head": {}, "boolean": false @@ -174,9 +172,8 @@ class ScratchQuery: ScratchAny() { } "describe scratch explicit" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) httpPost("$demoScratchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -184,8 +181,8 @@ class ScratchQuery: ScratchAny() { describe :Alice """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { subjectTerse(":Alice") { ignoreAll() } @@ -195,9 +192,8 @@ class ScratchQuery: ScratchAny() { } "describe scratch where" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) httpPost("$demoScratchPath/query") { setSparqlQueryBody( """ @@ -209,8 +205,8 @@ class ScratchQuery: ScratchAny() { """.trimIndent() ) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response includesTriples { + this shouldHaveStatus HttpStatusCode.OK + this includesTriples { subjectTerse(":Rex") { ignoreAll() } @@ -251,19 +247,18 @@ class ScratchQuery: ScratchAny() { // } "nothing exists" { - withTest { + testApplication { httpPost("/orgs/not-exists/repos/not-exists/scratches/not-exists/query") { setSparqlQueryBody(queryNames) }.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } "concat" { - updateScratch(demoScratchPath, insertAliceRex) - - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) httpPost("$demoScratchPath/query") { setSparqlQueryBody(""" $demoPrefixesStr @@ -275,8 +270,8 @@ class ScratchQuery: ScratchAny() { } """.trimIndent()) }.apply { - response shouldHaveStatus HttpStatusCode.OK - response equalsSparqlResults { + this shouldHaveStatus HttpStatusCode.OK + this equalsSparqlResults { binding( "concat" to "test:Alice".bindingLit ) diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ScratchRead.kt b/src/test/kotlin/org/openmbee/flexo/mms/ScratchRead.kt index f16fea2e..f9d7f7f3 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ScratchRead.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ScratchRead.kt @@ -1,5 +1,7 @@ +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.core.test.TestCase import io.ktor.http.* +import io.ktor.server.testing.* import org.openmbee.flexo.mms.ScratchAny import org.openmbee.flexo.mms.util.* @@ -7,28 +9,28 @@ class ScratchRead : ScratchAny() { // create a scratch before each test override suspend fun beforeEach(testCase: TestCase) { super.beforeEach(testCase) - createScratch(demoScratchPath, demoScratchName) + testApplication { + createScratch(demoScratchPath, demoScratchName) + } } init { "head scratch" { - loadScratch(demoScratchPath, loadAliceRex) - - withTest { + testApplication { + loadScratch(demoScratchPath, loadAliceRex) httpHead("$demoScratchPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK } } } "get scratch" { - loadScratch(demoScratchPath, loadAliceRex) - - withTest { + testApplication { + loadScratch(demoScratchPath, loadAliceRex) httpGet("$demoScratchPath/graph") {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { subjectTerse(":Alice") { ignoreAll() } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/ScratchUpdate.kt b/src/test/kotlin/org/openmbee/flexo/mms/ScratchUpdate.kt index bd615f3b..93601f4e 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/ScratchUpdate.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/ScratchUpdate.kt @@ -1,7 +1,9 @@ package org.openmbee.flexo.mms +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.core.test.TestCase import io.ktor.http.* +import io.ktor.server.testing.* import org.apache.jena.rdf.model.ResourceFactory import org.openmbee.flexo.mms.util.* @@ -9,17 +11,19 @@ class ScratchUpdate: ScratchAny() { // create a scratch before each test override suspend fun beforeEach(testCase: TestCase) { super.beforeEach(testCase) - createScratch(demoScratchPath, demoScratchName) + testApplication { + createScratch(demoScratchPath, demoScratchName) + } } init { "insert data" { val updateBody = mutableListOf(insertAliceRex, insertBobFluffy).joinToString(";\n") - withTest { + testApplication { httpPost("$demoScratchPath/update") { setSparqlUpdateBody(updateBody) } httpGet("$demoScratchPath/graph") {}.apply { - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { val people = demoPrefixes.get("") subject("${people}Alice") { ignoreAll() @@ -78,14 +82,14 @@ class ScratchUpdate: ScratchAny() { } """.trimIndent() ).joinToString(";\n") - withTest { + testApplication { httpPost("$demoScratchPath/update") { setSparqlUpdateBody(updateBody) }.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK } httpGet("$demoScratchPath/graph") {}.apply { - response.exclusivelyHasTriples { + this.exclusivelyHasTriples { subject("urn:these") { exclusivelyHas(ResourceFactory.createProperty("urn:more") exactly ResourceFactory.createResource("urn:inserts")) } @@ -98,20 +102,20 @@ class ScratchUpdate: ScratchAny() { } "update on non-empty scratch" { - updateScratch(demoScratchPath, insertAliceRex) val updateBody = """ insert data { . } """.trimIndent() - withTest { + testApplication { + updateScratch(demoScratchPath, insertAliceRex) httpPost("$demoScratchPath/update") { setSparqlUpdateBody(updateBody) }.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK } httpGet("$demoScratchPath/graph") {}.apply { - response.includesTriples { + this.includesTriples { subject("urn:this") { exclusivelyHas(ResourceFactory.createProperty("urn:is") exactly ResourceFactory.createResource("urn:inserted")) } @@ -134,14 +138,14 @@ class ScratchUpdate: ScratchAny() { . } """.trimIndent() - withTest { + testApplication { httpPost("$demoScratchPath/update") { setSparqlUpdateBody(updateBody) }.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK } httpGet("$demoScratchPath/graph") {}.apply { - response.includesTriples { + this.includesTriples { subject("urn:this") { exclusivelyHas(ResourceFactory.createProperty("urn:is") exactly ResourceFactory.createResource("urn:inserted")) } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/BlazegraphBackend.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/BlazegraphBackend.kt deleted file mode 100644 index 8571cd32..00000000 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/BlazegraphBackend.kt +++ /dev/null @@ -1,106 +0,0 @@ -package org.openmbee.flexo.mms.util - -import com.sun.net.httpserver.HttpServer -import java.io.File -import java.net.InetSocketAddress -import java.net.URI -import java.net.http.HttpClient -import java.net.http.HttpRequest -import java.net.http.HttpResponse.BodyHandlers -import java.nio.charset.StandardCharsets -import java.util.* - -/** - * Runs a Blazegraph server in a separate process. Not used anymore and probably - * can be deleted, but kept here for reference. - */ -class BlazegraphBackend : SparqlBackend { - private val server = HttpServer.create() - private val id = UUID.randomUUID().toString() - private var started = false - - override fun start() { - if (started) { - throw IllegalStateException("Already started") - } - started = true - server.bind(InetSocketAddress(0), 16) - server.createContext("/") { exchange -> - exchange.responseBody.writer(StandardCharsets.UTF_8).use { writer -> - writer.write(id) - } - } - val cmd = listOf( - System.getProperty("java.home") + File.separator + "bin" + File.separator + "java", - "-cp", - System.getProperty("java.class.path"), - javaClass.name + "Kt", - id, - server.address.port.toString() - ) - val workingDir = File("build" + File.separator + "blazegraph") - if (!workingDir.exists()) { - workingDir.mkdirs() - } - File(workingDir, "blazegraph.jnl").delete() - File(workingDir, "rules.log").delete() - val p = ProcessBuilder(cmd) - .directory(workingDir) - .start() - val s = Scanner(p.inputStream) - println("Waiting for BlazeGraph...") - while (s.hasNext()) { - val line = s.nextLine() - println(line) - if (line.startsWith("Go to")) { - break - } - } - println("BlazeGraph Ready") - } - - override fun stop() { - server.stop(0) - } - - override fun getQueryUrl(): String { - return "http://localhost:9999/blazegraph/sparql" - } - - override fun getUpdateUrl(): String { - return getQueryUrl(); - } - - override fun getGspUrl(): String { - return getQueryUrl(); - } -} - -fun main(args: Array) { - val cmd = listOf( - System.getProperty("java.home") + File.separator + "bin" + File.separator + "java", - "-jar", - "/Users/gaspardo/Downloads/blazegraph.jar" - ) - println("[START BLAZEGRAPH]") - val p = ProcessBuilder(cmd) - .inheritIO() - .start() - try { - var client = HttpClient.newHttpClient() - while (true) { - val req = HttpRequest.newBuilder(URI("http://localhost:" + args[1])) - .GET() - .build() - var res = client.send(req, BodyHandlers.ofString()) - if (res.body().trim() != args[1]) { - throw IllegalStateException("Unexpected ID") - } - Thread.sleep(100) - } - } catch (e: Exception) { - println("[STOP BLAZEGRAPH BECAUSE ${e.message}]") - } finally { - p.destroy() - } -} \ No newline at end of file diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/Common.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/Common.kt index 69872269..347c84a9 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/Common.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/util/Common.kt @@ -1,6 +1,5 @@ package org.openmbee.flexo.mms.util -import io.kotest.core.NamedTag import io.kotest.core.spec.Spec import io.kotest.core.spec.style.StringSpec import io.kotest.core.test.TestCase @@ -14,10 +13,6 @@ import org.apache.jena.sparql.exec.http.UpdateExecutionHTTP import java.io.File import java.io.FileOutputStream -val NoAuth = NamedTag("NoAuth") - -val Expect404 = NamedTag("Expect404") - val backend = RemoteBackend() fun escapeFileName(name: String): String { diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/Environment.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/Environment.kt index 3210c359..2aad14c5 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/Environment.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/util/Environment.kt @@ -21,26 +21,3 @@ fun testEnv(): ApplicationEngineEnvironment { } } - -fun withTest(testName: String, test: TestScope?, engine: TestApplicationEngine.(String) -> R) : R { - return withSystemProperties(mapOf( - "FLEXO_MMS_QUERY_URL" to backend.getQueryUrl(), - "FLEXO_MMS_UPDATE_URL" to backend.getQueryUrl(), - "FLEXO_MMS_GRAPH_STORE_PROTOCOL_URL" to backend.getGspUrl(), - )) { - System.setProperty("FLEXO_MMS_TEST_NO_AUTH", if(test?.testCase?.config?.tags?.contains(NoAuth) == true) "1" else "") - System.setProperty("FLEXO_MMS_TEST_EXPECT", if(test?.testCase?.config?.tags?.contains(Expect404) == true) "404" else "") - withApplication(testEnv()) { - engine(testName) - } - } -} - -fun withTest(test: TestApplicationEngine.(String) -> R) : R { - return withTest("(unnamed)", null, test) -} - - -fun TestScope.withTest(test: TestApplicationEngine.(String) -> R) : R { - return withTest(this.testCase.name.testName, this, test) -} diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/FusekiBackend.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/FusekiBackend.kt deleted file mode 100644 index f0ce8531..00000000 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/FusekiBackend.kt +++ /dev/null @@ -1,66 +0,0 @@ -package org.openmbee.flexo.mms.util - -import java.io.File -import java.lang.reflect.Constructor -import java.lang.reflect.Method -import java.net.ServerSocket -import java.net.URLClassLoader - -/** - * Fuseki SPARQL backend. Runs fuseki-server JAR in an isolated ClassLoader using an in-memory dataset. - */ -class FusekiBackend : SparqlBackend { - - companion object { - private val datasetGraphInMemoryConstructor: Constructor<*> - private val makeFusekiMethod: Method - private val startFusekiMethod: Method - private val stopFusekiMethod: Method - - init { - val fusekiJarUrls = (File("build" + File.separator + "test-fuseki-server").listFiles() ?: arrayOf()) - .filter { it.extension.lowercase() == "jar" } - .map { it.toURI().toURL() } - .toTypedArray() - if (fusekiJarUrls.isEmpty()) { - throw IllegalStateException("No fuseki-server JAR Found; run gradle build to initialize") - } - val bootstrapClassLoader = ClassLoader.getSystemClassLoader().parent - val fusekiClassLoader = URLClassLoader(fusekiJarUrls, bootstrapClassLoader) - - val fusekiServerClass = fusekiClassLoader.loadClass("org.apache.jena.fuseki.main.FusekiServer") - makeFusekiMethod = fusekiServerClass.getMethod("make", Integer.TYPE, fusekiClassLoader.loadClass("java.lang.String"), fusekiClassLoader.loadClass("org.apache.jena.sparql.core.DatasetGraph")) - startFusekiMethod = fusekiServerClass.getMethod("start") - stopFusekiMethod = fusekiServerClass.getMethod("stop") - datasetGraphInMemoryConstructor = - fusekiClassLoader.loadClass("org.apache.jena.sparql.core.mem.DatasetGraphInMemory") - .getConstructor() - } - } - - /** Port to use for fuseki. Finds a random open port */ - private val fusekiPort = ServerSocket(0).use { it.localPort } - - /** FusekiServer object */ - private val fusekiServer = makeFusekiMethod.invoke(null, fusekiPort, "/ds", datasetGraphInMemoryConstructor.newInstance()); - - override fun start() { - startFusekiMethod.invoke(fusekiServer) - } - - override fun stop() { - stopFusekiMethod.invoke(fusekiServer) - } - - override fun getQueryUrl(): String { - return "http://localhost:${fusekiPort}/ds/query" - } - - override fun getUpdateUrl(): String { - return "http://localhost:${fusekiPort}/ds/update" - } - - override fun getGspUrl(): String { - return "http://localhost:${fusekiPort}/ds/data" - } -} \ No newline at end of file diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/Helper.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/Helper.kt index 5b8e122d..ee3e02a5 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/Helper.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/util/Helper.kt @@ -2,145 +2,104 @@ package org.openmbee.flexo.mms.util import io.ktor.client.* import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.ktor.http.* import io.ktor.server.testing.* import org.openmbee.flexo.mms.* import java.net.URLEncoder - -fun createOrg(orgId: String, orgName: String): TestApplicationCall { - return withTest { - httpPut("/orgs/$orgId") { - setTurtleBody(""" - <> dct:title "$orgName"@en . - """.trimIndent()) - }.apply { - response shouldHaveStatus HttpStatusCode.Created - - // assert it exists - httpGet("/orgs/$orgId") {}.apply { - response shouldHaveStatus 200 - } - } +suspend fun ApplicationTestBuilder.createOrg(orgId: String, orgName: String): HttpResponse { + val response = httpPut("/orgs/$orgId") { + setTurtleBody(""" + <> dct:title "$orgName"@en . + """.trimIndent()) } + response shouldHaveStatus HttpStatusCode.Created + return response } -fun createRepo(orgPath: String, repoId: String, repoName: String): TestApplicationCall { - return withTest { - httpPut("$orgPath/repos/$repoId") { - setTurtleBody(""" - <> dct:title "$repoName"@en . - """.trimIndent()) - }.apply { - response shouldHaveStatus HttpStatusCode.Created - - // assert it exists - httpGet("/$orgPath/repos/$repoId") {}.apply { - response shouldHaveStatus 200 - } - } +suspend fun ApplicationTestBuilder.createRepo(orgPath: String, repoId: String, repoName: String): HttpResponse { + val response = httpPut("$orgPath/repos/$repoId") { + setTurtleBody(""" + <> dct:title "$repoName"@en . + """.trimIndent()) } + response shouldHaveStatus HttpStatusCode.Created + return response } -// Creates an empty scratch -fun createScratch(path: String, scratchName: String): TestApplicationCall { - return withTest { - httpPut(path) { - setTurtleBody(""" - <> dct:title "$scratchName"@en . - """) - }.apply { - response shouldHaveStatus HttpStatusCode.Created - - // assert it exists - httpGet(path) {}.apply { - response shouldHaveStatus 200 - } - } +suspend fun ApplicationTestBuilder.createScratch(path: String, scratchName: String): HttpResponse { + val response = httpPut(path) { + setTurtleBody(""" + <> dct:title "$scratchName"@en . + """.trimIndent()) } + response shouldHaveStatus HttpStatusCode.Created + return response } -fun createBranch(repoPath: String, refId: String, branchId: String, branchName: String): TestApplicationCall { - return withTest { - httpPut("$repoPath/branches/$branchId") { - setTurtleBody(""" - <> dct:title "$branchName"@en . - <> mms:ref <./$refId> . - """.trimIndent()) - }.apply { - response shouldHaveStatus HttpStatusCode.Created - - // assert it exists - httpGet("/$repoPath/branches/$branchId") {}.apply { - this.response shouldHaveStatus 200 - } - } +suspend fun ApplicationTestBuilder.createBranch(repoPath: String, refId: String, branchId: String, branchName: String): HttpResponse { + val response = httpPut("$repoPath/branches/$branchId") { + setTurtleBody(""" + <> dct:title "$branchName"@en . + <> mms:ref <./$refId> . + """.trimIndent()) } + response shouldHaveStatus HttpStatusCode.Created + return response } -fun createLock(repoPath: String, refPath: String, lockId: String): TestApplicationCall { - return withTest { - httpPut("$repoPath/locks/$lockId") { - setTurtleBody(""" - <> mms:ref <$refPath> . - """.trimIndent()) - }.apply { - response shouldHaveStatus HttpStatusCode.Created - } +suspend fun ApplicationTestBuilder.createLock(repoPath: String, refPath: String, lockId: String): HttpResponse { + val response = httpPut("$repoPath/locks/$lockId") { + setTurtleBody(""" + <> mms:ref <$refPath> . + """.trimIndent()) } + response shouldHaveStatus HttpStatusCode.Created + return response } -fun createGroup(groupId: String, groupTitle: String): TestApplicationCall { - return withTest { - httpPut("/groups/${URLEncoder.encode(groupId, "UTF-8")}") { - setTurtleBody(""" - <> dct:title "${groupTitle}"@en . - """.trimIndent()) - }.apply { - response shouldHaveStatus HttpStatusCode.Created - } +suspend fun ApplicationTestBuilder.createGroup(groupId: String, groupTitle: String): HttpResponse { + val response = httpPut("/groups/${URLEncoder.encode(groupId, "UTF-8")}") { + setTurtleBody(""" + <> dct:title "${groupTitle}"@en . + """.trimIndent()) } + response shouldHaveStatus HttpStatusCode.Created + return response } -// For inserting things into already created scratches, sparql should be a query -fun updateScratch(scratchPath: String, sparql: String): TestApplicationCall { - return withTest { - httpPost("$scratchPath/update") { - setSparqlUpdateBody(sparql) - }.apply { - response shouldHaveStatus HttpStatusCode.OK - } +suspend fun ApplicationTestBuilder.updateScratch(scratchPath: String, sparql: String): HttpResponse { + val response = httpPost("$scratchPath/update") { + setSparqlUpdateBody(sparql) } + response shouldHaveStatus HttpStatusCode.OK + return response } -fun commitModel(refPath: String, sparql: String): TestApplicationCall { - return withTest { - httpPost("$refPath/update") { - setSparqlUpdateBody(sparql) - }.apply { - response shouldHaveStatus HttpStatusCode.Created - } +suspend fun ApplicationTestBuilder.commitModel(refPath: String, sparql: String): HttpResponse { + val response = httpPost("$refPath/update") { + setSparqlUpdateBody(sparql) } + response shouldHaveStatus HttpStatusCode.Created + return response } -fun loadModel(refPath: String, turtle: String): TestApplicationCall { - return withTest { - httpPut("$refPath/graph") { - setTurtleBody(turtle) - }.apply { - response shouldHaveStatus HttpStatusCode.OK - } +suspend fun ApplicationTestBuilder.loadModel(refPath: String, turtle: String): HttpResponse { + val response = httpPut("$refPath/graph") { + setTurtleBody(turtle) } + response shouldHaveStatus HttpStatusCode.OK + return response } -fun loadScratch(scratchPath: String, turtle: String): TestApplicationCall { - return withTest { - httpPut("$scratchPath/graph") { - setTurtleBody(turtle) - }.apply { - response shouldHaveStatus HttpStatusCode.NoContent - } +suspend fun ApplicationTestBuilder.loadScratch(scratchPath: String, turtle: String): HttpResponse { + val response = httpPut("$scratchPath/graph") { + setTurtleBody(turtle) } + response shouldHaveStatus HttpStatusCode.NoContent + return response } fun includePrefixes(vararg prefixKeys: String, extraSetup: (PrefixMapBuilder.() -> Unit)?=null): String { diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/JsonAssertions.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/JsonAssertions.kt index 7a7b4573..2c4c6ed8 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/JsonAssertions.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/util/JsonAssertions.kt @@ -2,9 +2,11 @@ package org.openmbee.flexo.mms.util import io.kotest.assertions.fail import io.kotest.assertions.json.shouldBeJsonObject +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldStartWith +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import kotlinx.serialization.json.* @@ -91,14 +93,14 @@ class JsonAsserter(json: JsonElement, var resultsName: String="Unnamed") { } } -infix fun TestApplicationResponse.equalsSparqlResults(build: JsonAsserter.() -> Unit) { +suspend infix fun HttpResponse.equalsSparqlResults(build: JsonAsserter.() -> Unit) { this shouldHaveStatus HttpStatusCode.OK // assert content-type header (ignore charset if present) this.headers[HttpHeaders.ContentType].shouldStartWith(RdfContentTypes.SparqlResultsJson.contentType) // load str - val jsonStr = this.content.toString() + val jsonStr = bodyAsText() // json object jsonStr.shouldBeJsonObject() diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/KtorAssertions.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/KtorAssertions.kt deleted file mode 100644 index 4de589dd..00000000 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/KtorAssertions.kt +++ /dev/null @@ -1,136 +0,0 @@ -package org.openmbee.flexo.mms.util - -import io.kotest.matchers.Matcher -import io.kotest.matchers.MatcherResult -import io.kotest.matchers.should -import io.kotest.matchers.shouldNot -import io.ktor.http.* -import io.ktor.server.response.* -import io.ktor.server.testing.* - - -infix fun TestApplicationResponse.shouldHaveETag(etag: String) = this should haveETag(etag) -infix fun TestApplicationResponse.shouldNotHaveETag(etag: String) = this shouldNot haveETag(etag) -fun haveETag(expected: String) = object : Matcher { - override fun test(value: TestApplicationResponse): MatcherResult { - val actual = value.headers[HttpHeaders.ETag] - return MatcherResult( - actual == expected, - { "Response should have ETag $expected but had ${actual}. Response body: ${value.content}" }, - { "Response should not have ETag $expected. Response body: ${value.content}" } - ) - } -} - -infix fun TestApplicationResponse.shouldHaveCacheControl(cacheControl: String) = this should haveCacheControl(cacheControl) -infix fun TestApplicationResponse.shouldNotCacheControl(cacheControl: String) = this shouldNot haveCacheControl(cacheControl) -fun haveCacheControl(expected: String) = object : Matcher { - override fun test(value: TestApplicationResponse): MatcherResult { - val actual = value.headers[HttpHeaders.CacheControl] - return MatcherResult( - actual == expected, - { "Response should have Cache-Control: $expected but had: ${actual}. Response body: ${value.content}" }, - { "Response should not have Cache-Control $expected. Response body: ${value.content}" } - ) - } -} - -infix fun TestApplicationResponse.shouldHaveContentEncoding(encoding: String) = this should haveContentEncoding(encoding) -infix fun TestApplicationResponse.shouldNotHaveContentEncoding(encoding: String) = this shouldNot haveContentEncoding(encoding) -fun haveContentEncoding(expected: String) = object : Matcher { - override fun test(value: TestApplicationResponse): MatcherResult { - val actual = value.headers[HttpHeaders.ContentEncoding] - return MatcherResult( - actual == expected, - { "Response should have Content-Encoding: $expected but had: ${actual}. Response body: ${value.content}" }, - { "Response should not have Content-Encoding $expected. Response body: ${value.content}" } - ) - } -} - -infix fun TestApplicationResponse.shouldHaveStatus(httpStatusCode: HttpStatusCode) = this.shouldHaveStatus(httpStatusCode.value) -infix fun TestApplicationResponse.shouldHaveStatus(code: Int) = this should haveStatus(code) -infix fun TestApplicationResponse.shouldNotHaveStatus(httpStatusCode: HttpStatusCode) = this.shouldNotHaveStatus(httpStatusCode.value) -infix fun TestApplicationResponse.shouldNotHaveStatus(code: Int) = this shouldNot haveStatus(code) -fun haveStatus(code: Int) = object : Matcher { - override fun test(value: TestApplicationResponse): MatcherResult { - return MatcherResult( - value.status()?.value == code, - { "Response should have status $code but had status ${value.status()?.value}. Response body: ${value.content}" }, - { "Response should not have status $code. Response body: ${value.content}" } - ) - } -} - -@JvmName("shouldHaveOneOfStatusesCodes") -infix fun TestApplicationResponse.shouldHaveOneOfStatuses(httpStatusCodes: Set) = this.shouldHaveOneOfStatuses(httpStatusCodes.map { it.value }.toSet()) -@JvmName("shouldHaveOneOfStatusesInts") -infix fun TestApplicationResponse.shouldHaveOneOfStatuses(codes: Set) = this should haveOneOfStatuses(codes) -infix fun TestApplicationResponse.shouldNotHaveStatus(httpStatusCodes: Set) = this.shouldNotHaveOneOfStatuses(httpStatusCodes.map { it.value }.toSet()) -infix fun TestApplicationResponse.shouldNotHaveOneOfStatuses(codes: Set) = this shouldNot haveOneOfStatuses(codes) -fun haveOneOfStatuses(codes: Set) = object : Matcher { - override fun test(value: TestApplicationResponse): MatcherResult { - return MatcherResult( - codes.contains(value.status()?.value), - { "Response should have one of the statuses: [${codes.joinToString(", ") { "$it" }}] but had status ${value.status()?.value}. Response body: ${value.content}" }, - { "Response should not have any of the status [${codes.joinToString(", ") { "$it" }}]. Response body: ${value.content}" } - ) - } -} - -infix fun TestApplicationResponse.shouldHaveContent(content: String) = this should haveContent(content) -infix fun TestApplicationResponse.shouldNotHaveContent(content: String) = this shouldNot haveContent(content) -fun haveContent(content: String) = object : Matcher { - override fun test(value: TestApplicationResponse): MatcherResult { - return MatcherResult( - value.content == content, - { "Response should have content $content but had content ${value.content}" }, - { "Response should not have content $content" } - ) - } -} - -fun TestApplicationResponse.shouldHaveContentType(contentType: ContentType) = - this should haveContentType(contentType) - -fun TestApplicationResponse.shouldNotHaveContentType(contentType: ContentType) = - this shouldNot haveContentType(contentType) - -fun haveContentType(contentType: ContentType) = object : Matcher { - override fun test(value: TestApplicationResponse): MatcherResult { - return MatcherResult( - value.contentType() == contentType, - { "Response should have ContentType $contentType but was ${value.contentType()}" }, - { "Response should not have ContentType $contentType" } - ) - } -} - -fun TestApplicationResponse.shouldHaveHeader(name: String, value: String) = this should haveHeader(name, value) -fun TestApplicationResponse.shouldNotHaveHeader(name: String, value: String) = this shouldNot haveHeader(name, value) -fun haveHeader(headerName: String, headerValue: String) = object : Matcher { - override fun test(value: TestApplicationResponse): MatcherResult { - return MatcherResult( - value.headers[headerName] == headerValue, - { "Response should have header $headerName=$headerValue but $headerName=${value.headers[headerName]}" }, - { "Response should not have header $headerName=$headerValue" } - ) - } -} - -fun TestApplicationResponse.shouldHaveCookie(name: String, cookieValue: String? = null) = this should haveCookie(name, cookieValue) -fun TestApplicationResponse.shouldNotHaveCookie(name: String, cookieValue: String? = null) = this shouldNot haveCookie(name, cookieValue) -fun haveCookie(name: String, cookieValue: String? = null) = object : Matcher { - override fun test(value: ApplicationResponse): MatcherResult { - val passed = when (cookieValue) { - null -> value.cookies[name] != null - else -> value.cookies[name]?.value == cookieValue - } - - return MatcherResult( - passed, - { "Response should have cookie with name $name" }, - { "Response should have cookie with name $name" } - ) - } -} diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/LinkedDataPlatform.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/LinkedDataPlatform.kt index 031514fe..e9257ce0 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/LinkedDataPlatform.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/util/LinkedDataPlatform.kt @@ -1,8 +1,12 @@ package org.openmbee.flexo.mms.util +import io.kotest.assertions.ktor.client.shouldHaveHeader +import io.kotest.assertions.ktor.client.shouldHaveStatus import io.kotest.assertions.withClue import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldNotBeBlank +import io.ktor.client.request.* +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.apache.jena.sparql.vocabulary.FOAF @@ -41,24 +45,24 @@ val PATCH_INSERT_TRIPLES = "<> foaf:homepage ." * Bundles responses for when resources get created in tests */ data class TestApplicationCreatedResponseBundle( - val response: TestApplicationResponse, - val createdBase: TestApplicationResponse, - val createdOthers: List = listOf(), + val response: HttpResponse, + val createdBase: HttpResponse, + val createdOthers: List = listOf(), ) class LinkedDataPlatformDirectContainerTests( val basePath: String, var resourceId: String, var validBodyForCreate: String = "", - val resourceCreator: () -> TestApplicationCall, + val resourceCreator: suspend ApplicationTestBuilder.() -> HttpResponse, val useCreatorLocationForResource: Boolean = false, body: LinkedDataPlatformDirectContainerTests.() -> Unit ) { var resourcePath = "$basePath/${URLEncoder.encode(resourceId, "UTF-8")}" - fun setResource(call: TestApplicationCall) { + fun setResource(call: HttpResponse) { if (useCreatorLocationForResource) { - resourceId = call.response.headers[HttpHeaders.Location]!!.removePrefix("$ROOT_CONTEXT$basePath/") + resourceId = call.headers[HttpHeaders.Location]!!.removePrefix("$ROOT_CONTEXT$basePath/") resourcePath = "$basePath/${URLEncoder.encode(resourceId, "UTF-8")}" } } @@ -68,25 +72,25 @@ class LinkedDataPlatformDirectContainerTests( } // overloaded version of below - fun TestApplicationCall.validateCreatedLdpResource( + suspend fun HttpResponse.validateCreatedLdpResource( testName: String, - validator: (TriplesAsserter.(TestApplicationResponse, String) -> Unit)?=null, + validator: (TriplesAsserter.(HttpResponse, String) -> Unit)?=null, ) { validateCreatedLdpResource(testName, validator, false) } - fun TestApplicationCall.validateCreatedLdpResource( + suspend fun HttpResponse.validateCreatedLdpResource( testName: String, - validator: (TriplesAsserter.(TestApplicationResponse, String) -> Unit)?=null, + validator: (TriplesAsserter.(HttpResponse, String) -> Unit)?=null, slugWasOmitted: Boolean?=false ) { // LDP 4.2.1.3 - Etag withClue("Expected created LDP resource to return ETag header") { - response.headers[HttpHeaders.ETag].shouldNotBeBlank() + this.headers[HttpHeaders.ETag].shouldNotBeBlank() } // LDP 5.2.3.1 - Location header points to new resource - val location = response.headers[HttpHeaders.Location] + val location = this.headers[HttpHeaders.Location] withClue("Expected created LDP resource to return Location header") { location.shouldNotBeBlank() } @@ -111,22 +115,22 @@ class LinkedDataPlatformDirectContainerTests( } // LDP 5.2.3.1 - response with status code 201; body is not required by LDP - response shouldHaveStatus HttpStatusCode.Created - response.exclusivelyHasTriples { + this shouldHaveStatus HttpStatusCode.Created + this exclusivelyHasTriples { modelName = testName - validator?.invoke(this, response, slug) + validator?.invoke(this, this@validateCreatedLdpResource, slug) } } /** * Checks that the LDP direct container responds correctly to various create calls */ - fun CommonSpec.create(validator: (TriplesAsserter.(TestApplicationResponse, String) -> Unit)?=null) { + fun CommonSpec.create(validator: (TriplesAsserter.(HttpResponse, String) -> Unit)?=null) { // POST to the resource container basePath.let { "POST $it - allow missing slug".config(tags = setOf(NoAuth)) { - withTest { + testApplication { httpPost(basePath) { // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) @@ -137,15 +141,15 @@ class LinkedDataPlatformDirectContainerTests( } "POST $it - reject invalid id".config(tags = setOf(NoAuth)) { - withTest { + testApplication { httpPost(basePath) { // use Slug header to define new resource id - addHeader(HttpHeaders.SLUG, "test with invalid id") + header(HttpHeaders.SLUG, "test with invalid id") // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } @@ -153,45 +157,45 @@ class LinkedDataPlatformDirectContainerTests( // conflicting preconditions CONFLICTING_PRECONDITIONS.forEachIndexed { index, preconditions -> "POST $it - reject conflicting preconditions #${index+1}".config(tags=setOf(NoAuth)) { - withTest { + testApplication { httpPost(basePath) { preconditions.forEach { - addHeader(it.key, it.value) + header(it.key, it.value) } // use Slug header to define new resource id - addHeader(HttpHeaders.SLUG, resourceId) + header(HttpHeaders.SLUG, resourceId) // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - response shouldHaveStatus HttpStatusCode.PreconditionFailed + this shouldHaveStatus HttpStatusCode.PreconditionFailed } } } } "POST $it - reject precondition: if-none-match star".config(tags = setOf(NoAuth)) { - withTest { + testApplication { httpPost(basePath) { - addHeader(HttpHeaders.IfNoneMatch, "*") + header(HttpHeaders.IfNoneMatch, "*") // use Slug header to define new resource id - addHeader(HttpHeaders.SLUG, resourceId) + header(HttpHeaders.SLUG, resourceId) // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - response shouldHaveStatus HttpStatusCode.PreconditionFailed + this shouldHaveStatus HttpStatusCode.PreconditionFailed } } } "POST $it - create valid" { - withTest { + testApplication { httpPost(basePath) { // use Slug header to define new resource id - addHeader(HttpHeaders.SLUG, resourceId) + header(HttpHeaders.SLUG, resourceId) // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) @@ -205,26 +209,26 @@ class LinkedDataPlatformDirectContainerTests( // PUT to a specific resource run { "PUT $resourcePath - reject invalid id".config(tags = setOf(NoAuth)) { - withTest { + testApplication { httpPut("$basePath/test with invalid id") { // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } EXHAUSTIVE_PRECONDITIONS.forEach { preconditions -> "PUT $resourcePath - reject failed precondition: if-match $preconditions".config(tags = setOf(NoAuth)) { - withTest { + testApplication { httpPut(resourcePath) { - addHeader(HttpHeaders.IfMatch, preconditions) + header(HttpHeaders.IfMatch, preconditions) // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - response shouldHaveStatus HttpStatusCode.PreconditionFailed + this shouldHaveStatus HttpStatusCode.PreconditionFailed } } } @@ -233,28 +237,28 @@ class LinkedDataPlatformDirectContainerTests( // conflicting preconditions CONFLICTING_PRECONDITIONS.forEachIndexed { index, preconditions -> "PUT $resourcePath - reject conflicting preconditions #${index + 1}".config(tags = setOf(NoAuth)) { - withTest { + testApplication { httpPut(resourcePath) { preconditions.forEach { - addHeader(it.key, it.value) + header(it.key, it.value) } // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - response shouldHaveStatus HttpStatusCode.PreconditionFailed + this shouldHaveStatus HttpStatusCode.PreconditionFailed } } } } "PUT $resourcePath - create valid" { - withTest { + testApplication { httpPut(resourcePath) { // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - validateCreatedLdpResource(it, validator) + validateCreatedLdpResource("PUT $resourcePath - create valid", validator) } } } @@ -262,14 +266,14 @@ class LinkedDataPlatformDirectContainerTests( EXHAUSTIVE_PRECONDITIONS.forEach { preconditions -> "PUT $resourcePath - create valid with precondition: if-none-match $preconditions" { - withTest { + testApplication { httpPut(resourcePath) { - addHeader(HttpHeaders.IfNoneMatch, preconditions) + header(HttpHeaders.IfNoneMatch, preconditions) // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - validateCreatedLdpResource(it, validator) + validateCreatedLdpResource("PUT $resourcePath - create valid with precondition: if-none-match $preconditions", validator) } } } @@ -281,20 +285,20 @@ class LinkedDataPlatformDirectContainerTests( * Checks that the LDP direct container responds correctly to POST'ing with precondition */ fun CommonSpec.postWithPrecondition( - validation: (TestApplicationCall.(testName: String) -> Unit) + validation: suspend (HttpResponse.(testName: String) -> Unit) ) { "POST $basePath - with precondition: if-match star".config(tags = setOf(NoAuth)) { - withTest { + testApplication { httpPost(basePath) { - addHeader(HttpHeaders.IfMatch, "*") + header(HttpHeaders.IfMatch, "*") // use Slug header to define new resource id - addHeader(HttpHeaders.SLUG, resourceId) + header(HttpHeaders.SLUG, resourceId) // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { - validation(it) + validation("POST $basePath - with precondition: if-match star") } } } @@ -304,145 +308,145 @@ class LinkedDataPlatformDirectContainerTests( * Checks that the LDP direct container responds correctly to various read calls */ fun CommonSpec.read( - vararg creators: () -> TestApplicationCall, - validator: ((TestApplicationCreatedResponseBundle) -> Unit) + vararg creators: suspend ApplicationTestBuilder.() -> HttpResponse, + validator: suspend ((TestApplicationCreatedResponseBundle) -> Unit) ) { "HEAD $basePath - empty" { - withTest { + testApplication { httpHead(basePath) {}.apply { - response shouldHaveStatus HttpStatusCode.NoContent - response.headers["ETag"].shouldNotBeBlank() + this shouldHaveStatus HttpStatusCode.NoContent + this.headers["ETag"].shouldNotBeBlank() } } } "GET $basePath - empty" { - withTest { + testApplication { httpGet(basePath) {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response.headers["ETag"].shouldNotBeBlank() + this shouldHaveStatus HttpStatusCode.OK + this.headers["ETag"].shouldNotBeBlank() } } } "HEAD $resourcePath - non-existent" { - withTest { + testApplication { httpHead(resourcePath) {}.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } "GET $resourcePath - non-existent" { - withTest { + testApplication { httpGet(resourcePath) {}.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } "HEAD $resourcePath - valid" { - val createdBase = resourceCreator() - val etag = createdBase.response.headers[HttpHeaders.ETag]!! - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + val etag = createdBase.headers[HttpHeaders.ETag]!! + setResource(createdBase) httpHead(resourcePath) {}.apply { - response shouldHaveStatus HttpStatusCode.NoContent - response.shouldHaveHeader(HttpHeaders.ETag, etag) + this shouldHaveStatus HttpStatusCode.NoContent + this.shouldHaveHeader(HttpHeaders.ETag, etag) } } } "GET $resourcePath - valid" { - val createdBase = resourceCreator() - val etag = createdBase.response.headers[HttpHeaders.ETag]!! - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + val etag = createdBase.headers[HttpHeaders.ETag]!! + setResource(createdBase) httpGet(resourcePath) {}.apply { - response shouldHaveStatus HttpStatusCode.OK - response.shouldHaveHeader(HttpHeaders.ETag, etag) + this shouldHaveStatus HttpStatusCode.OK + this.shouldHaveHeader(HttpHeaders.ETag, etag) - validator(TestApplicationCreatedResponseBundle(response, createdBase.response)) + validator(TestApplicationCreatedResponseBundle(this, createdBase)) } } } "GET $resourcePath - if-match etag" { - val createdBase = resourceCreator() - val etag = createdBase.response.headers[HttpHeaders.ETag]!! - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + val etag = createdBase.headers[HttpHeaders.ETag]!! + setResource(createdBase) httpGet(resourcePath) { - addHeader(HttpHeaders.IfMatch, "\"$etag\"") + header(HttpHeaders.IfMatch, "\"$etag\"") }.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK } } } "GET $resourcePath - if-match random" { - val createdBase = resourceCreator() - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + setResource(createdBase) httpGet(resourcePath) { - addHeader(HttpHeaders.IfMatch, "\"${UUID.randomUUID()}\"") + header(HttpHeaders.IfMatch, "\"${UUID.randomUUID()}\"") }.apply { - response shouldHaveStatus HttpStatusCode.PreconditionFailed + this shouldHaveStatus HttpStatusCode.PreconditionFailed } } } "GET $resourcePath - if-none-match etag" { - val createdBase = resourceCreator() - val etag = createdBase.response.headers[HttpHeaders.ETag]!! - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + val etag = createdBase.headers[HttpHeaders.ETag]!! + setResource(createdBase) httpGet(resourcePath) { - addHeader(HttpHeaders.IfNoneMatch, "\"$etag\"") + header(HttpHeaders.IfNoneMatch, "\"$etag\"") }.apply { - response shouldHaveStatus HttpStatusCode.NotModified + this shouldHaveStatus HttpStatusCode.NotModified } } } "GET $resourcePath - if-none-match star" { - val createdBase = resourceCreator() - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + setResource(createdBase) httpGet(resourcePath) { - addHeader(HttpHeaders.IfNoneMatch, "*") + header(HttpHeaders.IfNoneMatch, "*") }.apply { - response shouldHaveStatus HttpStatusCode.NotModified + this shouldHaveStatus HttpStatusCode.NotModified } } } "GET $basePath - all resources" { - val createdBase = resourceCreator() - val createdOthers = creators.map { it() } - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + val createdOthers = creators.map { it() } + setResource(createdBase) httpGet(basePath) {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK - response.includesTriples { - modelName = it + this.includesTriples { + modelName = basePath - validator(TestApplicationCreatedResponseBundle(response, createdBase.response, createdOthers.map { it.response })) + //TODO validator(TestApplicationCreatedResponseBundle(this@apply, createdBase, createdOthers)) } } } } } - fun CommonSpec.replaceExisting(validator: ((TestApplicationResponse) -> Unit)) { + fun CommonSpec.replaceExisting(validator: suspend ((HttpResponse) -> Unit)) { "PUT $resourcePath - replace resource" { - resourceCreator() - withTest { + testApplication { + resourceCreator() httpPut(resourcePath) { setTurtleBody(validBodyForCreate) }.apply { - validator(response) + validator(this) } } } @@ -452,7 +456,7 @@ class LinkedDataPlatformDirectContainerTests( * Checks that the LDP direct container responds correctly to various patch calls */ fun CommonSpec.patch() { - fun validatePatchResponse(response: TestApplicationResponse) { + suspend fun validatePatchResponse(response: HttpResponse) { response shouldHaveStatus HttpStatusCode.OK response includesTriples { @@ -465,23 +469,23 @@ class LinkedDataPlatformDirectContainerTests( } "PATCH $resourcePath - Turtle: insert 1 triple unconditionally" { - val createdBase = resourceCreator() - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + setResource(createdBase) httpPatch(resourcePath) { setTurtleBody(withAllTestPrefixes(""" $PATCH_INSERT_TRIPLES """.trimIndent())) }.apply { - validatePatchResponse(response) + validatePatchResponse(this) } } } "PATCH $resourcePath - SPARQL UPDATE: insert 1 triple unconditionally" { - val createdBase = resourceCreator() - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + setResource(createdBase) httpPatch(resourcePath) { setSparqlUpdateBody(withAllTestPrefixes(""" insert data { @@ -489,15 +493,15 @@ class LinkedDataPlatformDirectContainerTests( } """.trimIndent())) }.apply { - validatePatchResponse(response) + validatePatchResponse(this) } } } "PATCH $resourcePath - SPARQL UPDATE: insert 1 triple conditionally passing" { - val createdBase = resourceCreator() - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + setResource(createdBase) httpPatch(resourcePath) { setSparqlUpdateBody(withAllTestPrefixes(""" insert { @@ -508,15 +512,15 @@ class LinkedDataPlatformDirectContainerTests( } """.trimIndent())) }.apply { - validatePatchResponse(response) + validatePatchResponse(this) } } } "PATCH $resourcePath - SPARQL UPDATE: insert 1 triple conditionally failing" { - val createdBase = resourceCreator() - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + setResource(createdBase) httpPatch(resourcePath) { setSparqlUpdateBody(withAllTestPrefixes(""" insert { @@ -527,15 +531,15 @@ class LinkedDataPlatformDirectContainerTests( } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.PreconditionFailed + this shouldHaveStatus HttpStatusCode.PreconditionFailed } } } "PATCH $resourcePath - SPARQL UPDATE: patch branch with bad delete data" { - val createdBase = resourceCreator() // This creates a tuple - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() // This creates a tuple + setResource(createdBase) httpPatch(resourcePath) { setSparqlUpdateBody( withAllTestPrefixes(""" @@ -545,15 +549,15 @@ class LinkedDataPlatformDirectContainerTests( """.trimIndent()) ) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } "PATCH $resourcePath - SPARQL UPDATE: patch branch with bad insert data" { - val createdBase = resourceCreator() - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() + setResource(createdBase) httpPatch(resourcePath) { setSparqlUpdateBody(withAllTestPrefixes(""" insert data { @@ -561,15 +565,15 @@ class LinkedDataPlatformDirectContainerTests( } """.trimIndent())) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } "PATCH $resourcePath - SPARQL UPDATE: patch branch with bad delete pattern" { - val createdBase = resourceCreator() // This creates a tuple - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() // This creates a tuple + setResource(createdBase) httpPatch(resourcePath) { setSparqlUpdateBody( withAllTestPrefixes(""" @@ -582,15 +586,15 @@ class LinkedDataPlatformDirectContainerTests( """.trimIndent()) ) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } "PATCH $resourcePath - SPARQL UPDATE: patch branch with bad insert pattern" { - val createdBase = resourceCreator() // This creates a tuple - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() // This creates a tuple + setResource(createdBase) httpPatch(resourcePath) { setSparqlUpdateBody( withAllTestPrefixes(""" @@ -603,15 +607,15 @@ class LinkedDataPlatformDirectContainerTests( """.trimIndent()) ) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } "PATCH $resourcePath - SPARQL UPDATE: patch branch with bad delete predicate variable" { - val createdBase = resourceCreator() // This creates a tuple - setResource(createdBase) - withTest { + testApplication { + val createdBase = resourceCreator() // This creates a tuple + setResource(createdBase) httpPatch(resourcePath) { setSparqlUpdateBody( withAllTestPrefixes(""" @@ -624,7 +628,7 @@ class LinkedDataPlatformDirectContainerTests( """.trimIndent()) ) }.apply { - response shouldHaveStatus HttpStatusCode.BadRequest + this shouldHaveStatus HttpStatusCode.BadRequest } } } @@ -636,24 +640,18 @@ class LinkedDataPlatformDirectContainerTests( */ fun CommonSpec.delete() { "DELETE $resourcePath" { - val createdBase = resourceCreator() - - withTest { + testApplication { + val createdBase = resourceCreator() // delete resource should work httpDelete(resourcePath) {}.apply { - response shouldHaveStatus HttpStatusCode.OK + this shouldHaveStatus HttpStatusCode.OK } // get deleted resource should 404 httpGet(resourcePath) {}.apply { - response shouldHaveStatus HttpStatusCode.NotFound + this shouldHaveStatus HttpStatusCode.NotFound } } } } } - -fun TriplesAsserter.validateLdpRead() { - // context - -} diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/RdfAssertions.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/RdfAssertions.kt index 9ef4d7bf..4d72709c 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/RdfAssertions.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/util/RdfAssertions.kt @@ -7,6 +7,7 @@ import io.kotest.assertions.json.shouldEqualJson import io.kotest.assertions.withClue import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldStartWith +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.request.* import io.ktor.server.testing.* @@ -379,29 +380,29 @@ class TriplesAsserter(val model: Model, var modelName: String="Unnamed") { } } -infix fun TestApplicationResponse.includesTriples(assertions: TriplesAsserter.() -> Unit): TriplesAsserter { +suspend infix fun HttpResponse.includesTriples(assertions: TriplesAsserter.() -> Unit): TriplesAsserter { // assert content-type header (ignore charset if present) headers[HttpHeaders.ContentType].shouldStartWith(RdfContentTypes.Turtle.contentType) // parse turtle into model val model = ModelFactory.createDefaultModel() - parseTurtle(content.toString(), model, call.request.uri) + parseTurtle(bodyAsText(), model, call.request.url.toString()) // make triple assertions and then assert the model is empty return TriplesAsserter(model).apply { assertions() } } -infix fun TestApplicationResponse.exclusivelyHasTriples(assertions: TriplesAsserter.() -> Unit) { +suspend infix fun HttpResponse.exclusivelyHasTriples(assertions: TriplesAsserter.() -> Unit) { includesTriples(assertions).assertEmpty() } -infix fun TestApplicationResponse.shouldEqualSparqlResultsJson(expectedJson: String) { +suspend infix fun HttpResponse.shouldEqualSparqlResultsJson(expectedJson: String) { // assert content-type header (ignore charset if present) headers[HttpHeaders.ContentType].shouldStartWith(RdfContentTypes.SparqlResultsJson.contentType) // json object - content!!.shouldBeJsonObject() + bodyAsText().shouldBeJsonObject() // assert equal - content!!.shouldEqualJson(expectedJson) + bodyAsText().shouldEqualJson(expectedJson) } diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/Requests.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/Requests.kt index 9c45f193..66ef87d9 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/Requests.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/util/Requests.kt @@ -2,9 +2,15 @@ package org.openmbee.flexo.mms.util import com.auth0.jwt.JWT import com.auth0.jwt.algorithms.Algorithm +import io.kotest.assertions.ktor.client.shouldHaveHeader +import io.kotest.assertions.ktor.client.shouldHaveStatus +import io.kotest.matchers.collections.shouldBeIn import io.kotest.matchers.string.shouldStartWith +import io.ktor.client.request.* +import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* +import org.junit.runner.Request.method import org.openmbee.flexo.mms.ROOT_CONTEXT import org.openmbee.flexo.mms.server.BuildInfo import java.util.* @@ -53,9 +59,9 @@ private fun authorization(auth: AuthStruct): String { * Extension function to add a Turtle request body with appropriate Content-Type * to a test request */ -fun TestApplicationRequest.setTurtleBody(body: String) { - addHeader("Content-Type", "text/turtle") - addHeader("Content-Length", body.length.toString()) +fun HttpRequestBuilder.setTurtleBody(body: String) { + header("Content-Type", "text/turtle") + header("Content-Length", body.length.toString()) setBody(body) } @@ -63,82 +69,67 @@ fun TestApplicationRequest.setTurtleBody(body: String) { * Extension function to add a SPARQL update request body with appropriate Content-Type * to a test request */ -fun TestApplicationRequest.setSparqlUpdateBody(body: String) { - addHeader("Content-Type", "application/sparql-update") +fun HttpRequestBuilder.setSparqlUpdateBody(body: String) { + header("Content-Type", "application/sparql-update") setBody(body) } -fun TestApplicationRequest.setSparqlQueryBody(body: String) { - addHeader("Content-Type", "application/sparql-query") +fun HttpRequestBuilder.setSparqlQueryBody(body: String) { + header("Content-Type", "application/sparql-query") setBody(body) } -fun TestApplicationEngine.httpRequest(method: HttpMethod, uri: String, setup: TestApplicationRequest.() -> Unit): TestApplicationCall { - if("1" != System.getProperty("FLEXO_MMS_TEST_NO_AUTH", "")) { - handleRequest(method, uri) { - addHeader("Authorization", authorization(anonAuth)) +suspend fun ApplicationTestBuilder.httpRequest(method: HttpMethod, uri: String, skipAnon: Boolean = false, setup: HttpRequestBuilder.() -> Unit): HttpResponse { + if (!skipAnon) { + client.request { + this.method = method + this.url(uri) + header("Authorization", authorization(anonAuth)) setup() }.apply { - if("" != System.getProperty("FLEXO_MMS_TEST_EXPECT", "")) { - response shouldHaveStatus System.getProperty("FLEXO_MMS_TEST_EXPECT").toInt() + if (HttpStatusCode.OK === this.status) { + println("?"); } - else { - if(HttpStatusCode.OK === response.status()) { - println("?"); - } - - response shouldHaveOneOfStatuses setOf( - HttpStatusCode.BadRequest, - HttpStatusCode.Forbidden, - HttpStatusCode.NotFound, - HttpStatusCode.MethodNotAllowed, - HttpStatusCode.NotImplemented, - ) - } - - // else if(method == HttpMethod.Get) { - // - // } else { - // response shouldHaveStatus HttpStatusCode.Forbidden - // } + this.status shouldBeIn setOf( + HttpStatusCode.BadRequest, + HttpStatusCode.Forbidden, + HttpStatusCode.NotFound, + HttpStatusCode.MethodNotAllowed, + HttpStatusCode.NotImplemented, + ) } } - - return handleRequest(method, uri) { - addHeader("Authorization", authorization(rootAuth)) + return client.request { + this.method = method + this.url(uri) + header("Authorization", authorization(rootAuth)) setup() }.apply { - response.shouldHaveHeader("Flexo-MMS-Layer-1", "Version=${BuildInfo.getProperty("build.version")}") + this.shouldHaveHeader("Flexo-MMS-Layer-1", "Version=${BuildInfo.getProperty("build.version")}") } } -fun TestApplicationEngine.httpHead(uri: String, setup: TestApplicationRequest.() -> Unit): TestApplicationCall { - return this.httpRequest(HttpMethod.Head, uri, setup) +suspend fun ApplicationTestBuilder.httpHead(uri: String, skipAnon: Boolean = false, setup: HttpRequestBuilder.() -> Unit): HttpResponse { + return httpRequest(HttpMethod.Head, uri, skipAnon, setup) } - -fun TestApplicationEngine.httpGet(uri: String, setup: TestApplicationRequest.() -> Unit): TestApplicationCall { - return this.httpRequest(HttpMethod.Get, uri, setup) +suspend fun ApplicationTestBuilder.httpGet(uri: String, skipAnon: Boolean = false, setup: HttpRequestBuilder.() -> Unit): HttpResponse { + return httpRequest(HttpMethod.Get, uri, skipAnon, setup) } - -fun TestApplicationEngine.httpPost(uri: String, setup: TestApplicationRequest.() -> Unit): TestApplicationCall { - return this.httpRequest(HttpMethod.Post, uri, setup) +suspend fun ApplicationTestBuilder.httpPost(uri: String, skipAnon: Boolean = false, setup: HttpRequestBuilder.() -> Unit): HttpResponse { + return httpRequest(HttpMethod.Post, uri, skipAnon, setup) } - -fun TestApplicationEngine.httpPut(uri: String, setup: TestApplicationRequest.() -> Unit): TestApplicationCall { - return this.httpRequest(HttpMethod.Put, uri, setup) +suspend fun ApplicationTestBuilder.httpPut(uri: String, skipAnon: Boolean = false, setup: HttpRequestBuilder.() -> Unit): HttpResponse { + return httpRequest(HttpMethod.Put, uri, skipAnon, setup) } - -fun TestApplicationEngine.httpPatch(uri: String, setup: TestApplicationRequest.() -> Unit): TestApplicationCall { - return this.httpRequest(HttpMethod.Patch, uri, setup) +suspend fun ApplicationTestBuilder.httpPatch(uri: String, skipAnon: Boolean = false, setup: HttpRequestBuilder.() -> Unit): HttpResponse { + return httpRequest(HttpMethod.Patch, uri, skipAnon, setup) } - -fun TestApplicationEngine.httpDelete(uri: String, setup: TestApplicationRequest.() -> Unit): TestApplicationCall { - return this.httpRequest(HttpMethod.Delete, uri, setup) +suspend fun ApplicationTestBuilder.httpDelete(uri: String, skipAnon: Boolean = false, setup: HttpRequestBuilder.() -> Unit): HttpResponse { + return httpRequest(HttpMethod.Delete, uri, skipAnon, setup) } - -fun TestApplicationEngine.onlyAllowsMethods(path: String, allowedMethods: Set) { - val verbs: MutableMap TestApplicationCall> = mutableMapOf( +suspend fun ApplicationTestBuilder.onlyAllowsMethods(path: String, allowedMethods: Set) { + val verbs: MutableMap HttpResponse> = mutableMapOf( HttpMethod.Head to { httpHead(it) {} }, HttpMethod.Get to { httpGet(it) {} }, HttpMethod.Post to { httpPost(it) {} }, @@ -158,9 +149,10 @@ fun TestApplicationEngine.onlyAllowsMethods(path: String, allowedMethods: Set Date: Mon, 16 Jun 2025 21:28:33 -0700 Subject: [PATCH 2/3] test: migrated --- .circleci/config.yml | 1 + .../flexo/mms/util/LinkedDataPlatform.kt | 32 +++++++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 890df7de..2036c1ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,6 +42,7 @@ jobs: shell: /bin/bash command: | docker-compose -f src/test/resources/docker-compose.yml up -d + cp src/main/resources/application.conf.test ./src/main/resources/application.conf docker build -t flexo-mms-test:latest -f Dockerfile-Test . docker run --network=flexo-mms-test-network --name flexo-mms-test-container flexo-mms-test:latest SIG_INT=$? diff --git a/src/test/kotlin/org/openmbee/flexo/mms/util/LinkedDataPlatform.kt b/src/test/kotlin/org/openmbee/flexo/mms/util/LinkedDataPlatform.kt index e9257ce0..00205c4b 100644 --- a/src/test/kotlin/org/openmbee/flexo/mms/util/LinkedDataPlatform.kt +++ b/src/test/kotlin/org/openmbee/flexo/mms/util/LinkedDataPlatform.kt @@ -129,9 +129,9 @@ class LinkedDataPlatformDirectContainerTests( fun CommonSpec.create(validator: (TriplesAsserter.(HttpResponse, String) -> Unit)?=null) { // POST to the resource container basePath.let { - "POST $it - allow missing slug".config(tags = setOf(NoAuth)) { + "POST $it - allow missing slug" { testApplication { - httpPost(basePath) { + httpPost(basePath, true) { // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { @@ -140,9 +140,9 @@ class LinkedDataPlatformDirectContainerTests( } } - "POST $it - reject invalid id".config(tags = setOf(NoAuth)) { + "POST $it - reject invalid id" { testApplication { - httpPost(basePath) { + httpPost(basePath, true) { // use Slug header to define new resource id header(HttpHeaders.SLUG, "test with invalid id") @@ -156,9 +156,9 @@ class LinkedDataPlatformDirectContainerTests( // conflicting preconditions CONFLICTING_PRECONDITIONS.forEachIndexed { index, preconditions -> - "POST $it - reject conflicting preconditions #${index+1}".config(tags=setOf(NoAuth)) { + "POST $it - reject conflicting preconditions #${index+1}" { testApplication { - httpPost(basePath) { + httpPost(basePath, true) { preconditions.forEach { header(it.key, it.value) } @@ -175,9 +175,9 @@ class LinkedDataPlatformDirectContainerTests( } } - "POST $it - reject precondition: if-none-match star".config(tags = setOf(NoAuth)) { + "POST $it - reject precondition: if-none-match star" { testApplication { - httpPost(basePath) { + httpPost(basePath, true) { header(HttpHeaders.IfNoneMatch, "*") // use Slug header to define new resource id @@ -208,9 +208,9 @@ class LinkedDataPlatformDirectContainerTests( // PUT to a specific resource run { - "PUT $resourcePath - reject invalid id".config(tags = setOf(NoAuth)) { + "PUT $resourcePath - reject invalid id" { testApplication { - httpPut("$basePath/test with invalid id") { + httpPut("$basePath/test with invalid id", true) { // set valid turtle body for creating new resource setTurtleBody(withAllTestPrefixes(validBodyForCreate)) }.apply { @@ -220,9 +220,9 @@ class LinkedDataPlatformDirectContainerTests( } EXHAUSTIVE_PRECONDITIONS.forEach { preconditions -> - "PUT $resourcePath - reject failed precondition: if-match $preconditions".config(tags = setOf(NoAuth)) { + "PUT $resourcePath - reject failed precondition: if-match $preconditions" { testApplication { - httpPut(resourcePath) { + httpPut(resourcePath, true) { header(HttpHeaders.IfMatch, preconditions) // set valid turtle body for creating new resource @@ -236,9 +236,9 @@ class LinkedDataPlatformDirectContainerTests( // conflicting preconditions CONFLICTING_PRECONDITIONS.forEachIndexed { index, preconditions -> - "PUT $resourcePath - reject conflicting preconditions #${index + 1}".config(tags = setOf(NoAuth)) { + "PUT $resourcePath - reject conflicting preconditions #${index + 1}" { testApplication { - httpPut(resourcePath) { + httpPut(resourcePath, true) { preconditions.forEach { header(it.key, it.value) } @@ -287,9 +287,9 @@ class LinkedDataPlatformDirectContainerTests( fun CommonSpec.postWithPrecondition( validation: suspend (HttpResponse.(testName: String) -> Unit) ) { - "POST $basePath - with precondition: if-match star".config(tags = setOf(NoAuth)) { + "POST $basePath - with precondition: if-match star" { testApplication { - httpPost(basePath) { + httpPost(basePath, true) { header(HttpHeaders.IfMatch, "*") // use Slug header to define new resource id From a10f3bb2503a86f945d5e8e69be68557e5d2a64a Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 11 Aug 2025 21:22:34 -0700 Subject: [PATCH 3/3] fix: remove unnecessary condition to improve performance --- .../org/openmbee/flexo/mms/Conditions.kt | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/src/main/kotlin/org/openmbee/flexo/mms/Conditions.kt b/src/main/kotlin/org/openmbee/flexo/mms/Conditions.kt index 3bcfd67c..c46e81aa 100644 --- a/src/main/kotlin/org/openmbee/flexo/mms/Conditions.kt +++ b/src/main/kotlin/org/openmbee/flexo/mms/Conditions.kt @@ -88,39 +88,19 @@ val BRANCH_COMMIT_CONDITIONS = REPO_CRUD_CONDITIONS.append { } } -val SNAPSHOT_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append { - require("queryableSnapshotExists") { - handler = { layer1 -> "The target model is corrupt. No queryable snapshots found." to HttpStatusCode.InternalServerError } - - """ - graph mor-graph:Metadata { - ?__mms_ref - # select the latest commit from the current named ref - mms:commit ?__mms_baseCommit ; - - # and its etag value - mms:etag ?__mms_etag ; - - # and a queryable snapshot - mms:snapshot/mms:graph ?__mms_queryGraph . - } - """ - } -} - -val REPO_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append { +val REPO_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append { permit(Permission.READ_REPO, Scope.REPO) } -val BRANCH_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append { +val BRANCH_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append { permit(Permission.READ_BRANCH, Scope.BRANCH) } -val LOCK_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append { +val LOCK_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append { permit(Permission.READ_LOCK, Scope.LOCK) } -val ARTIFACT_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append { +val ARTIFACT_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append { permit(Permission.READ_ARTIFACT, Scope.ARTIFACT) } @@ -134,7 +114,7 @@ val SCRATCH_UPDATE_CONDITIONS = REPO_CRUD_CONDITIONS.append { permit(Permission.UPDATE_SCRATCH, Scope.SCRATCH) } -val DIFF_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append { +val DIFF_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append { permit(Permission.READ_DIFF, Scope.DIFF) }