Navegador

navegador / tests / test_completions.py
Blame History Raw 236 lines
1
"""Tests for shell completions — module API and CLI command."""
2
3
from pathlib import Path
4
5
import pytest
6
from click.testing import CliRunner
7
8
from navegador.cli.commands import main
9
from navegador.completions import (
10
SUPPORTED_SHELLS,
11
get_eval_line,
12
get_rc_path,
13
install_completion,
14
)
15
16
# ── get_eval_line ─────────────────────────────────────────────────────────────
17
18
19
class TestGetEvalLine:
20
def test_bash_contains_bash_source(self):
21
line = get_eval_line("bash")
22
assert "bash_source" in line
23
assert "navegador" in line
24
25
def test_zsh_contains_zsh_source(self):
26
line = get_eval_line("zsh")
27
assert "zsh_source" in line
28
assert "navegador" in line
29
30
def test_fish_contains_fish_source(self):
31
line = get_eval_line("fish")
32
assert "fish_source" in line
33
assert "navegador" in line
34
35
def test_bash_uses_eval(self):
36
line = get_eval_line("bash")
37
assert line.startswith("eval ")
38
39
def test_zsh_uses_eval(self):
40
line = get_eval_line("zsh")
41
assert line.startswith("eval ")
42
43
def test_fish_uses_pipe_source(self):
44
line = get_eval_line("fish")
45
assert "| source" in line
46
47
def test_invalid_shell_raises_value_error(self):
48
with pytest.raises(ValueError, match="Unsupported shell"):
49
get_eval_line("powershell")
50
51
def test_all_supported_shells_return_string(self):
52
for shell in SUPPORTED_SHELLS:
53
assert isinstance(get_eval_line(shell), str)
54
55
56
# ── get_rc_path ───────────────────────────────────────────────────────────────
57
58
59
class TestGetRcPath:
60
def test_bash_returns_bashrc(self):
61
assert get_rc_path("bash") == "~/.bashrc"
62
63
def test_zsh_returns_zshrc(self):
64
assert get_rc_path("zsh") == "~/.zshrc"
65
66
def test_fish_returns_config_fish(self):
67
assert "config.fish" in get_rc_path("fish")
68
69
def test_invalid_shell_raises_value_error(self):
70
with pytest.raises(ValueError, match="Unsupported shell"):
71
get_rc_path("ksh")
72
73
def test_all_supported_shells_return_string(self):
74
for shell in SUPPORTED_SHELLS:
75
assert isinstance(get_rc_path(shell), str)
76
77
78
# ── install_completion ────────────────────────────────────────────────────────
79
80
81
class TestInstallCompletion:
82
def test_creates_file_with_eval_line(self, tmp_path):
83
rc = tmp_path / ".bashrc"
84
result = install_completion("bash", rc_path=str(rc))
85
assert result.exists()
86
content = rc.read_text()
87
assert "bash_source" in content
88
assert "navegador" in content
89
90
def test_creates_parent_dirs_for_fish(self, tmp_path):
91
rc = tmp_path / ".config" / "fish" / "config.fish"
92
result = install_completion("fish", rc_path=str(rc))
93
assert result.exists()
94
assert rc.parent.is_dir()
95
96
def test_returns_path_object(self, tmp_path):
97
rc = tmp_path / ".zshrc"
98
result = install_completion("zsh", rc_path=str(rc))
99
assert isinstance(result, Path)
100
101
def test_idempotent_does_not_duplicate(self, tmp_path):
102
rc = tmp_path / ".bashrc"
103
install_completion("bash", rc_path=str(rc))
104
install_completion("bash", rc_path=str(rc))
105
content = rc.read_text()
106
# The eval line should appear exactly once
107
line = "eval \"$(_NAVEGADOR_COMPLETE=bash_source navegador)\""
108
assert content.count(line) == 1
109
110
def test_appends_to_existing_file(self, tmp_path):
111
rc = tmp_path / ".zshrc"
112
rc.write_text("# existing content\nexport FOO=bar\n")
113
install_completion("zsh", rc_path=str(rc))
114
content = rc.read_text()
115
assert "existing content" in content
116
assert "zsh_source" in content
117
118
def test_invalid_shell_raises_value_error(self, tmp_path):
119
with pytest.raises(ValueError, match="Unsupported shell"):
120
install_completion("tcsh", rc_path=str(tmp_path / ".tcshrc"))
121
122
def test_zsh_eval_line_in_file(self, tmp_path):
123
rc = tmp_path / ".zshrc"
124
install_completion("zsh", rc_path=str(rc))
125
assert "zsh_source" in rc.read_text()
126
127
def test_fish_source_line_in_file(self, tmp_path):
128
rc = tmp_path / "config.fish"
129
install_completion("fish", rc_path=str(rc))
130
assert "fish_source" in rc.read_text()
131
assert "| source" in rc.read_text()
132
133
134
# ── CLI: navegador completions <shell> ────────────────────────────────────────
135
136
137
class TestCompletionsCommand:
138
# Basic output
139
140
def test_bash_outputs_eval_line(self):
141
runner = CliRunner()
142
result = runner.invoke(main, ["completions", "bash"])
143
assert result.exit_code == 0
144
assert "bash_source" in result.output
145
146
def test_zsh_outputs_eval_line(self):
147
runner = CliRunner()
148
result = runner.invoke(main, ["completions", "zsh"])
149
assert result.exit_code == 0
150
assert "zsh_source" in result.output
151
152
def test_fish_outputs_source_line(self):
153
runner = CliRunner()
154
result = runner.invoke(main, ["completions", "fish"])
155
assert result.exit_code == 0
156
assert "fish_source" in result.output
157
158
def test_output_mentions_rc_file(self):
159
runner = CliRunner()
160
result = runner.invoke(main, ["completions", "bash"])
161
assert result.exit_code == 0
162
assert ".bashrc" in result.output
163
164
def test_output_mentions_install_hint(self):
165
runner = CliRunner()
166
result = runner.invoke(main, ["completions", "zsh"])
167
assert result.exit_code == 0
168
assert "--install" in result.output
169
170
# Invalid shell
171
172
def test_invalid_shell_exits_nonzero(self):
173
runner = CliRunner()
174
result = runner.invoke(main, ["completions", "powershell"])
175
assert result.exit_code != 0
176
177
def test_invalid_shell_shows_error(self):
178
runner = CliRunner()
179
result = runner.invoke(main, ["completions", "powershell"])
180
assert result.exit_code != 0
181
# Click's Choice type reports the invalid value
182
assert "powershell" in result.output or "invalid" in result.output.lower()
183
184
# --install flag
185
186
def test_install_bash_creates_file(self):
187
runner = CliRunner()
188
with runner.isolated_filesystem() as tmp:
189
rc = str(Path(tmp) / ".bashrc")
190
result = runner.invoke(main, ["completions", "bash", "--install", "--rc-path", rc])
191
assert result.exit_code == 0
192
assert Path(rc).exists()
193
assert "bash_source" in Path(rc).read_text()
194
195
def test_install_zsh_creates_file(self):
196
runner = CliRunner()
197
with runner.isolated_filesystem() as tmp:
198
rc = str(Path(tmp) / ".zshrc")
199
result = runner.invoke(main, ["completions", "zsh", "--install", "--rc-path", rc])
200
assert result.exit_code == 0
201
assert Path(rc).exists()
202
203
def test_install_fish_creates_file(self):
204
runner = CliRunner()
205
with runner.isolated_filesystem() as tmp:
206
rc = str(Path(tmp) / "config.fish")
207
result = runner.invoke(main, ["completions", "fish", "--install", "--rc-path", rc])
208
assert result.exit_code == 0
209
assert Path(rc).exists()
210
211
def test_install_shows_success_message(self):
212
runner = CliRunner()
213
with runner.isolated_filesystem() as tmp:
214
rc = str(Path(tmp) / ".bashrc")
215
result = runner.invoke(main, ["completions", "bash", "--install", "--rc-path", rc])
216
assert result.exit_code == 0
217
assert "installed" in result.output.lower() or "Completion" in result.output
218
219
def test_install_shows_restart_hint(self):
220
runner = CliRunner()
221
with runner.isolated_filesystem() as tmp:
222
rc = str(Path(tmp) / ".zshrc")
223
result = runner.invoke(main, ["completions", "zsh", "--install", "--rc-path", rc])
224
assert result.exit_code == 0
225
assert "source" in result.output or "restart" in result.output.lower()
226
227
def test_install_idempotent_via_cli(self):
228
runner = CliRunner()
229
with runner.isolated_filesystem() as tmp:
230
rc = str(Path(tmp) / ".zshrc")
231
runner.invoke(main, ["completions", "zsh", "--install", "--rc-path", rc])
232
runner.invoke(main, ["completions", "zsh", "--install", "--rc-path", rc])
233
content = Path(rc).read_text()
234
line = 'eval "$(_NAVEGADOR_COMPLETE=zsh_source navegador)"'
235
assert content.count(line) == 1
236

Keyboard Shortcuts

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