Navegador

navegador / tests / test_editor.py
Source Blame History 218 lines
8b12743… lmata 1 """Tests for editor integration — EditorIntegration class and CLI command."""
8b12743… lmata 2
8b12743… lmata 3 import json
8b12743… lmata 4 from pathlib import Path
8b12743… lmata 5 from unittest.mock import MagicMock, patch
8b12743… lmata 6
8b12743… lmata 7 import pytest
8b12743… lmata 8 from click.testing import CliRunner
8b12743… lmata 9
8b12743… lmata 10 from navegador.cli.commands import main
8b12743… lmata 11 from navegador.editor import SUPPORTED_EDITORS, EditorIntegration
8b12743… lmata 12
8b12743… lmata 13 # ── EditorIntegration unit tests ──────────────────────────────────────────────
8b12743… lmata 14
8b12743… lmata 15
8b12743… lmata 16 class TestEditorIntegration:
8b12743… lmata 17 def setup_method(self):
8b12743… lmata 18 self.integration = EditorIntegration(db=".navegador/graph.db")
8b12743… lmata 19
8b12743… lmata 20 # config_for
8b12743… lmata 21
8b12743… lmata 22 def test_config_for_claude_code(self):
8b12743… lmata 23 cfg = self.integration.config_for("claude-code")
8b12743… lmata 24 assert cfg["mcpServers"]["navegador"]["command"] == "navegador"
8b12743… lmata 25 assert cfg["mcpServers"]["navegador"]["args"] == ["mcp", "--db", ".navegador/graph.db"]
8b12743… lmata 26
8b12743… lmata 27 def test_config_for_cursor(self):
8b12743… lmata 28 cfg = self.integration.config_for("cursor")
8b12743… lmata 29 assert cfg["mcpServers"]["navegador"]["command"] == "navegador"
8b12743… lmata 30 assert cfg["mcpServers"]["navegador"]["args"] == ["mcp", "--db", ".navegador/graph.db"]
8b12743… lmata 31
8b12743… lmata 32 def test_config_for_codex(self):
8b12743… lmata 33 cfg = self.integration.config_for("codex")
8b12743… lmata 34 assert cfg["mcpServers"]["navegador"]["command"] == "navegador"
8b12743… lmata 35 assert cfg["mcpServers"]["navegador"]["args"] == ["mcp", "--db", ".navegador/graph.db"]
8b12743… lmata 36
8b12743… lmata 37 def test_config_for_windsurf(self):
8b12743… lmata 38 cfg = self.integration.config_for("windsurf")
8b12743… lmata 39 assert cfg["mcpServers"]["navegador"]["command"] == "navegador"
8b12743… lmata 40 assert cfg["mcpServers"]["navegador"]["args"] == ["mcp", "--db", ".navegador/graph.db"]
8b12743… lmata 41
8b12743… lmata 42 def test_config_for_invalid_editor_raises(self):
8b12743… lmata 43 with pytest.raises(ValueError, match="Unsupported editor"):
8b12743… lmata 44 self.integration.config_for("vscode")
8b12743… lmata 45
8b12743… lmata 46 # custom db path
8b12743… lmata 47
8b12743… lmata 48 def test_custom_db_path_reflected_in_config(self):
8b12743… lmata 49 integration = EditorIntegration(db="/custom/path/graph.db")
8b12743… lmata 50 cfg = integration.config_for("cursor")
8b12743… lmata 51 assert cfg["mcpServers"]["navegador"]["args"][2] == "/custom/path/graph.db"
8b12743… lmata 52
8b12743… lmata 53 # config_json
8b12743… lmata 54
8b12743… lmata 55 def test_config_json_is_valid_json(self):
8b12743… lmata 56 raw = self.integration.config_json("claude-code")
8b12743… lmata 57 parsed = json.loads(raw)
8b12743… lmata 58 assert "mcpServers" in parsed
8b12743… lmata 59
8b12743… lmata 60 def test_config_json_is_pretty_printed(self):
8b12743… lmata 61 raw = self.integration.config_json("cursor")
8b12743… lmata 62 assert "\n" in raw # indented
8b12743… lmata 63
8b12743… lmata 64 # config_path
8b12743… lmata 65
8b12743… lmata 66 def test_config_path_claude_code(self):
8b12743… lmata 67 assert self.integration.config_path("claude-code") == ".claude/mcp.json"
8b12743… lmata 68
8b12743… lmata 69 def test_config_path_cursor(self):
8b12743… lmata 70 assert self.integration.config_path("cursor") == ".cursor/mcp.json"
8b12743… lmata 71
8b12743… lmata 72 def test_config_path_codex(self):
8b12743… lmata 73 assert self.integration.config_path("codex") == ".codex/config.json"
8b12743… lmata 74
8b12743… lmata 75 def test_config_path_windsurf(self):
8b12743… lmata 76 assert self.integration.config_path("windsurf") == ".windsurf/mcp.json"
8b12743… lmata 77
8b12743… lmata 78 def test_config_path_invalid_editor_raises(self):
8b12743… lmata 79 with pytest.raises(ValueError, match="Unsupported editor"):
8b12743… lmata 80 self.integration.config_path("sublime")
8b12743… lmata 81
8b12743… lmata 82 # write_config
8b12743… lmata 83
8b12743… lmata 84 def test_write_config_creates_file(self, tmp_path):
8b12743… lmata 85 written = self.integration.write_config("claude-code", base_dir=str(tmp_path))
8b12743… lmata 86 assert written.exists()
8b12743… lmata 87 parsed = json.loads(written.read_text())
8b12743… lmata 88 assert "mcpServers" in parsed
8b12743… lmata 89
8b12743… lmata 90 def test_write_config_creates_parent_dirs(self, tmp_path):
8b12743… lmata 91 written = self.integration.write_config("windsurf", base_dir=str(tmp_path))
8b12743… lmata 92 assert (tmp_path / ".windsurf").is_dir()
8b12743… lmata 93 assert written.name == "mcp.json"
8b12743… lmata 94
8b12743… lmata 95 def test_write_config_returns_path_object(self, tmp_path):
8b12743… lmata 96 result = self.integration.write_config("cursor", base_dir=str(tmp_path))
8b12743… lmata 97 assert isinstance(result, Path)
8b12743… lmata 98
8b12743… lmata 99 def test_write_config_content_matches_config_json(self, tmp_path):
8b12743… lmata 100 written = self.integration.write_config("codex", base_dir=str(tmp_path))
8b12743… lmata 101 assert written.read_text() == self.integration.config_json("codex")
8b12743… lmata 102
8b12743… lmata 103 # all editors covered
8b12743… lmata 104
8b12743… lmata 105 def test_all_editors_supported(self):
8b12743… lmata 106 for ed in SUPPORTED_EDITORS:
8b12743… lmata 107 cfg = self.integration.config_for(ed)
8b12743… lmata 108 assert "mcpServers" in cfg
8b12743… lmata 109
8b12743… lmata 110
8b12743… lmata 111 # ── CLI tests ─────────────────────────────────────────────────────────────────
8b12743… lmata 112
8b12743… lmata 113
8b12743… lmata 114 class TestEditorSetupCommand:
8b12743… lmata 115 # Basic output
8b12743… lmata 116
8b12743… lmata 117 def test_claude_code_outputs_json(self):
8b12743… lmata 118 runner = CliRunner()
8b12743… lmata 119 result = runner.invoke(main, ["editor", "setup", "claude-code"])
8b12743… lmata 120 assert result.exit_code == 0
8b12743… lmata 121 parsed = json.loads(result.output)
8b12743… lmata 122 assert "mcpServers" in parsed
8b12743… lmata 123 assert parsed["mcpServers"]["navegador"]["command"] == "navegador"
8b12743… lmata 124
8b12743… lmata 125 def test_cursor_outputs_json(self):
8b12743… lmata 126 runner = CliRunner()
8b12743… lmata 127 result = runner.invoke(main, ["editor", "setup", "cursor"])
8b12743… lmata 128 assert result.exit_code == 0
8b12743… lmata 129 parsed = json.loads(result.output)
8b12743… lmata 130 assert "mcpServers" in parsed
8b12743… lmata 131
8b12743… lmata 132 def test_codex_outputs_json(self):
8b12743… lmata 133 runner = CliRunner()
8b12743… lmata 134 result = runner.invoke(main, ["editor", "setup", "codex"])
8b12743… lmata 135 assert result.exit_code == 0
8b12743… lmata 136 parsed = json.loads(result.output)
8b12743… lmata 137 assert "mcpServers" in parsed
8b12743… lmata 138
8b12743… lmata 139 def test_windsurf_outputs_json(self):
8b12743… lmata 140 runner = CliRunner()
8b12743… lmata 141 result = runner.invoke(main, ["editor", "setup", "windsurf"])
8b12743… lmata 142 assert result.exit_code == 0
8b12743… lmata 143 parsed = json.loads(result.output)
8b12743… lmata 144 assert "mcpServers" in parsed
8b12743… lmata 145
8b12743… lmata 146 # --db option
8b12743… lmata 147
8b12743… lmata 148 def test_custom_db_reflected_in_output(self):
8b12743… lmata 149 runner = CliRunner()
8b12743… lmata 150 result = runner.invoke(main, ["editor", "setup", "cursor", "--db", "/custom/graph.db"])
8b12743… lmata 151 assert result.exit_code == 0
8b12743… lmata 152 parsed = json.loads(result.output)
8b12743… lmata 153 assert parsed["mcpServers"]["navegador"]["args"][2] == "/custom/graph.db"
8b12743… lmata 154
8b12743… lmata 155 # 'all' generates for all editors
8b12743… lmata 156
8b12743… lmata 157 def test_all_generates_for_all_editors(self):
8b12743… lmata 158 runner = CliRunner()
8b12743… lmata 159 result = runner.invoke(main, ["editor", "setup", "all"])
8b12743… lmata 160 assert result.exit_code == 0
8b12743… lmata 161 # Each editor name should appear in the output header
8b12743… lmata 162 for ed in SUPPORTED_EDITORS:
8b12743… lmata 163 assert ed in result.output
8b12743… lmata 164
8b12743… lmata 165 def test_all_output_contains_multiple_json_blocks(self):
8b12743… lmata 166 runner = CliRunner()
8b12743… lmata 167 result = runner.invoke(main, ["editor", "setup", "all"])
8b12743… lmata 168 assert result.exit_code == 0
8b12743… lmata 169 # Count occurrences of "mcpServers" — one per editor
8b12743… lmata 170 assert result.output.count("mcpServers") == len(SUPPORTED_EDITORS)
8b12743… lmata 171
8b12743… lmata 172 # Invalid editor name
8b12743… lmata 173
8b12743… lmata 174 def test_invalid_editor_exits_nonzero(self):
8b12743… lmata 175 runner = CliRunner()
8b12743… lmata 176 result = runner.invoke(main, ["editor", "setup", "vscode"])
8b12743… lmata 177 assert result.exit_code != 0
8b12743… lmata 178
8b12743… lmata 179 def test_invalid_editor_shows_error(self):
8b12743… lmata 180 runner = CliRunner()
8b12743… lmata 181 result = runner.invoke(main, ["editor", "setup", "vim"])
8b12743… lmata 182 assert "vim" in result.output or "vim" in (result.exception or "")
8b12743… lmata 183
8b12743… lmata 184 # --write flag
8b12743… lmata 185
8b12743… lmata 186 def test_write_flag_creates_file(self):
8b12743… lmata 187 runner = CliRunner()
8b12743… lmata 188 with runner.isolated_filesystem():
8b12743… lmata 189 result = runner.invoke(main, ["editor", "setup", "claude-code", "--write"])
8b12743… lmata 190 assert result.exit_code == 0
8b12743… lmata 191 written = Path(".claude/mcp.json")
8b12743… lmata 192 assert written.exists()
8b12743… lmata 193 parsed = json.loads(written.read_text())
8b12743… lmata 194 assert "mcpServers" in parsed
8b12743… lmata 195
8b12743… lmata 196 def test_write_flag_cursor_creates_correct_file(self):
8b12743… lmata 197 runner = CliRunner()
8b12743… lmata 198 with runner.isolated_filesystem():
8b12743… lmata 199 result = runner.invoke(main, ["editor", "setup", "cursor", "--write"])
8b12743… lmata 200 assert result.exit_code == 0
8b12743… lmata 201 assert Path(".cursor/mcp.json").exists()
8b12743… lmata 202
8b12743… lmata 203 def test_write_flag_all_creates_all_files(self):
8b12743… lmata 204 runner = CliRunner()
8b12743… lmata 205 with runner.isolated_filesystem():
8b12743… lmata 206 result = runner.invoke(main, ["editor", "setup", "all", "--write"])
8b12743… lmata 207 assert result.exit_code == 0
8b12743… lmata 208 assert Path(".claude/mcp.json").exists()
8b12743… lmata 209 assert Path(".cursor/mcp.json").exists()
8b12743… lmata 210 assert Path(".codex/config.json").exists()
8b12743… lmata 211 assert Path(".windsurf/mcp.json").exists()
8b12743… lmata 212
8b12743… lmata 213 def test_write_flag_shows_written_path(self):
8b12743… lmata 214 runner = CliRunner()
8b12743… lmata 215 with runner.isolated_filesystem():
8b12743… lmata 216 result = runner.invoke(main, ["editor", "setup", "windsurf", "--write"])
8b12743… lmata 217 assert result.exit_code == 0
8b12743… lmata 218 assert "Written" in result.output or ".windsurf" in result.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