test: added tests coverage
Build & Test (NowChessSystems) TeamCity build failed

This commit is contained in:
shahdlala66
2026-04-08 08:26:06 +02:00
parent ef9bbcfe85
commit f6a6c8376a
3 changed files with 337 additions and 0 deletions
@@ -0,0 +1,108 @@
package de.nowchess.io.json
import de.nowchess.api.game.GameContext
import de.nowchess.api.board.{Piece, Square, File, Rank, Board, CastlingRights, Color, PieceType}
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
class JsonExporterMoveSuite extends AnyFunSuite with Matchers:
test("export initial position has empty moves") {
val context = GameContext.initial
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"moves\": []"))
}
test("export move using withMove applies it validly") {
val move = Move(Square(File.E, Rank.R2), Square(File.E, Rank.R4))
val context = GameContext.initial.withMove(move)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"e2\""))
assert(json.contains("\"e4\""))
}
test("export castling rights after kingside castling") {
val move = Move(Square(File.E, Rank.R1), Square(File.G, Rank.R1), MoveType.CastleKingside)
// Note: We can't apply kingside castling without proper board state, so test structure
val cr = CastlingRights(false, false, true, true)
val context = GameContext.initial.copy(castlingRights = cr)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"whiteKingSide\": false"))
assert(json.contains("\"blackKingSide\": true"))
}
test("export en passant square if set") {
val epSquare = Some(Square(File.E, Rank.R3))
val context = GameContext.initial.copy(enPassantSquare = epSquare)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"enPassantSquare\": \"e3\""))
}
test("export null en passant square") {
val context = GameContext.initial.copy(enPassantSquare = None)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"enPassantSquare\": null"))
}
test("export move JSON structure contains required fields") {
val move = Move(Square(File.D, Rank.R2), Square(File.D, Rank.R4))
val context = GameContext.initial.withMove(move)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"d2\""))
assert(json.contains("\"d4\""))
assert(json.contains("\"moves\""))
}
test("export complex board with custom pieces") {
val board = Board(Map(
Square(File.A, Rank.R1) -> Piece(Color.White, PieceType.Rook),
Square(File.E, Rank.R1) -> Piece(Color.White, PieceType.King),
Square(File.H, Rank.R1) -> Piece(Color.White, PieceType.Rook),
Square(File.A, Rank.R8) -> Piece(Color.Black, PieceType.Rook),
Square(File.E, Rank.R8) -> Piece(Color.Black, PieceType.King),
Square(File.H, Rank.R8) -> Piece(Color.Black, PieceType.Rook)
))
val context = GameContext.initial.copy(board = board)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"a1\""))
assert(json.contains("\"e1\""))
assert(json.contains("\"h1\""))
assert(json.contains("\"Rook\""))
}
test("export with no castling rights") {
val cr = CastlingRights(false, false, false, false)
val context = GameContext.initial.copy(castlingRights = cr)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"whiteKingSide\": false"))
assert(json.contains("\"whiteQueenSide\": false"))
assert(json.contains("\"blackKingSide\": false"))
assert(json.contains("\"blackQueenSide\": false"))
}
test("export with partial castling rights") {
val cr = CastlingRights(true, false, true, false)
val context = GameContext.initial.copy(castlingRights = cr)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"whiteKingSide\": true"))
assert(json.contains("\"whiteQueenSide\": false"))
}
test("export normal move type") {
val normalMove = Move(Square(File.C, Rank.R2), Square(File.C, Rank.R4), MoveType.Normal(false))
val context = GameContext.initial.withMove(normalMove)
val json = JsonExporter.exportGameContext(context)
assert(json.contains("\"c2\""))
assert(json.contains("\"c4\""))
}
@@ -0,0 +1,122 @@
package de.nowchess.io.json
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
class JsonModelExtraTestSuite extends AnyFunSuite with Matchers:
test("JsonMetadata with all fields") {
val meta = JsonMetadata(Some("Event"), Some(Map("a" -> "b")), Some("2026-04-08"), Some("1-0"))
assert(meta.event.contains("Event"))
assert(meta.players.exists(_.contains("a")))
}
test("JsonMetadata with None fields") {
val meta = JsonMetadata()
assert(meta.event.isEmpty)
assert(meta.players.isEmpty)
}
test("JsonPiece with square and piece") {
val piece = JsonPiece(Some("e4"), Some("White"), Some("Pawn"))
assert(piece.square.contains("e4"))
assert(piece.color.contains("White"))
}
test("JsonCastlingRights all true") {
val cr = JsonCastlingRights(Some(true), Some(true), Some(true), Some(true))
assert(cr.whiteKingSide.contains(true))
assert(cr.blackQueenSide.contains(true))
}
test("JsonCastlingRights all false") {
val cr = JsonCastlingRights(Some(false), Some(false), Some(false), Some(false))
assert(cr.whiteKingSide.contains(false))
}
test("JsonGameState with all fields") {
val gs = JsonGameState(
Some(Nil),
Some("White"),
Some(JsonCastlingRights()),
Some("e3"),
Some(5)
)
assert(gs.board.contains(Nil))
assert(gs.halfMoveClock.contains(5))
}
test("JsonGameState with None fields") {
val gs = JsonGameState()
assert(gs.board.isEmpty)
assert(gs.halfMoveClock.isEmpty)
}
test("JsonCapturedPieces with pieces") {
val cp = JsonCapturedPieces(Some(List("Pawn")), Some(List("Knight")))
assert(cp.byWhite.exists(_.contains("Pawn")))
assert(cp.byBlack.exists(_.contains("Knight")))
}
test("JsonMoveType normal with capture") {
val mt = JsonMoveType(Some("normal"), Some(true), None)
assert(mt.`type`.contains("normal"))
assert(mt.isCapture.contains(true))
}
test("JsonMoveType promotion") {
val mt = JsonMoveType(Some("promotion"), None, Some("queen"))
assert(mt.`type`.contains("promotion"))
assert(mt.promotionPiece.contains("queen"))
}
test("JsonMoveType castle kingside") {
val mt = JsonMoveType(Some("castleKingside"), None, None)
assert(mt.`type`.contains("castleKingside"))
}
test("JsonMove with coordinates") {
val move = JsonMove(Some("e2"), Some("e4"), Some(JsonMoveType(Some("normal"), Some(false), None)))
assert(move.from.contains("e2"))
assert(move.to.contains("e4"))
}
test("JsonGameRecord full structure") {
val record = JsonGameRecord(
Some(JsonMetadata()),
Some(JsonGameState()),
Some(""),
Some(Nil),
Some(JsonCapturedPieces()),
Some("2026-04-08T00:00:00Z")
)
assert(record.metadata.nonEmpty)
assert(record.timestamp.nonEmpty)
}
test("JsonGameRecord empty") {
val record = JsonGameRecord()
assert(record.metadata.isEmpty)
assert(record.moves.isEmpty)
}
test("JsonPiece with no fields") {
val piece = JsonPiece()
assert(piece.square.isEmpty)
assert(piece.color.isEmpty)
assert(piece.piece.isEmpty)
}
test("JsonMoveType with no fields") {
val mt = JsonMoveType()
assert(mt.`type`.isEmpty)
assert(mt.isCapture.isEmpty)
assert(mt.promotionPiece.isEmpty)
}
test("JsonMove with empty fields") {
val move = JsonMove()
assert(move.from.isEmpty)
assert(move.to.isEmpty)
assert(move.`type`.isEmpty)
}
@@ -0,0 +1,107 @@
package de.nowchess.io.json
import de.nowchess.api.game.GameContext
import de.nowchess.api.board.{Color, PieceType, Piece, Square, File, Rank}
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
class JsonParserMoveTypeSuite extends AnyFunSuite with Matchers:
test("parse all move type variations") {
val json = """{
"metadata": {"event": "Game", "result": "*"},
"gameState": {"turn": "White", "board": []},
"moves": [
{"from": "e2", "to": "e4", "type": {"type": "normal", "isCapture": false}},
{"from": "e1", "to": "g1", "type": {"type": "castleKingside"}},
{"from": "e1", "to": "c1", "type": {"type": "castleQueenside"}},
{"from": "e5", "to": "d4", "type": {"type": "enPassant"}},
{"from": "a7", "to": "a8", "type": {"type": "promotion", "promotionPiece": "queen"}},
{"from": "b7", "to": "b8", "type": {"type": "promotion", "promotionPiece": "rook"}},
{"from": "c7", "to": "c8", "type": {"type": "promotion", "promotionPiece": "bishop"}},
{"from": "d7", "to": "d8", "type": {"type": "promotion", "promotionPiece": "knight"}}
]
}"""
val result = JsonParser.importGameContext(json)
assert(result.isRight)
val ctx = result.toOption.get
assert(ctx.moves.length == 8)
assert(ctx.moves(0).moveType == MoveType.Normal(false))
assert(ctx.moves(1).moveType == MoveType.CastleKingside)
assert(ctx.moves(2).moveType == MoveType.CastleQueenside)
assert(ctx.moves(3).moveType == MoveType.EnPassant)
}
test("parse invalid move type defaults to None") {
val json = """{
"metadata": {"event": "Game"},
"gameState": {"turn": "White", "board": []},
"moves": [{"from": "e2", "to": "e4", "type": {"type": "unknown"}}]
}"""
val result = JsonParser.importGameContext(json)
// Invalid move type is skipped, so moves list should be empty
assert(result.isRight)
}
test("parse promotion with default piece") {
val json = """{
"metadata": {},
"gameState": {"turn": "White", "board": []},
"moves": [{"from": "a7", "to": "a8", "type": {"type": "promotion", "promotionPiece": "invalid"}}]
}"""
val result = JsonParser.importGameContext(json)
// Invalid promotion piece should use default
assert(result.isRight)
}
test("parse move with missing from/to skips it") {
val json = """{
"metadata": {},
"gameState": {"turn": "White", "board": []},
"moves": [{"from": "e2", "to": "invalid", "type": {"type": "normal"}}]
}"""
val result = JsonParser.importGameContext(json)
assert(result.isRight)
val ctx = result.toOption.get
// Invalid square should be filtered out
assert(ctx.moves.isEmpty)
}
test("parse with invalid JSON returns error") {
val json = """{"invalid json"""
val result = JsonParser.importGameContext(json)
assert(result.isLeft)
}
test("parse normal move with isCapture true") {
val json = """{
"metadata": {},
"gameState": {"turn": "White", "board": []},
"moves": [{"from": "e4", "to": "d5", "type": {"type": "normal", "isCapture": true}}]
}"""
val result = JsonParser.importGameContext(json)
assert(result.isRight)
val ctx = result.toOption.get
val move = ctx.moves.head
assert(move.moveType == MoveType.Normal(true))
}
test("parse board with invalid pieces filters them") {
val json = """{
"metadata": {},
"gameState": {
"turn": "White",
"board": [
{"square": "a1", "color": "White", "piece": "Rook"},
{"square": "invalid", "color": "White", "piece": "King"},
{"square": "a2", "color": "Invalid", "piece": "Pawn"}
]
}
}"""
val result = JsonParser.importGameContext(json)
assert(result.isRight)
val ctx = result.toOption.get
// Only valid piece should be in board
assert(ctx.board.pieces.size == 1)
}