test: added UI model tests
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
package de.nowchess.ui
|
||||
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
|
||||
|
||||
class MainTest extends AnyFunSuite with Matchers {
|
||||
|
||||
test("main should execute and quit immediately when fed 'quit'") {
|
||||
val in = new ByteArrayInputStream("quit\n".getBytes)
|
||||
val out = new ByteArrayOutputStream()
|
||||
|
||||
Console.withIn(in) {
|
||||
Console.withOut(out) {
|
||||
Main.main(Array.empty)
|
||||
}
|
||||
}
|
||||
|
||||
val output = out.toString
|
||||
output should include ("Game over. Goodbye!")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package de.nowchess.ui.terminal
|
||||
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
|
||||
import de.nowchess.chess.engine.GameEngine
|
||||
import de.nowchess.chess.observer.*
|
||||
import de.nowchess.api.board.{Board, Color}
|
||||
import de.nowchess.chess.logic.GameHistory
|
||||
|
||||
class TerminalUITest extends AnyFunSuite with Matchers {
|
||||
|
||||
test("TerminalUI should start, print initial state, and correctly respond to 'q'") {
|
||||
val in = new ByteArrayInputStream("q\n".getBytes)
|
||||
val out = new ByteArrayOutputStream()
|
||||
|
||||
val engine = new GameEngine()
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withIn(in) {
|
||||
Console.withOut(out) {
|
||||
ui.start()
|
||||
}
|
||||
}
|
||||
|
||||
val output = out.toString
|
||||
output should include("White's turn.")
|
||||
output should include("Game over. Goodbye!")
|
||||
}
|
||||
|
||||
test("TerminalUI should ignore empty inputs and re-print prompt") {
|
||||
val in = new ByteArrayInputStream("\nq\n".getBytes)
|
||||
val out = new ByteArrayOutputStream()
|
||||
|
||||
val engine = new GameEngine()
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withIn(in) {
|
||||
Console.withOut(out) {
|
||||
ui.start()
|
||||
}
|
||||
}
|
||||
|
||||
val output = out.toString
|
||||
// Prompt appears three times: Initial, after empty, on exit.
|
||||
output.split("White's turn.").length should be > 2
|
||||
}
|
||||
|
||||
test("TerminalUI printPrompt should include undo and redo hints if engine returns true") {
|
||||
val in = new ByteArrayInputStream("\nq\n".getBytes)
|
||||
val out = new ByteArrayOutputStream()
|
||||
|
||||
val engine = new GameEngine() {
|
||||
// Stub engine to force undo/redo to true
|
||||
override def canUndo: Boolean = true
|
||||
override def canRedo: Boolean = true
|
||||
}
|
||||
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withIn(in) {
|
||||
Console.withOut(out) {
|
||||
ui.start()
|
||||
}
|
||||
}
|
||||
|
||||
val output = out.toString
|
||||
output should include("[undo]")
|
||||
output should include("[redo]")
|
||||
}
|
||||
|
||||
test("TerminalUI onGameEvent should properly format InvalidMoveEvent") {
|
||||
val out = new ByteArrayOutputStream()
|
||||
val engine = new GameEngine()
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withOut(out) {
|
||||
ui.onGameEvent(InvalidMoveEvent(Board(Map.empty), GameHistory(), Color.Black, "Invalid move format"))
|
||||
}
|
||||
|
||||
out.toString should include("⚠️")
|
||||
out.toString should include("Invalid move format")
|
||||
}
|
||||
|
||||
test("TerminalUI onGameEvent should properly format CheckDetectedEvent") {
|
||||
val out = new ByteArrayOutputStream()
|
||||
val engine = new GameEngine()
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withOut(out) {
|
||||
ui.onGameEvent(CheckDetectedEvent(Board(Map.empty), GameHistory(), Color.Black))
|
||||
}
|
||||
|
||||
out.toString should include("Black is in check!")
|
||||
}
|
||||
|
||||
test("TerminalUI onGameEvent should properly format CheckmateEvent") {
|
||||
val out = new ByteArrayOutputStream()
|
||||
val engine = new GameEngine()
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withOut(out) {
|
||||
ui.onGameEvent(CheckmateEvent(Board(Map.empty), GameHistory(), Color.Black, Color.White))
|
||||
}
|
||||
|
||||
val ostr = out.toString
|
||||
ostr should include("Checkmate! White wins.")
|
||||
}
|
||||
|
||||
test("TerminalUI onGameEvent should properly format StalemateEvent") {
|
||||
val out = new ByteArrayOutputStream()
|
||||
val engine = new GameEngine()
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withOut(out) {
|
||||
ui.onGameEvent(StalemateEvent(Board(Map.empty), GameHistory(), Color.Black))
|
||||
}
|
||||
|
||||
out.toString should include("Stalemate! The game is a draw.")
|
||||
}
|
||||
|
||||
test("TerminalUI onGameEvent should properly format BoardResetEvent") {
|
||||
val out = new ByteArrayOutputStream()
|
||||
val engine = new GameEngine()
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withOut(out) {
|
||||
ui.onGameEvent(BoardResetEvent(Board(Map.empty), GameHistory(), Color.White))
|
||||
}
|
||||
|
||||
out.toString should include("Board has been reset to initial position.")
|
||||
}
|
||||
|
||||
test("TerminalUI onGameEvent should properly format MoveExecutedEvent with capturing piece") {
|
||||
val out = new ByteArrayOutputStream()
|
||||
val engine = new GameEngine()
|
||||
val ui = new TerminalUI(engine)
|
||||
|
||||
Console.withOut(out) {
|
||||
ui.onGameEvent(MoveExecutedEvent(Board(Map.empty), GameHistory(), Color.Black, "A1", "A8", Some("Knight(White)")))
|
||||
}
|
||||
|
||||
out.toString should include("Captured: Knight(White) on A8") // Depending on how piece/coord serialize
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user