test(core): add GameEngineLoadGameTest for loadGame/exportGame

Add 3 focused tests for GameEngine load/export functionality:
- loadGame with PgnParser validates PGN parsing and undo/redo state
- loadGame with FenParser validates position loading without move replay
- exportGame with PgnExporter validates PGN output

Fix: PgnParser now extends GameContextImport trait for consistency with FenParser.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-05 15:22:04 +02:00
parent e88f502ffc
commit 17fa13c82a
2 changed files with 45 additions and 1 deletions
@@ -0,0 +1,43 @@
package de.nowchess.chess.engine
import scala.collection.mutable
import de.nowchess.api.board.{Board, Color}
import de.nowchess.api.game.GameContext
import de.nowchess.chess.observer.{Observer, GameEvent, PgnLoadedEvent}
import de.nowchess.io.pgn.PgnParser
import de.nowchess.io.fen.FenParser
import de.nowchess.io.pgn.PgnExporter
import de.nowchess.io.fen.FenExporter
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
class GameEngineLoadGameTest extends AnyFunSuite with Matchers:
test("loadGame with PgnParser: loads valid PGN and enables undo/redo"):
val engine = new GameEngine()
val pgn = "[Event \"Test\"]\n\n1. e4 e5\n"
val result = engine.loadGame(PgnParser, pgn)
result shouldBe Right(())
engine.context.moves.size shouldBe 2
engine.canUndo shouldBe true
test("loadGame with FenParser: loads position without replaying moves"):
val engine = new GameEngine()
val fen = "8/4P3/4k3/8/8/8/8/8 w - - 0 1"
val result = engine.loadGame(FenParser, fen)
result shouldBe Right(())
engine.context.moves.isEmpty shouldBe true
engine.canUndo shouldBe false
test("exportGame with PgnExporter: exports current game as PGN"):
val engine = new GameEngine()
engine.processUserInput("e2e4")
engine.processUserInput("e7e5")
val pgn = engine.exportGame(PgnExporter)
pgn.contains("e4") shouldBe true
pgn.contains("e5") shouldBe true
private class MockObserver extends Observer:
val events = mutable.ListBuffer[GameEvent]()
override def onGameEvent(event: GameEvent): Unit =
events += event
@@ -3,6 +3,7 @@ package de.nowchess.io.pgn
import de.nowchess.api.board.* import de.nowchess.api.board.*
import de.nowchess.api.move.{Move, MoveType, PromotionPiece} import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
import de.nowchess.api.game.{GameContext, HistoryMove} import de.nowchess.api.game.{GameContext, HistoryMove}
import de.nowchess.io.GameContextImport
import de.nowchess.rules.sets.DefaultRules import de.nowchess.rules.sets.DefaultRules
/** A parsed PGN game containing headers and the resolved move list. */ /** A parsed PGN game containing headers and the resolved move list. */
@@ -11,7 +12,7 @@ case class PgnGame(
moves: List[HistoryMove] moves: List[HistoryMove]
) )
object PgnParser: object PgnParser extends GameContextImport:
/** Strictly validate a PGN text. /** Strictly validate a PGN text.
* Returns Right(PgnGame) if every move token is a legal move in the evolving position. * Returns Right(PgnGame) if every move token is a legal move in the evolving position.