go_games_collection/oneohone_tui_test.go
2026-07-04 13:51:04 +03:00

118 lines
3.7 KiB
Go

package main
import "testing"
func TestOneOhOneModelDealsCorrectPlayerCount(t *testing.T) {
for n := 2; n <= 6; n++ {
m := NewOneOhOneModel(n)
if len(m.game.Players) != n {
t.Errorf("ожидалось %d игроков, получено %d", n, len(m.game.Players))
}
}
}
func TestOneOhOneModelClampsPlayerCount(t *testing.T) {
m := NewOneOhOneModel(1)
if len(m.game.Players) != 2 {
t.Errorf("ожидалось ограничение снизу до 2, получено %d", len(m.game.Players))
}
m = NewOneOhOneModel(10)
if len(m.game.Players) != 6 {
t.Errorf("ожидалось ограничение сверху до 6, получено %d", len(m.game.Players))
}
}
func TestOneOhOneModelPlayCardViaKeys(t *testing.T) {
m := NewOneOhOneModel(2)
m.game.Discard = []Card{c(Nine, Clubs)}
m.game.Players[m.humanIdx].Hand = []Card{c(Ten, Clubs)}
m.game.CurrentPlayerIdx = m.humanIdx
m.game.Phase = OneOhOnePhasePlay
m.cursor = 0
next, _ := m.Update(key("enter"))
m = next.(OneOhOneModel)
if m.isError {
t.Fatalf("неожиданная ошибка: %s", m.message)
}
}
func TestOneOhOneModelDrawViaKeys(t *testing.T) {
m := NewOneOhOneModel(2)
m.game.Discard = []Card{c(Nine, Clubs)}
m.game.Players[m.humanIdx].Hand = []Card{c(Ten, Hearts)} // не подходит
m.game.Stock = []Card{c(Two, Diamonds)}
m.game.CurrentPlayerIdx = m.humanIdx
m.game.Phase = OneOhOnePhasePlay
next, _ := m.Update(key("d"))
m = next.(OneOhOneModel)
if m.isError {
t.Fatalf("неожиданная ошибка: %s", m.message)
}
if len(m.game.Players[m.humanIdx].Hand) != 2 {
t.Fatalf("рука должна была вырасти на 1 карту, получено %d карт", len(m.game.Players[m.humanIdx].Hand))
}
}
func TestOneOhOneModelQReturnsToMenu(t *testing.T) {
m := NewOneOhOneModel(2)
next, _ := m.Update(key("q"))
m = next.(OneOhOneModel)
if !m.backToMenu {
t.Fatalf("ожидался флаг backToMenu после 'q'")
}
if m.quitting {
t.Fatalf("'q' не должен закрывать всё приложение")
}
}
// TestOneOhOneModelFullAutoPlaythrough прогоняет TUI-модель от
// начала до конца матча, где "человек" отыгрывает свои ходы через
// реальные нажатия клавиш (используя ту же логику, что и бот).
func TestOneOhOneModelFullAutoPlaythrough(t *testing.T) {
for n := 2; n <= 4; n++ {
m := NewOneOhOneModel(n)
const maxRounds = 100
round := 0
for ; round < maxRounds; round++ {
const maxSteps = 6000
steps := 0
for m.game.Phase != OneOhOnePhaseRoundOver && steps < maxSteps {
steps++
if m.game.CurrentPlayerIdx != m.humanIdx {
next, _ := m.Update(botMoveMsg{})
m = next.(OneOhOneModel)
continue
}
if card, ok := m.bot.DecideAction(m.game); ok {
for i, hc := range m.currentHand() {
if hc == card {
m.cursor = i
break
}
}
next, _ := m.Update(key("enter"))
m = next.(OneOhOneModel)
} else {
next, _ := m.Update(key("d"))
m = next.(OneOhOneModel)
}
}
if steps >= maxSteps {
t.Fatalf("игроков %d, раунд %d: раунд через TUI не завершился за %d шагов", n, round, maxSteps)
}
if m.game.Result == nil {
t.Fatalf("игроков %d, раунд %d: раунд завершился без результата", n, round)
}
if m.game.Result.MatchOver {
break
}
next, _ := m.Update(key("n"))
m = next.(OneOhOneModel)
}
if round >= maxRounds {
t.Fatalf("игроков %d: матч не завершился за %d раундов", n, maxRounds)
}
}
}