import pytest from tiny_computer_agent import ( Action, Element, Observation, Policy, PolicyViolation, ) FRAME = Observation(elements=(Element("Terminal"), Element("Save"))) def test_allows_an_ordinary_click(): Policy().check(Action("click", label="Save"), FRAME) def test_refuses_a_denied_key_chord(): with pytest.raises(PolicyViolation, match="deny list"): Policy().check(Action("key", keys="ctrl+alt+t")) @pytest.mark.parametrize("text", ["sudo apt install foo", "rm -rf /", "my password is hunter2"]) def test_refuses_denied_text(text): with pytest.raises(PolicyViolation, match="deny list"): Policy().check(Action("type", text=text)) def test_refuses_clicking_a_denied_widget(): with pytest.raises(PolicyViolation, match="Terminal"): Policy().check(Action("click", label="Terminal"), FRAME) def test_deny_label_is_case_insensitive(): with pytest.raises(PolicyViolation): Policy().check(Action("click", label="terminal"), FRAME) def test_kill_switch_is_off_until_the_file_exists(tmp_path): marker = tmp_path / "STOP" policy = Policy(kill_switch_path=str(marker)) assert policy.should_stop() is False marker.write_text("stop") assert policy.should_stop() is True def test_no_kill_switch_path_means_never_stops(): assert Policy().should_stop() is False def test_rejects_a_useless_budget(): with pytest.raises(ValueError, match="step_budget"): Policy(step_budget=0) def test_deny_lists_are_configurable(): lax = Policy(deny_text_patterns=(), deny_labels=(), deny_keys=()) lax.check(Action("type", text="sudo rm -rf /")) lax.check(Action("click", label="Terminal"), FRAME)