diff --git a/build.sbt b/build.sbt index 553f6a26..e2199dad 100644 --- a/build.sbt +++ b/build.sbt @@ -66,7 +66,9 @@ lazy val app = (project in file("modules/app")) cirisCore, cirisHtt4s, log4Cats, - logback + logback, + weaver, + testContainers, ), Compile / run / fork := true ) diff --git a/modules/app/src/test/scala/Clients.scala b/modules/app/src/test/scala/Clients.scala new file mode 100644 index 00000000..21581c43 --- /dev/null +++ b/modules/app/src/test/scala/Clients.scala @@ -0,0 +1,33 @@ +package lila.search +package app +package test + +import cats.effect.{ IO, Resource } +import lila.search.spec.{ HealthService, SearchService } +import org.http4s.Uri +import org.http4s.ember.client.EmberClientBuilder +import smithy4s.http4s.* + +object Clients: + + def health(uri: Uri): Resource[IO, HealthService[IO]] = + EmberClientBuilder + .default[IO] + .build + .flatMap: client => + SimpleRestJsonBuilder + .apply(HealthService) + .client(client) + .uri(uri) + .resource + + def search(uri: Uri): Resource[IO, SearchService[IO]] = + EmberClientBuilder + .default[IO] + .build + .flatMap: client => + SimpleRestJsonBuilder + .apply(SearchService) + .client(client) + .uri(uri) + .resource diff --git a/modules/app/src/test/scala/ElasticSearchContainer.scala b/modules/app/src/test/scala/ElasticSearchContainer.scala new file mode 100644 index 00000000..bd4975b5 --- /dev/null +++ b/modules/app/src/test/scala/ElasticSearchContainer.scala @@ -0,0 +1,34 @@ +package lila.search +package app +package test + +import cats.effect.{ IO, Resource } +import com.dimafeng.testcontainers.GenericContainer +import org.testcontainers.containers.wait.strategy.Wait + +object ElasticSearchContainer: + + private val PORT = 9200 + private val container = + val env = Map( + "discovery.type" -> "single-node", + "http.cors.allow-origin" -> "/.*/", + "http.cors.enabled" -> "true", + "xpack.security.enabled" -> "false" + ) + val start = IO( + GenericContainer( + "elasticsearch:7.10.1", + exposedPorts = Seq(PORT), + waitStrategy = Wait.forListeningPort(), + env = env + ) + ) + .flatTap(cont => IO(cont.start())) + Resource.make(start)(cont => IO(cont.stop())) + + def parseConfig(container: GenericContainer): ElasticConfig = + ElasticConfig(s"http://${container.host}:${container.mappedPort(PORT)}") + + def start: Resource[IO, ElasticConfig] = + container.map(parseConfig) diff --git a/modules/app/src/test/scala/IntegrationSuite.scala b/modules/app/src/test/scala/IntegrationSuite.scala new file mode 100644 index 00000000..7946e4f3 --- /dev/null +++ b/modules/app/src/test/scala/IntegrationSuite.scala @@ -0,0 +1,40 @@ +package lila.search +package app +package test + +import cats.effect.{ IO, Resource } +import com.comcast.ip4s.* +import lila.search.spec.{ ElasticStatus, HealthCheckOutput } +import org.http4s.Uri +import org.typelevel.log4cats.Logger +import org.typelevel.log4cats.noop.NoOpLogger +import weaver.* + +object IntegrationSuite extends IOSuite: + + given Logger[IO] = NoOpLogger[IO] + + private val uri = Uri.unsafeFromString("http://localhost:9999") + + override type Res = AppResources + // start our server + override def sharedResource: Resource[IO, Res] = + for + elastic <- ElasticSearchContainer.start + config = testAppConfig(elastic) + res <- AppResources.instance(config) + _ <- SearchApp(res, config).run() + yield res + + def testAppConfig(elastic: ElasticConfig) = AppConfig( + server = + HttpServerConfig(ip"0.0.0.0", port"9999", apiLogger = false, shutdownTimeout = 30, enableDocs = false), + elastic = elastic + ) + + test("health check should return healthy"): + Clients + .health(uri) + .use: + _.healthCheck() + .map(expect.same(_, HealthCheckOutput(ElasticStatus.green))) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 53e1c53a..27983db6 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -13,7 +13,7 @@ object Dependencies { } def http4s(artifact: String) = "org.http4s" %% s"http4s-$artifact" % V.http4s - def smithy4s(artifact: String): ModuleID = "com.disneystreaming.smithy4s" %% s"smithy4s-$artifact" % smithy4sVersion + def smithy4s(artifact: String) = "com.disneystreaming.smithy4s" %% s"smithy4s-$artifact" % smithy4sVersion val catsCore = "org.typelevel" %% "cats-core" % "2.12.0" val catsEffect = "org.typelevel" %% "cats-effect" % V.catsEffect @@ -45,7 +45,7 @@ object Dependencies { val ducktape = "io.github.arainko" %% "ducktape" % "0.2.2" - val testContainers = "com.dimafeng" %% "testcontainers-scala-postgresql" % "0.41.3" % Test + val testContainers = "com.dimafeng" %% "testcontainers-scala-core" % "0.41.3" % Test val weaver = "com.disneystreaming" %% "weaver-cats" % "0.8.4" % Test val weaverScalaCheck = "com.disneystreaming" %% "weaver-scalacheck" % "0.8.4" % Test val catsEffectTestKit = "org.typelevel" %% "cats-effect-testkit" % V.catsEffect % Test