File size: 3,621 Bytes
e2f048d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""A change you cannot measure is a change you cannot verify."""

from tiny_computer_agent import ChangeVerifier, Delta, Element, Observation, diff, element_key


def frame(elements, text=""):
    return Observation(index=0, frame="frame", elements=tuple(elements), text=text)


def button(label, x=10, y=10, width=60, height=20, kind="button"):
    return Element(label, kind=kind, x=x, y=y, width=width, height=height)


def test_nothing_changed_is_measured_rather_than_guessed():
    picture = frame([button("Save", x=100)])
    delta = diff(picture, picture)

    assert delta.empty and not delta.changed
    assert delta.summary() == "no change"
    assert isinstance(delta, Delta)


def test_a_dialog_closing_is_a_removed_element_not_a_missing_string():
    """The whole point: verification without depending on the dialog's own words."""
    before = frame([button("Save As"), button("Cancel", x=80)])
    after = frame([button("Save As")])
    delta = diff(before, after)

    assert delta.closed and not delta.opened
    assert [e.label for e in delta.removed] == ["Cancel"]
    assert delta.matches(disappeared=["cancel"])
    assert not delta.matches(appeared=["cancel"])


def test_a_menu_opening_is_an_added_element():
    delta = diff(frame([button("File")]), frame([button("File"), button("Save As", y=60)]))

    assert delta.opened and not delta.closed
    assert [e.label for e in delta.added] == ["Save As"]
    assert delta.matches(appeared=["save as"])


def test_a_redraw_is_not_movement_and_a_real_move_is():
    still = diff(frame([button("Save", x=100)]), frame([button("Save", x=101)]))
    assert still.empty, "a one-pixel re-render is not a change"

    moved = diff(frame([button("Save", x=100)]), frame([button("Save", x=400)]))
    assert moved.moved and moved.settled, "nothing appeared or vanished: it moved"
    assert not moved.changed is False
    assert moved.to_dict()["moved"] == ["Save"]


def test_labels_are_compared_the_way_the_index_compares_them():
    """OCR drops spaces and models add punctuation, so identity is the alphanumeric core."""
    before = frame([button("Save As")])
    after = frame([button("SaveAs.")])
    delta = diff(before, after)

    assert delta.empty, "the same label, differently spelled, is the same element"
    assert element_key(button("Save As")) == element_key(button("SaveAs."))


def test_added_and_removed_are_told_apart_when_counts_differ():
    before = frame([button("Row 1"), button("Row 2")])
    after = frame([button("Row 2"), button("Row 3"), button("Row 4")])
    delta = diff(before, after)

    assert sorted(e.label for e in delta.added) == ["Row 3", "Row 4"]
    assert [e.label for e in delta.removed] == ["Row 1"]
    assert delta.summary().startswith("+2")


def test_the_verifier_remembers_the_previous_frame():
    verify = ChangeVerifier(disappeared=["Cancel"])
    with_cancel = frame([button("Save"), button("Cancel", x=200)])
    without_cancel = frame([button("Save")])

    assert verify(with_cancel) is False, "the first frame has nothing to compare against"
    assert verify(without_cancel) is True
    assert verify.last is not None and verify.last.closed, "Cancel is gone: the dialog closed"
    assert verify(without_cancel) is False, "and the comparison advances with the frame"
    assert verify.last is not None and verify.last.empty


def test_the_verifier_can_be_reset_between_episodes():
    verify = ChangeVerifier(appeared=["Saved"])
    verify(frame([button("Save")]))
    verify.reset()

    assert verify.previous is None and verify.last is None
    assert verify(frame([button("Saved")])) is False