PlanOpticon

planopticon / tests / test_companion.py
Source Blame History 162 lines
0981a08… noreply 1 """Tests for the CompanionREPL (without launching the loop)."""
0981a08… noreply 2
0981a08… noreply 3 from unittest.mock import patch
0981a08… noreply 4
0981a08… noreply 5 from video_processor.cli.companion import CompanionREPL
0981a08… noreply 6
0981a08… noreply 7
0981a08… noreply 8 class TestImport:
0981a08… noreply 9 def test_import(self):
0981a08… noreply 10 from video_processor.cli import companion # noqa: F401
0981a08… noreply 11
0981a08… noreply 12 assert hasattr(companion, "CompanionREPL")
0981a08… noreply 13
0981a08… noreply 14
0981a08… noreply 15 class TestConstructor:
0981a08… noreply 16 def test_defaults(self):
0981a08… noreply 17 repl = CompanionREPL()
0981a08… noreply 18 assert repl.kg is None
0981a08… noreply 19 assert repl.query_engine is None
0981a08… noreply 20 assert repl.agent is None
0981a08… noreply 21 assert repl.provider_manager is None
0981a08… noreply 22
0981a08… noreply 23 def test_explicit_args(self):
0981a08… noreply 24 repl = CompanionREPL(
0981a08… noreply 25 kb_paths=["/tmp/fake.db"],
0981a08… noreply 26 provider="openai",
0981a08… noreply 27 chat_model="gpt-4",
0981a08… noreply 28 )
0981a08… noreply 29 assert repl._kb_paths == ["/tmp/fake.db"]
0981a08… noreply 30 assert repl._provider_name == "openai"
0981a08… noreply 31 assert repl._chat_model == "gpt-4"
0981a08… noreply 32
0981a08… noreply 33
0981a08… noreply 34 class TestAutoDiscovery:
0981a08… noreply 35 @patch(
0981a08… noreply 36 "video_processor.integrators.graph_discovery.find_nearest_graph",
0981a08… noreply 37 return_value=None,
0981a08… noreply 38 )
0981a08… noreply 39 def test_no_graph_found(self, mock_find):
0981a08… noreply 40 repl = CompanionREPL()
0981a08… noreply 41 repl._discover()
0981a08… noreply 42 assert repl.query_engine is None
0981a08… noreply 43 assert repl.kg is None
0981a08… noreply 44 mock_find.assert_called_once()
0981a08… noreply 45
0981a08… noreply 46
0981a08… noreply 47 class TestHandleHelp:
0981a08… noreply 48 def test_handle_help(self):
0981a08… noreply 49 repl = CompanionREPL()
0981a08… noreply 50 output = repl.handle_input("/help")
0981a08… noreply 51 assert "Available commands" in output
0981a08… noreply 52 assert "/status" in output
0981a08… noreply 53 assert "/skills" in output
0981a08… noreply 54 assert "/entities" in output
0981a08… noreply 55 assert "/quit" in output
0981a08… noreply 56
0981a08… noreply 57
0981a08… noreply 58 class TestHandleStatus:
0981a08… noreply 59 def test_handle_status_no_kg(self):
0981a08… noreply 60 repl = CompanionREPL()
0981a08… noreply 61 output = repl.handle_input("/status")
0981a08… noreply 62 assert "Workspace status" in output
0981a08… noreply 63 assert "not loaded" in output
0981a08… noreply 64
0981a08… noreply 65
0981a08… noreply 66 class TestHandleSkills:
0981a08… noreply 67 def test_handle_skills(self):
0981a08… noreply 68 repl = CompanionREPL()
0981a08… noreply 69 output = repl.handle_input("/skills")
0981a08… noreply 70 # Either lists skills or says none registered
0981a08… noreply 71 assert "skills" in output.lower() or "No skills" in output
0981a08… noreply 72
0981a08… noreply 73
0981a08… noreply 74 class TestHandleQuit:
0981a08… noreply 75 def test_quit(self):
0981a08… noreply 76 repl = CompanionREPL()
0981a08… noreply 77 assert repl.handle_input("/quit") == "__QUIT__"
0981a08… noreply 78
0981a08… noreply 79 def test_exit(self):
0981a08… noreply 80 repl = CompanionREPL()
0981a08… noreply 81 assert repl.handle_input("/exit") == "__QUIT__"
0981a08… noreply 82
0981a08… noreply 83 def test_bare_quit(self):
0981a08… noreply 84 repl = CompanionREPL()
0981a08… noreply 85 assert repl.handle_input("quit") == "__QUIT__"
0981a08… noreply 86
0981a08… noreply 87 def test_bare_exit(self):
0981a08… noreply 88 repl = CompanionREPL()
0981a08… noreply 89 assert repl.handle_input("exit") == "__QUIT__"
0981a08… noreply 90
0981a08… noreply 91 def test_bare_bye(self):
0981a08… noreply 92 repl = CompanionREPL()
0981a08… noreply 93 assert repl.handle_input("bye") == "__QUIT__"
0981a08… noreply 94
0981a08… noreply 95 def test_bare_q(self):
0981a08… noreply 96 repl = CompanionREPL()
0981a08… noreply 97 assert repl.handle_input("q") == "__QUIT__"
0981a08… noreply 98
0981a08… noreply 99
0981a08… noreply 100 class TestHandleUnknownSlash:
0981a08… noreply 101 def test_unknown_command(self):
0981a08… noreply 102 repl = CompanionREPL()
0981a08… noreply 103 output = repl.handle_input("/foobar")
0981a08… noreply 104 assert "Unknown command" in output
0981a08… noreply 105 assert "/help" in output
0981a08… noreply 106
0981a08… noreply 107
0981a08… noreply 108 class TestHandleChatNoProvider:
0981a08… noreply 109 def test_chat_no_provider(self):
0981a08… noreply 110 repl = CompanionREPL()
0981a08… noreply 111 output = repl.handle_input("What is this project about?")
0981a08… noreply 112 assert "LLM provider" in output or "API" in output
0981a08… noreply 113 # Should not crash
0981a08… noreply 114
0981a08… noreply 115
0981a08… noreply 116 class TestHandleEntitiesNoKG:
0981a08… noreply 117 def test_entities_no_kg(self):
0981a08… noreply 118 repl = CompanionREPL()
0981a08… noreply 119 output = repl.handle_input("/entities")
0981a08… noreply 120 assert "No knowledge graph loaded" in output
0981a08… noreply 121
0981a08… noreply 122 def test_search_no_kg(self):
0981a08… noreply 123 repl = CompanionREPL()
0981a08… noreply 124 output = repl.handle_input("/search python")
0981a08… noreply 125 assert "No knowledge graph loaded" in output
0981a08… noreply 126
0981a08… noreply 127 def test_neighbors_no_kg(self):
0981a08… noreply 128 repl = CompanionREPL()
0981a08… noreply 129 output = repl.handle_input("/neighbors Alice")
0981a08… noreply 130 assert "No knowledge graph loaded" in output
0981a08… noreply 131
0981a08… noreply 132
0981a08… noreply 133 class TestProviderCommand:
0981a08… noreply 134 def test_provider_list(self):
0981a08… noreply 135 repl = CompanionREPL()
0981a08… noreply 136 output = repl.handle_input("/provider")
0981a08… noreply 137 assert "Available providers" in output
0981a08… noreply 138 assert "openai" in output
0981a08… noreply 139 assert "anthropic" in output
0981a08… noreply 140
0981a08… noreply 141 def test_provider_switch(self):
0981a08… noreply 142 repl = CompanionREPL()
0981a08… noreply 143 output = repl.handle_input("/provider openai")
0981a08… noreply 144 # Will fail to init without key, but shouldn't crash
0981a08… noreply 145 assert "openai" in output.lower()
0981a08… noreply 146
0981a08… noreply 147 def test_model_show(self):
0981a08… noreply 148 repl = CompanionREPL()
0981a08… noreply 149 output = repl.handle_input("/model")
0981a08… noreply 150 assert "Current model" in output
0981a08… noreply 151
0981a08… noreply 152 def test_model_switch(self):
0981a08… noreply 153 repl = CompanionREPL()
0981a08… noreply 154 output = repl.handle_input("/model gpt-4o")
0981a08… noreply 155 # Will fail without provider, but shouldn't crash
0981a08… noreply 156 assert "gpt-4o" in output
0981a08… noreply 157
0981a08… noreply 158 def test_help_includes_provider(self):
0981a08… noreply 159 repl = CompanionREPL()
0981a08… noreply 160 output = repl.handle_input("/help")
0981a08… noreply 161 assert "/provider" in output
0981a08… noreply 162 assert "/model" in output

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button