feat: add IoResource and Square key serializer/deserializer tests
Build & Test (NowChessSystems) TeamCity build failed
Build & Test (NowChessSystems) TeamCity build failed
This commit is contained in:
+5
-1
@@ -36,7 +36,11 @@ val coverageExclusions = listOf(
|
||||
"**/core/src/main/scala/de/nowchess/chess/registry/GameEntry.scala",
|
||||
"**/core/src/main/scala/de/nowchess/chess/registry/GameRegistryImpl.scala",
|
||||
// GameResource — REST integration layer with @Inject var fields; mocking dependencies for unit tests is infeasible with Quarkus DI; integration tests would require @QuarkusTest which Scoverage doesn't instrument
|
||||
"**/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala"
|
||||
"**/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala",
|
||||
// IoResource — same rationale as GameResource; @QuarkusTest not instrumented by Scoverage
|
||||
"**/io/src/main/scala/de/nowchess/io/service/resource/IoResource.scala",
|
||||
// JacksonConfig — Quarkus lifecycle hook, no testable logic beyond ObjectMapper registration
|
||||
"**/io/src/main/scala/de/nowchess/io/service/config/JacksonConfig.scala",
|
||||
)
|
||||
|
||||
// Converts a Sonar-style glob to a scoverage regex (matched against full source path).
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package de.nowchess.io.json
|
||||
|
||||
import com.fasterxml.jackson.core.`type`.TypeReference
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import com.fasterxml.jackson.module.scala.DefaultScalaModule
|
||||
import de.nowchess.api.board.{File, Rank, Square}
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class SquareKeyDeserializerTest extends AnyFunSuite with Matchers:
|
||||
|
||||
private def mapper: ObjectMapper =
|
||||
val m = new ObjectMapper()
|
||||
val mod = new SimpleModule()
|
||||
mod.addKeyDeserializer(classOf[Square], new SquareKeyDeserializer())
|
||||
m.registerModule(DefaultScalaModule)
|
||||
m.registerModule(mod)
|
||||
m
|
||||
|
||||
private def readMap(json: String): Map[Square, Int] =
|
||||
mapper.readValue(json, new TypeReference[Map[Square, Int]] {})
|
||||
|
||||
test("deserializes valid algebraic key") {
|
||||
val result = readMap("""{"e4":1}""")
|
||||
result(Square(File.E, Rank.R4)) shouldBe 1
|
||||
}
|
||||
|
||||
test("deserializes a1 corner") {
|
||||
val result = readMap("""{"a1":1}""")
|
||||
result(Square(File.A, Rank.R1)) shouldBe 1
|
||||
}
|
||||
|
||||
test("deserializes h8 corner") {
|
||||
val result = readMap("""{"h8":1}""")
|
||||
result(Square(File.H, Rank.R8)) shouldBe 1
|
||||
}
|
||||
|
||||
test("deserializes multiple squares") {
|
||||
val result = readMap("""{"a1":1,"h8":2,"e4":3}""")
|
||||
result(Square(File.A, Rank.R1)) shouldBe 1
|
||||
result(Square(File.H, Rank.R8)) shouldBe 2
|
||||
result(Square(File.E, Rank.R4)) shouldBe 3
|
||||
}
|
||||
|
||||
test("deserializeKey returns null for invalid square") {
|
||||
new SquareKeyDeserializer().deserializeKey("invalid", null) shouldBe null
|
||||
}
|
||||
|
||||
test("deserializeKey returns null for wrong-length key") {
|
||||
new SquareKeyDeserializer().deserializeKey("e44", null) shouldBe null
|
||||
}
|
||||
|
||||
test("deserializeKey returns null for bad file") {
|
||||
new SquareKeyDeserializer().deserializeKey("z4", null) shouldBe null
|
||||
}
|
||||
|
||||
test("deserializeKey returns null for bad rank") {
|
||||
new SquareKeyDeserializer().deserializeKey("e9", null) shouldBe null
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package de.nowchess.io.json
|
||||
|
||||
import com.fasterxml.jackson.core.`type`.TypeReference
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import com.fasterxml.jackson.module.scala.DefaultScalaModule
|
||||
import de.nowchess.api.board.{File, Rank, Square}
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class SquareKeySerializerTest extends AnyFunSuite with Matchers:
|
||||
|
||||
private def mapper: ObjectMapper =
|
||||
val m = new ObjectMapper()
|
||||
val mod = new SimpleModule()
|
||||
mod.addKeySerializer(classOf[Square], new SquareKeySerializer())
|
||||
m.registerModule(DefaultScalaModule)
|
||||
m.registerModule(mod)
|
||||
m
|
||||
|
||||
test("serializes square as algebraic notation") {
|
||||
val json = mapper.writeValueAsString(Map(Square(File.E, Rank.R4) -> 1))
|
||||
json should include("\"e4\"")
|
||||
}
|
||||
|
||||
test("serializes a1 corner") {
|
||||
val json = mapper.writeValueAsString(Map(Square(File.A, Rank.R1) -> 1))
|
||||
json should include("\"a1\"")
|
||||
}
|
||||
|
||||
test("serializes h8 corner") {
|
||||
val json = mapper.writeValueAsString(Map(Square(File.H, Rank.R8) -> 1))
|
||||
json should include("\"h8\"")
|
||||
}
|
||||
|
||||
test("round-trips with SquareKeyDeserializer") {
|
||||
val rt = {
|
||||
val m = new ObjectMapper()
|
||||
val mod = new SimpleModule()
|
||||
mod.addKeySerializer(classOf[Square], new SquareKeySerializer())
|
||||
mod.addKeyDeserializer(classOf[Square], new SquareKeyDeserializer())
|
||||
m.registerModule(DefaultScalaModule)
|
||||
m.registerModule(mod)
|
||||
m
|
||||
}
|
||||
val original = Map(Square(File.D, Rank.R5) -> 99)
|
||||
val json = rt.writeValueAsString(original)
|
||||
val result = rt.readValue(json, new TypeReference[Map[Square, Int]] {})
|
||||
result shouldBe original
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package de.nowchess.io.service.resource
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import com.fasterxml.jackson.module.scala.DefaultScalaModule
|
||||
import de.nowchess.api.board.Square
|
||||
import de.nowchess.api.game.GameContext
|
||||
import de.nowchess.io.json.{SquareKeyDeserializer, SquareKeySerializer}
|
||||
import io.quarkus.test.junit.QuarkusTest
|
||||
import io.restassured.RestAssured
|
||||
import io.restassured.http.ContentType
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
// scalafix:off
|
||||
@QuarkusTest
|
||||
class IoResourceTest:
|
||||
|
||||
private lazy val testMapper: ObjectMapper =
|
||||
val m = new ObjectMapper()
|
||||
val mod = new SimpleModule()
|
||||
mod.addKeySerializer(classOf[Square], new SquareKeySerializer())
|
||||
mod.addKeyDeserializer(classOf[Square], new SquareKeyDeserializer())
|
||||
m.registerModule(new DefaultScalaModule())
|
||||
m.registerModule(mod)
|
||||
m
|
||||
|
||||
private def contextJson(ctx: GameContext): String = testMapper.writeValueAsString(ctx)
|
||||
|
||||
@Test
|
||||
def importFenReturns200(): Unit =
|
||||
val resp = RestAssured.`given`()
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""{"fen":"rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1"}""")
|
||||
.post("/io/import/fen")
|
||||
assertEquals(200, resp.statusCode())
|
||||
|
||||
@Test
|
||||
def importFenInvalidReturns400(): Unit =
|
||||
val resp = RestAssured.`given`()
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""{"fen":"not-a-fen"}""")
|
||||
.post("/io/import/fen")
|
||||
assertEquals(400, resp.statusCode())
|
||||
|
||||
@Test
|
||||
def importPgnReturns200(): Unit =
|
||||
val resp = RestAssured.`given`()
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""{"pgn":"1. e4 e5"}""")
|
||||
.post("/io/import/pgn")
|
||||
assertEquals(200, resp.statusCode())
|
||||
|
||||
@Test
|
||||
def importPgnInvalidReturns400(): Unit =
|
||||
val resp = RestAssured.`given`()
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""{"pgn":"not valid pgn !!!###"}""")
|
||||
.post("/io/import/pgn")
|
||||
assertEquals(400, resp.statusCode())
|
||||
|
||||
@Test
|
||||
def exportFenReturns200WithFen(): Unit =
|
||||
val resp = RestAssured.`given`()
|
||||
.contentType(ContentType.JSON)
|
||||
.body(contextJson(GameContext.initial))
|
||||
.post("/io/export/fen")
|
||||
assertEquals(200, resp.statusCode())
|
||||
assertTrue(resp.getBody.asString().contains("rnbqkbnr"))
|
||||
|
||||
@Test
|
||||
def exportPgnReturns200(): Unit =
|
||||
val resp = RestAssured.`given`()
|
||||
.contentType(ContentType.JSON)
|
||||
.body(contextJson(GameContext.initial))
|
||||
.post("/io/export/pgn")
|
||||
assertEquals(200, resp.statusCode())
|
||||
// scalafix:on
|
||||
Reference in New Issue
Block a user