import pytest from tiny_computer_agent import Element, FakeScreen, Observation def test_element_center_is_the_middle_of_the_box(): assert Element("Save", x=320, y=120, width=80, height=24).center == (360, 132) def test_element_center_falls_back_to_corner_without_size(): assert Element("dot", x=5, y=7).center == (5, 7) def test_element_rejects_empty_label(): with pytest.raises(ValueError, match="non-empty"): Element(" ") def test_element_rejects_negative_geometry(): with pytest.raises(ValueError, match="non-negative"): Element("Save", x=-5) def test_fake_screen_advances_then_holds_the_last_frame(): screen = FakeScreen([(Element("A"),), (Element("B"),)]) assert [e.label for f in range(4) for e in screen.capture().elements] == ["A", "B", "B", "B"] assert screen.captures == 4 def test_find_prefers_exact_match_over_substring(): observation = Observation(elements=( Element("Save as"), Element("Save"), Element("Save all"), )) assert observation.find("Save").label == "Save" # exact wins assert observation.find("save as").label == "Save as" # case-insensitive assert observation.find("ave a").label == "Save as" # substring fallback assert observation.find("Quit") is None def test_summary_lists_elements_and_truncates(): observation = Observation( index=2, elements=tuple(Element(f"button {i}") for i in range(5)), text=" Untitled\n document ", ) summary = observation.summary(max_elements=3) assert "step 2" in summary assert "Untitled document" in summary # whitespace collapsed assert "button 0" in summary assert "and 2 more" in summary def test_summary_admits_when_there_is_no_index(): assert "no element index" in Observation().summary()