Skip to content

Commit

Permalink
test: Set up plumbing for ZIO Test based E2E-Tests (#3148)
Browse files Browse the repository at this point in the history
  • Loading branch information
BalduinLandolt committed Mar 26, 2024
1 parent 72476e3 commit a9a7993
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 1 deletion.
83 changes: 83 additions & 0 deletions integration/src/test/scala/org/knora/webapi/E2EZSpec.scala
@@ -0,0 +1,83 @@
/*
* Copyright © 2021 - 2024 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors.
* SPDX-License-Identifier: Apache-2.0
*/

package org.knora.webapi

import zio._
import zio.http._
import zio.json._
import zio.test._

import org.knora.webapi.core.AppServer
import org.knora.webapi.core.LayersTest
import org.knora.webapi.core.TestStartupUtils
import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject

abstract class E2EZSpec extends ZIOSpecDefault with TestStartupUtils {

private lazy val testLayers = util.Logger.text() >>> core.LayersTest.integrationTestsWithFusekiTestcontainers()

def rdfDataObjects: List[RdfDataObject] = List.empty[RdfDataObject]

type env = LayersTest.DefaultTestEnvironmentWithoutSipi with Client with Scope

private def prepare: ZIO[AppServer.AppServerEnvironment, Throwable, AppServer] = for {
appServer <- AppServer.init()
_ <- appServer.start(requiresAdditionalRepositoryChecks = false, requiresIIIFService = false).orDie
_ <- prepareRepository(rdfDataObjects)
} yield appServer

def withResettedTriplestore =
TestAspect.before(prepareRepository(rdfDataObjects))

def e2eSpec: Spec[env, Any]

override def spec = (
e2eSpec
@@ TestAspect.beforeAll(prepare)
@@ TestAspect.sequential
).provideShared(testLayers, Client.default, Scope.default)

def sendGetRequestString(url: String): ZIO[env, String, String] =
for {
client <- ZIO.service[Client]
urlStr = s"http://localhost:3333$url"
urlFull <- ZIO.fromEither(URL.decode(urlStr)).mapError(_.getMessage)
response <- client.url(urlFull).get("/").mapError(_.getMessage)
data <- response.body.asString.mapError(_.getMessage)
} yield data

def sendGetRequest[B](url: String)(implicit dec: JsonDecoder[B]): ZIO[env, String, B] =
for {
response <- sendGetRequestString(url)
result <- ZIO.fromEither(response.fromJson[B])
} yield result

def sendPostRequestString(url: String, data: String): ZIO[env, String, String] =
for {
client <- ZIO.service[Client]
urlStr = s"http://localhost:3333$url"
urlFull <- ZIO.fromEither(URL.decode(urlStr)).mapError(_.getMessage)
body = Body.fromString(data)
header = Header.ContentType(MediaType.application.json)
response <- client.url(urlFull).addHeader(header).post("")(body).mapError(_.getMessage)
data <- response.body.asString.mapError(_.getMessage)
} yield data

def getToken(email: String, password: String): ZIO[env, String, String] =
for {
response <-
sendPostRequestString(
"/v2/authentication",
s"""|{
| "email": "$email",
| "password": "$password"
|}""".stripMargin,
)
result <- ZIO.fromEither(response.fromJson[Map[String, String]])
token <- ZIO.fromOption(result.get("token")).orElseFail("No token in response")
} yield token

}
@@ -0,0 +1,66 @@
/*
* Copyright © 2021 - 2024 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors.
* SPDX-License-Identifier: Apache-2.0
*/

package org.knora.webapi.e2e

import zio.json._
import zio.test._

import org.knora.webapi.E2EZSpec
import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject

object SampleE2ESpec extends E2EZSpec {

// add something to this list, if particular test data should be loaded
override def rdfDataObjects: List[RdfDataObject] = List.empty

case class VersionResponse(
buildCommit: String,
buildTime: String,
fuseki: String,
name: String,
pekkoHttp: String,
scala: String,
sipi: String,
webapi: String,
)
object VersionResponse {
implicit val decoder: JsonDecoder[VersionResponse] = DeriveJsonDecoder.gen[VersionResponse]
}

case class HealthResponse(name: String, severity: String, status: Boolean, message: String)
object HealthResponse {
implicit val decoder: JsonDecoder[HealthResponse] = DeriveJsonDecoder.gen[HealthResponse]
}

override def e2eSpec = suite("SampleE2ESpec")(
versionTest,
healthTest,
getTokenTest @@ withResettedTriplestore, // this is not actually needed, it just shows how to use it
)

val versionTest = test("check version endpoint") {
for {
response <- sendGetRequest[VersionResponse]("/version")
} yield assertTrue(
response.name == "version",
response.webapi.startsWith("v"),
response.scala.startsWith("2.13."),
)
}

val healthTest = test("check health endpoint") {
for {
response <- sendGetRequest[HealthResponse]("/health")
expected = HealthResponse("AppState", "non fatal", true, "Application is healthy")
} yield assertTrue(response == expected)
}

val getTokenTest = test("foo") {
for {
token <- getToken("root@example.com", "test")
} yield assertTrue(token.nonEmpty)
}
}
Expand Up @@ -136,7 +136,7 @@ final case class AppServer(

object AppServer {

private type AppServerEnvironment =
type AppServerEnvironment =
State & TriplestoreService & RepositoryUpdater & actor.ActorSystem & OntologyCache & SipiService & HttpServer & AppConfig

/**
Expand Down

0 comments on commit a9a7993

Please sign in to comment.