Files
Tirsvad cb8e5edfbf Implement store strategy, five-minute run loop and command line entry point
StoreItem and choose_upgrade, get_store_items, buy_upgrade, get_cps,
run_bot with a Clock port, main and python -m cookie_clicker_bot. 74
offline tests. Reviewed in RC-012.

Task: MIL-003#1
Task: MIL-003#2
Task: MIL-003#3
Task: MIL-003#4
Task: MIL-003#5
Task: MIL-003#6
Closes #13
Closes #14
Closes #15
Closes #16
Closes #17
Closes #18
2026-10-28 16:37:21 +08:00

93 lines
2.9 KiB
Python

"""@file
@brief Tests of the command line entry point; no browser is started.
"""
from decimal import Decimal
from typing import cast
import pytest
from selenium.webdriver.remote.webdriver import WebDriver
from cookie_clicker_bot.application.ports.clock import Clock
from cookie_clicker_bot.application.ports.game_port import GamePort
from cookie_clicker_bot.constants import RUN_DURATION_SECONDS
from cookie_clicker_bot.presentation import cli
class FakeDriver:
def __init__(self) -> None:
self.quit_calls = 0
def quit(self) -> None:
self.quit_calls += 1
class Recorder:
"""Stands in for the use cases and the driver factory and records the calls."""
def __init__(self) -> None:
self.driver = FakeDriver()
self.headless: list[bool] = []
self.durations: list[float] = []
self.steps: list[str] = []
self.error: Exception | None = None
def driver_factory(self, headless: bool) -> WebDriver:
self.headless.append(headless)
return cast(WebDriver, self.driver)
def open_game(self, game: GamePort) -> None:
self.steps.append("open")
def select_language(self, game: GamePort) -> None:
self.steps.append("language")
def run_bot(self, game: GamePort, clock: Clock, duration: float) -> Decimal:
self.steps.append("run")
self.durations.append(duration)
if self.error is not None:
raise self.error
return Decimal("12.5")
@pytest.fixture
def recorder(monkeypatch: pytest.MonkeyPatch) -> Recorder:
rec = Recorder()
monkeypatch.setattr(cli, "open_game", rec.open_game)
monkeypatch.setattr(cli, "select_language", rec.select_language)
monkeypatch.setattr(cli, "run_bot", rec.run_bot)
return rec
def test_main_runs_the_steps_prints_the_result_and_closes(
recorder: Recorder, capsys: pytest.CaptureFixture[str]
) -> None:
assert cli.main([], recorder.driver_factory) == 0
assert recorder.steps == ["open", "language", "run"]
assert capsys.readouterr().out == "Result : 12.5\n"
assert recorder.driver.quit_calls == 1
def test_main_uses_the_default_duration_and_a_visible_browser(
recorder: Recorder,
) -> None:
cli.main([], recorder.driver_factory)
assert recorder.durations == [RUN_DURATION_SECONDS]
assert recorder.headless == [False]
def test_main_passes_the_headless_flag_and_duration(recorder: Recorder) -> None:
cli.main(["--headless", "--duration", "30"], recorder.driver_factory)
assert recorder.durations == [30.0]
assert recorder.headless == [True]
def test_main_closes_the_browser_when_the_run_fails(
recorder: Recorder, capsys: pytest.CaptureFixture[str]
) -> None:
recorder.error = RuntimeError("boom")
with pytest.raises(RuntimeError, match="boom"):
cli.main([], recorder.driver_factory)
assert recorder.driver.quit_calls == 1
assert capsys.readouterr().out == ""