package main import "testing" func TestCheckersModelSelectAndMoveViaKeys(t *testing.T) { m := NewCheckersModel(0) m.cursor = CheckersPos{Row: 5, Col: 2} next, _ := m.Update(key("enter")) m = next.(CheckersModel) if m.isError { t.Fatalf("неожиданная ошибка выбора: %s", m.message) } if m.selected == nil { t.Fatalf("ожидался выбор шашки") } m.cursor = CheckersPos{Row: 4, Col: 1} next, _ = m.Update(key("enter")) m = next.(CheckersModel) if m.isError { t.Fatalf("неожиданная ошибка хода: %s", m.message) } if m.game.Board[4][1] == nil { t.Fatalf("шашка должна была переместиться") } if m.selected != nil { t.Errorf("выбор должен был сброситься после хода") } } func TestCheckersModelCursorMovement(t *testing.T) { m := NewCheckersModel(0) m.cursor = CheckersPos{Row: 4, Col: 4} next, _ := m.Update(key("up")) m = next.(CheckersModel) if m.cursor.Row != 3 { t.Errorf("курсор должен был сдвинуться вверх") } next, _ = m.Update(key("right")) m = next.(CheckersModel) if m.cursor.Col != 5 { t.Errorf("курсор должен был сдвинуться вправо") } } func TestCheckersModelEscClearsSelection(t *testing.T) { m := NewCheckersModel(0) m.cursor = CheckersPos{Row: 5, Col: 2} next, _ := m.Update(key("enter")) m = next.(CheckersModel) if m.selected == nil { t.Fatalf("ожидался выбор") } next, _ = m.Update(key("esc")) m = next.(CheckersModel) if m.selected != nil { t.Errorf("esc должен был сбросить выбор") } } func TestCheckersModelCannotSelectEmptySquare(t *testing.T) { m := NewCheckersModel(0) m.cursor = CheckersPos{Row: 3, Col: 2} next, _ := m.Update(key("enter")) m = next.(CheckersModel) if !m.isError { t.Fatalf("ожидалась ошибка выбора пустой клетки") } } func TestCheckersModelQReturnsToMenu(t *testing.T) { m := NewCheckersModel(0) next, _ := m.Update(key("q")) m = next.(CheckersModel) if !m.backToMenu { t.Fatalf("ожидался флаг backToMenu после 'q'") } if m.quitting { t.Fatalf("'q' не должен закрывать всё приложение") } } func TestCheckersModelNewGameAfterResult(t *testing.T) { m := NewCheckersModel(0) m.game.Result = &CheckersResult{Winner: CheckersWhite} next, _ := m.Update(key("n")) m = next.(CheckersModel) if m.game.Result != nil { t.Errorf("новая партия не должна была начаться с результатом") } } // TestCheckersModelFullAutoPlaythrough прогоняет TUI-модель от // начала до конца, где "человек" отыгрывает свои ходы через бота // (небольшая глубина — ради скорости), проверяя, что весь путь // через Update не паникует и партия завершается. func TestCheckersModelFullAutoPlaythrough(t *testing.T) { m := NewCheckersModel(0) m.bot = CheckersBot{Depth: 2} helperBot := CheckersBot{Depth: 2} const maxSteps = 400 for i := 0; i < maxSteps && m.game.Result == nil; i++ { if m.game.Turn != m.human { next, _ := m.Update(botMoveMsg{}) m = next.(CheckersModel) continue } mv, ok := helperBot.DecideMove(m.game) if !ok { break } m.cursor = mv.From next, _ := m.Update(key("enter")) m = next.(CheckersModel) if m.isError { t.Fatalf("неожиданная ошибка выбора хода человеком: %s", m.message) } m.cursor = mv.To next, _ = m.Update(key("enter")) m = next.(CheckersModel) if m.isError { t.Fatalf("неожиданная ошибка хода человеком: %s", m.message) } } if m.game.Result == nil { t.Fatalf("партия через TUI не завершилась за %d шагов", maxSteps) } }