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

57 lines
1.6 KiB
Python

"""@file
@brief Fakes of the ports for tests that must not start a browser or sleep.
"""
from collections.abc import Callable
class FakeGame:
"""@brief Records what the bot does and answers reads from dictionaries."""
def __init__(
self,
texts: dict[str, str] | None = None,
attributes: dict[tuple[str, str], str] | None = None,
on_click: Callable[[str], None] | None = None,
) -> None:
self.texts: dict[str, str] = texts or {}
self.attributes: dict[tuple[str, str], str] = attributes or {}
self.on_click = on_click
self.opened: list[str] = []
self.waited: list[str] = []
self.clicked: list[str] = []
self.close_calls = 0
def open_page(self, url: str) -> None:
self.opened.append(url)
def wait_for_element(self, element_id: str) -> None:
self.waited.append(element_id)
def click_element(self, element_id: str) -> None:
self.clicked.append(element_id)
if self.on_click is not None:
self.on_click(element_id)
def read_text(self, element_id: str) -> str:
return self.texts[element_id]
def read_attribute(self, element_id: str, attribute: str) -> str:
return self.attributes.get((element_id, attribute), "")
def close(self) -> None:
self.close_calls += 1
class FakeClock:
"""@brief A clock that moves forward by a fixed step on every reading."""
def __init__(self, step: float = 1.0) -> None:
self.now = 0.0
self.step = step
def monotonic(self) -> float:
reading = self.now
self.now += self.step
return reading