package main import ( "fmt" "strings" "testing" "time" ) func TestCorpseStarchModelRequisitionViaKey(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() next, _ := m.Update(key("1")) m = next.(CorpseStarchModel) if m.game.Starch != 1 { t.Fatalf("ожидался запас 1 после нажатия [1], получено %v", m.game.Starch) } } func TestCorpseStarchModelDefendActionAppearsDuringIncursion(t *testing.T) { m := NewCorpseStarchModel() before := len(m.buildActions(m.game.LastTick)) m.game.ChaosIncursionUntil = m.game.LastTick.Add(1) after := m.buildActions(m.game.LastTick) if len(after) != before+1 { t.Fatalf("ожидалось на одно действие больше во время вторжения, было %d, стало %d", before, len(after)) } if after[len(after)-1].Label != Tf("corpsestarch.action.defend", 0) { t.Errorf("последнее действие должно быть 'отбиваться', получено: %q", after[len(after)-1].Label) } } func TestCorpseStarchModelDefendActionIncrementsCounterViaKey(t *testing.T) { m := NewCorpseStarchModel() m.game.ChaosIncursionUntil = time.Now().Add(time.Hour) actions := m.buildActions(time.Now()) defendKey := fmt.Sprintf("%d", len(actions)) next, _ := m.Update(key(defendKey)) m = next.(CorpseStarchModel) if m.game.ChaosDefendClicks != 1 { t.Errorf("ожидался счётчик защиты 1 после нажатия, получено %d", m.game.ChaosDefendClicks) } } func TestCorpseStarchModelWarpBreachVisibleInView(t *testing.T) { m := NewCorpseStarchModel() m.game.Starch = 1000 m.game.ServitorCounts[0] = 10 m.game.DipChainsword(m.game.LastTick, 0.95) m.game.DipChainsword(m.game.LastTick, 0.95) m.game.DipChainsword(m.game.LastTick, 0.95) view := m.View() if !strings.Contains(view, T("corpsestarch.log.warp_breach")) { t.Errorf("экран должен был показать сообщение о варп-выбросе в журнале") } if !strings.Contains(view, "ВТОРЖЕНИЕ ХАОСА") { t.Errorf("экран должен был показать баннер активного вторжения") } if m.game.ServitorCounts[0] != 5 { t.Errorf("сервиторы должны были уполовиниться, получено %d", m.game.ServitorCounts[0]) } } func TestCorpseStarchModelActionsExpandAsUnlocked(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() if len(m.buildActions(time.Now())) != 1 { t.Fatalf("в начале должно быть только 1 действие (реквизиция)") } m.game.TotalEarned = corpseStarchUnlockServitors if len(m.buildActions(time.Now())) != 2 { t.Fatalf("после открытия сервиторов должно быть 2 действия") } m.game.TotalEarned = corpseStarchUnlockMissions actions := m.buildActions(time.Now()) if len(actions) != 8 { t.Fatalf("ожидалось 8 действий при полностью открытых (кроме 3 тира) разделах, получено %d", len(actions)) } } func TestCorpseStarchModelBuyServitorViaKey(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() m.game.TotalEarned = corpseStarchUnlockServitors m.game.Starch = 100 next, _ := m.Update(key("2")) m = next.(CorpseStarchModel) if m.game.ServitorCounts[0] != 1 { t.Fatalf("ожидалась покупка сервочерпа, получено count=%d", m.game.ServitorCounts[0]) } } func TestCorpseStarchModelTickAccruesIncome(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() m.game.ServitorCounts[0] = 10 past := m.game.LastTick.Add(2 * time.Second) next, _ := m.Update(corpseStarchTickMsg{At: past}) m = next.(CorpseStarchModel) if m.game.Starch != 10 { t.Errorf("ожидался запас 10 после тика на 2 секунды при 5/сек, получено %v", m.game.Starch) } } func TestCorpseStarchModelResetRequestShowsConfirmation(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() next, _ := m.Update(key("N")) m = next.(CorpseStarchModel) if !m.confirmingReset { t.Fatalf("ожидался запрос подтверждения после нажатия N") } } func TestCorpseStarchModelResetCancelKeepsProgress(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() m.game.Starch = 500 m.game.TotalEarned = 500 next, _ := m.Update(key("N")) m = next.(CorpseStarchModel) next, _ = m.Update(key("n")) m = next.(CorpseStarchModel) if m.confirmingReset { t.Errorf("запрос подтверждения должен был закрыться после отмены") } if m.game.Starch != 500 { t.Errorf("прогресс не должен был сброситься при отмене, получено Starch=%v", m.game.Starch) } } func TestCorpseStarchModelResetConfirmWipesProgress(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() m.game.Starch = 500 m.game.TotalEarned = 500 next, _ := m.Update(key("N")) m = next.(CorpseStarchModel) next, _ = m.Update(key("y")) m = next.(CorpseStarchModel) if m.confirmingReset { t.Errorf("запрос подтверждения должен был закрыться после подтверждения") } if m.game.Starch != 0 || m.game.TotalEarned != 0 { t.Errorf("прогресс должен был сброситься, получено Starch=%v TotalEarned=%v", m.game.Starch, m.game.TotalEarned) } } func TestCorpseStarchModelResetActionsIgnoredWhileConfirming(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() starchBefore := m.game.Starch next, _ := m.Update(key("N")) m = next.(CorpseStarchModel) // нажатие "1" (реквизиция) не должно срабатывать, пока ждём подтверждения next, _ = m.Update(key("1")) m = next.(CorpseStarchModel) if m.game.Starch != starchBefore { t.Errorf("обычные действия не должны выполняться во время запроса подтверждения") } } func TestCorpseStarchModelQReturnsToMenu(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() next, _ := m.Update(key("q")) m = next.(CorpseStarchModel) if !m.backToMenu { t.Fatalf("ожидался флаг backToMenu после 'q'") } if m.quitting { t.Fatalf("'q' не должен закрывать всё приложение") } } func TestCorpseStarchModelMissionFlowViaKeys(t *testing.T) { withTempConfigDir(t) m := NewCorpseStarchModel() m.game.TotalEarned = corpseStarchUnlockMissions m.game.Starch = 0 actions := m.buildActions(time.Now()) missionActionIdx := -1 for i, a := range actions { if a.Label == Tf("corpsestarch.action.start_mission", T("corpsestarch.mission.vermin"), formatDuration(corpseStarchMissionDefs[0].Duration)) { missionActionIdx = i break } } if missionActionIdx == -1 { t.Fatalf("не нашли действие запуска первой миссии среди %d действий", len(actions)) } next, _ := m.Update(key(string(rune('1' + missionActionIdx)))) m = next.(CorpseStarchModel) if m.game.ActiveMission == nil { t.Fatalf("миссия должна была начаться") } finished := m.game.ActiveMission.StartedAt.Add(corpseStarchMissionDefs[0].Duration + time.Second) if m.game.MissionRemaining(finished) != 0 { t.Fatalf("миссия должна была завершиться к этому моменту") } collectActions := m.buildActions(finished) collectIdx := -1 for i, a := range collectActions { if a.Label == T("corpsestarch.action.collect_mission") { collectIdx = i break } } if collectIdx == -1 { t.Fatalf("не нашли действие сбора награды") } collectActions[collectIdx].Handle(&m, finished) if m.game.ActiveMission != nil { t.Errorf("миссия должна была завершиться после сбора награды") } if m.game.MissionsDone != 1 { t.Errorf("счётчик завершённых миссий должен был увеличиться") } }