Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 47500e5

Browse files
committedDec 29, 2022
refactor! Refactor CLI tests
1 parent b31a692 commit 47500e5

File tree

8 files changed

+1305
-1266
lines changed

8 files changed

+1305
-1266
lines changed
 

‎tests/cli/test_cli.py

Lines changed: 3 additions & 1266 deletions
Large diffs are not rendered by default.

‎tests/cli/test_convert.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import io
2+
import json
3+
import pathlib
4+
import typing as t
5+
6+
import pytest
7+
8+
from tmuxp import cli
9+
10+
11+
@pytest.mark.parametrize(
12+
"cli_args",
13+
[
14+
(["convert", "."]),
15+
(["convert", ".tmuxp.yaml"]),
16+
(["convert", ".tmuxp.yaml", "-y"]),
17+
(["convert", ".tmuxp.yml"]),
18+
(["convert", ".tmuxp.yml", "-y"]),
19+
],
20+
)
21+
def test_convert(
22+
cli_args: t.List[str],
23+
tmp_path: pathlib.Path,
24+
monkeypatch: pytest.MonkeyPatch,
25+
) -> None:
26+
# create dummy tmuxp yaml so we don't get yelled at
27+
filename = cli_args[1]
28+
if filename == ".":
29+
filename = ".tmuxp.yaml"
30+
file_ext = filename.rsplit(".", 1)[-1]
31+
assert file_ext in ["yaml", "yml"], file_ext
32+
workspace_file_path = tmp_path / filename
33+
workspace_file_path.write_text("\nsession_name: hello\n", encoding="utf-8")
34+
oh_my_zsh_path = tmp_path / ".oh-my-zsh"
35+
oh_my_zsh_path.mkdir()
36+
monkeypatch.setenv("HOME", str(tmp_path))
37+
38+
monkeypatch.chdir(tmp_path)
39+
40+
# If autoconfirm (-y) no need to prompt y
41+
input_args = "y\ny\n" if "-y" not in cli_args else ""
42+
43+
monkeypatch.setattr("sys.stdin", io.StringIO(input_args))
44+
try:
45+
cli.cli(cli_args)
46+
except SystemExit:
47+
pass
48+
tmuxp_json = tmp_path / ".tmuxp.json"
49+
assert tmuxp_json.exists()
50+
assert tmuxp_json.open().read() == json.dumps({"session_name": "hello"}, indent=2)
51+
52+
53+
@pytest.mark.parametrize(
54+
"cli_args",
55+
[
56+
(["convert", "."]),
57+
(["convert", ".tmuxp.json"]),
58+
(["convert", ".tmuxp.json", "-y"]),
59+
],
60+
)
61+
def test_convert_json(
62+
cli_args: t.List[str],
63+
tmp_path: pathlib.Path,
64+
monkeypatch: pytest.MonkeyPatch,
65+
) -> None:
66+
# create dummy tmuxp yaml so we don't get yelled at
67+
json_config = tmp_path / ".tmuxp.json"
68+
json_config.write_text('{"session_name": "hello"}', encoding="utf-8")
69+
oh_my_zsh_path = tmp_path / ".oh-my-zsh"
70+
oh_my_zsh_path.mkdir()
71+
monkeypatch.setenv("HOME", str(tmp_path))
72+
73+
monkeypatch.chdir(tmp_path)
74+
75+
# If autoconfirm (-y) no need to prompt y
76+
input_args = "y\ny\n" if "-y" not in cli_args else ""
77+
78+
monkeypatch.setattr("sys.stdin", io.StringIO(input_args))
79+
try:
80+
cli.cli(cli_args)
81+
except SystemExit:
82+
pass
83+
84+
tmuxp_yaml = tmp_path / ".tmuxp.yaml"
85+
assert tmuxp_yaml.exists()
86+
assert tmuxp_yaml.open().read() == "session_name: hello\n"

‎tests/cli/test_debug_info.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import pathlib
2+
3+
import pytest
4+
5+
from tmuxp import cli
6+
7+
8+
def test_debug_info_cli(
9+
monkeypatch: pytest.MonkeyPatch,
10+
tmp_path: pathlib.Path,
11+
capsys: pytest.CaptureFixture,
12+
) -> None:
13+
monkeypatch.setenv("SHELL", "/bin/bash")
14+
15+
cli.cli(["debug-info"])
16+
cli_output = capsys.readouterr().out
17+
assert "environment" in cli_output
18+
assert "python version" in cli_output
19+
assert "system PATH" in cli_output
20+
assert "tmux version" in cli_output
21+
assert "libtmux version" in cli_output
22+
assert "tmuxp version" in cli_output
23+
assert "tmux path" in cli_output
24+
assert "tmuxp path" in cli_output
25+
assert "shell" in cli_output
26+
assert "tmux session" in cli_output
27+
assert "tmux windows" in cli_output
28+
assert "tmux panes" in cli_output
29+
assert "tmux global options" in cli_output
30+
assert "tmux window options" in cli_output

‎tests/cli/test_freeze.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import io
2+
import pathlib
3+
import typing as t
4+
5+
import pytest
6+
7+
from libtmux.server import Server
8+
from tmuxp import cli
9+
from tmuxp.config_reader import ConfigReader
10+
11+
12+
@pytest.mark.parametrize(
13+
"cli_args,inputs",
14+
[
15+
(["freeze", "myfrozensession"], ["y\n", "./la.yaml\n", "y\n"]),
16+
( # Exists
17+
["freeze", "myfrozensession"],
18+
["y\n", "./exists.yaml\n", "./la.yaml\n", "y\n"],
19+
),
20+
( # Imply current session if not entered
21+
["freeze"],
22+
["y\n", "./la.yaml\n", "y\n"],
23+
),
24+
(["freeze"], ["y\n", "./exists.yaml\n", "./la.yaml\n", "y\n"]), # Exists
25+
],
26+
)
27+
def test_freeze(
28+
server: "Server",
29+
cli_args: t.List[str],
30+
inputs: t.List[str],
31+
tmp_path: pathlib.Path,
32+
monkeypatch: pytest.MonkeyPatch,
33+
) -> None:
34+
monkeypatch.setenv("HOME", str(tmp_path))
35+
exists_yaml = tmp_path / "exists.yaml"
36+
exists_yaml.touch()
37+
38+
server.new_session(session_name="myfirstsession")
39+
server.new_session(session_name="myfrozensession")
40+
41+
# Assign an active pane to the session
42+
second_session = server.sessions[1]
43+
first_pane_on_second_session_id = second_session.windows[0].panes[0].pane_id
44+
assert first_pane_on_second_session_id
45+
monkeypatch.setenv("TMUX_PANE", first_pane_on_second_session_id)
46+
47+
monkeypatch.chdir(tmp_path)
48+
# Use tmux server (socket name) used in the test
49+
assert server.socket_name is not None
50+
cli_args = cli_args + ["-L", server.socket_name]
51+
52+
monkeypatch.setattr("sys.stdin", io.StringIO("".join(inputs)))
53+
try:
54+
cli.cli(cli_args)
55+
except SystemExit:
56+
pass
57+
58+
yaml_config_path = tmp_path / "la.yaml"
59+
assert yaml_config_path.exists()
60+
61+
yaml_config = yaml_config_path.open().read()
62+
frozen_config = ConfigReader._load(format="yaml", content=yaml_config)
63+
64+
assert frozen_config["session_name"] == "myfrozensession"
65+
66+
67+
@pytest.mark.parametrize(
68+
"cli_args,inputs",
69+
[
70+
( # Overwrite
71+
["freeze", "mysession", "--force"],
72+
["\n", "\n", "y\n", "./exists.yaml\n", "y\n"],
73+
),
74+
( # Imply current session if not entered
75+
["freeze", "--force"],
76+
["\n", "\n", "y\n", "./exists.yaml\n", "y\n"],
77+
),
78+
],
79+
)
80+
def test_freeze_overwrite(
81+
server: "Server",
82+
cli_args: t.List[str],
83+
inputs: t.List[str],
84+
tmp_path: pathlib.Path,
85+
monkeypatch: pytest.MonkeyPatch,
86+
) -> None:
87+
monkeypatch.setenv("HOME", str(tmp_path))
88+
exists_yaml = tmp_path / "exists.yaml"
89+
exists_yaml.touch()
90+
91+
server.new_session(session_name="mysession")
92+
93+
monkeypatch.chdir(tmp_path)
94+
# Use tmux server (socket name) used in the test
95+
assert server.socket_name is not None
96+
cli_args = cli_args + ["-L", server.socket_name]
97+
98+
monkeypatch.setattr("sys.stdin", io.StringIO("".join(inputs)))
99+
try:
100+
cli.cli(cli_args)
101+
except SystemExit:
102+
pass
103+
104+
yaml_config_path = tmp_path / "exists.yaml"
105+
assert yaml_config_path.exists()

‎tests/cli/test_import.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import io
2+
import pathlib
3+
import typing as t
4+
5+
import pytest
6+
7+
from tmuxp import cli
8+
9+
from ..fixtures import utils as test_utils
10+
11+
12+
@pytest.mark.parametrize("cli_args", [(["import"])])
13+
def test_import(
14+
cli_args: t.List[str],
15+
tmp_path: pathlib.Path,
16+
monkeypatch: pytest.MonkeyPatch,
17+
capsys: pytest.CaptureFixture,
18+
) -> None:
19+
cli.cli(cli_args)
20+
result = capsys.readouterr()
21+
assert "tmuxinator" in result.out
22+
assert "teamocil" in result.out
23+
24+
25+
@pytest.mark.parametrize(
26+
"cli_args,inputs",
27+
[
28+
(
29+
["import", "teamocil", "./.teamocil/config.yaml"],
30+
["\n", "y\n", "./la.yaml\n", "y\n"],
31+
),
32+
(
33+
["import", "teamocil", "./.teamocil/config.yaml"],
34+
["\n", "y\n", "./exists.yaml\n", "./la.yaml\n", "y\n"],
35+
),
36+
(
37+
["import", "teamocil", "config"],
38+
["\n", "y\n", "./exists.yaml\n", "./la.yaml\n", "y\n"],
39+
),
40+
],
41+
)
42+
def test_import_teamocil(
43+
cli_args: t.List[str],
44+
inputs: t.List[str],
45+
tmp_path: pathlib.Path,
46+
monkeypatch: pytest.MonkeyPatch,
47+
) -> None:
48+
teamocil_config = test_utils.read_workspace_file("import_teamocil/test4.yaml")
49+
50+
teamocil_path = tmp_path / ".teamocil"
51+
teamocil_path.mkdir()
52+
53+
teamocil_config_path = teamocil_path / "config.yaml"
54+
teamocil_config_path.write_text(teamocil_config, encoding="utf-8")
55+
56+
exists_yaml = tmp_path / "exists.yaml"
57+
exists_yaml.touch()
58+
59+
monkeypatch.setenv("HOME", str(tmp_path))
60+
61+
monkeypatch.chdir(tmp_path)
62+
monkeypatch.setattr("sys.stdin", io.StringIO("".join(inputs)))
63+
64+
try:
65+
cli.cli(cli_args)
66+
except SystemExit:
67+
pass
68+
69+
new_config_yaml = tmp_path / "la.yaml"
70+
assert new_config_yaml.exists()
71+
72+
73+
@pytest.mark.parametrize(
74+
"cli_args,inputs",
75+
[
76+
(
77+
["import", "tmuxinator", "./.tmuxinator/config.yaml"],
78+
["\n", "y\n", "./la.yaml\n", "y\n"],
79+
),
80+
(
81+
["import", "tmuxinator", "./.tmuxinator/config.yaml"],
82+
["\n", "y\n", "./exists.yaml\n", "./la.yaml\n", "y\n"],
83+
),
84+
(
85+
["import", "tmuxinator", "config"],
86+
["\n", "y\n", "./exists.yaml\n", "./la.yaml\n", "y\n"],
87+
),
88+
],
89+
)
90+
def test_import_tmuxinator(
91+
cli_args: t.List[str],
92+
inputs: t.List[str],
93+
tmp_path: pathlib.Path,
94+
monkeypatch: pytest.MonkeyPatch,
95+
) -> None:
96+
tmuxinator_config = test_utils.read_workspace_file("import_tmuxinator/test3.yaml")
97+
98+
tmuxinator_path = tmp_path / ".tmuxinator"
99+
tmuxinator_path.mkdir()
100+
101+
tmuxinator_config_path = tmuxinator_path / "config.yaml"
102+
tmuxinator_config_path.write_text(tmuxinator_config, encoding="utf-8")
103+
104+
exists_yaml = tmp_path / "exists.yaml"
105+
exists_yaml.touch()
106+
107+
monkeypatch.setenv("HOME", str(tmp_path))
108+
109+
monkeypatch.chdir(tmp_path)
110+
111+
monkeypatch.setattr("sys.stdin", io.StringIO("".join(inputs)))
112+
try:
113+
cli.cli(cli_args)
114+
except SystemExit:
115+
pass
116+
117+
new_config_yaml = tmp_path / "la.yaml"
118+
assert new_config_yaml.exists()

‎tests/cli/test_load.py

Lines changed: 630 additions & 0 deletions
Large diffs are not rendered by default.

‎tests/cli/test_ls.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import os
2+
import pathlib
3+
4+
import pytest
5+
6+
from tmuxp import cli
7+
8+
9+
def test_ls_cli(
10+
monkeypatch: pytest.MonkeyPatch,
11+
tmp_path: pathlib.Path,
12+
capsys: pytest.CaptureFixture,
13+
) -> None:
14+
monkeypatch.setenv("HOME", str(tmp_path))
15+
monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / ".config"))
16+
17+
filenames = [
18+
".git/",
19+
".gitignore/",
20+
"session_1.yaml",
21+
"session_2.yaml",
22+
"session_3.json",
23+
"session_4.txt",
24+
]
25+
26+
# should ignore:
27+
# - directories should be ignored
28+
# - extensions not covered in VALID_WORKSPACE_DIR_FILE_EXTENSIONS
29+
ignored_filenames = [".git/", ".gitignore/", "session_4.txt"]
30+
stems = [os.path.splitext(f)[0] for f in filenames if f not in ignored_filenames]
31+
32+
for filename in filenames:
33+
location = tmp_path / f".tmuxp/{filename}"
34+
if filename.endswith("/"):
35+
location.mkdir(parents=True)
36+
else:
37+
location.touch()
38+
39+
try:
40+
cli.cli(["ls"])
41+
except SystemExit:
42+
pass
43+
cli_output = capsys.readouterr().out
44+
45+
assert cli_output == "\n".join(stems) + "\n"

‎tests/cli/test_shell.py

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
import io
2+
import pathlib
3+
import subprocess
4+
import typing as t
5+
6+
import pytest
7+
8+
from libtmux.server import Server
9+
from libtmux.session import Session
10+
from tmuxp import cli, exc
11+
12+
13+
@pytest.mark.parametrize("cli_cmd", [["shell"], ["shell", "--pdb"]])
14+
@pytest.mark.parametrize(
15+
"cli_args,inputs,env,expected_output",
16+
[
17+
(
18+
["-L{SOCKET_NAME}", "-c", "print(str(server.socket_name))"],
19+
[],
20+
{},
21+
"{SERVER_SOCKET_NAME}",
22+
),
23+
(
24+
[
25+
"-L{SOCKET_NAME}",
26+
"{SESSION_NAME}",
27+
"-c",
28+
"print(session.name)",
29+
],
30+
[],
31+
{},
32+
"{SESSION_NAME}",
33+
),
34+
(
35+
[
36+
"-L{SOCKET_NAME}",
37+
"{SESSION_NAME}",
38+
"{WINDOW_NAME}",
39+
"-c",
40+
"print(server.has_session(session.name))",
41+
],
42+
[],
43+
{},
44+
"True",
45+
),
46+
(
47+
[
48+
"-L{SOCKET_NAME}",
49+
"{SESSION_NAME}",
50+
"{WINDOW_NAME}",
51+
"-c",
52+
"print(window.name)",
53+
],
54+
[],
55+
{},
56+
"{WINDOW_NAME}",
57+
),
58+
(
59+
[
60+
"-L{SOCKET_NAME}",
61+
"{SESSION_NAME}",
62+
"{WINDOW_NAME}",
63+
"-c",
64+
"print(pane.id)",
65+
],
66+
[],
67+
{},
68+
"{PANE_ID}",
69+
),
70+
(
71+
[
72+
"-L{SOCKET_NAME}",
73+
"-c",
74+
"print(pane.id)",
75+
],
76+
[],
77+
{"TMUX_PANE": "{PANE_ID}"},
78+
"{PANE_ID}",
79+
),
80+
],
81+
)
82+
def test_shell(
83+
cli_cmd: t.List[str],
84+
cli_args: t.List[str],
85+
inputs: t.List[t.Any],
86+
expected_output: str,
87+
env: t.Dict[str, str],
88+
server: "Server",
89+
session: Session,
90+
tmp_path: pathlib.Path,
91+
monkeypatch: pytest.MonkeyPatch,
92+
capsys: pytest.CaptureFixture,
93+
) -> None:
94+
monkeypatch.setenv("HOME", str(tmp_path))
95+
window_name = "my_window"
96+
window = session.new_window(window_name=window_name)
97+
window.split_window()
98+
99+
assert window.attached_pane is not None
100+
101+
template_ctx = dict(
102+
SOCKET_NAME=server.socket_name,
103+
SESSION_NAME=session.name,
104+
WINDOW_NAME=window_name,
105+
PANE_ID=window.attached_pane.id,
106+
SERVER_SOCKET_NAME=server.socket_name,
107+
)
108+
109+
cli_args = cli_cmd + [cli_arg.format(**template_ctx) for cli_arg in cli_args]
110+
111+
for k, v in env.items():
112+
monkeypatch.setenv(k, v.format(**template_ctx))
113+
114+
monkeypatch.chdir(tmp_path)
115+
116+
cli.cli(cli_args)
117+
result = capsys.readouterr()
118+
assert expected_output.format(**template_ctx) in result.out
119+
120+
121+
@pytest.mark.parametrize(
122+
"cli_cmd",
123+
[
124+
["shell"],
125+
["shell", "--pdb"],
126+
],
127+
)
128+
@pytest.mark.parametrize(
129+
"cli_args,inputs,env,template_ctx,exception,message",
130+
[
131+
(
132+
["-LDoesNotExist", "-c", "print(str(server.socket_name))"],
133+
[],
134+
{},
135+
{},
136+
subprocess.CalledProcessError,
137+
r".*DoesNotExist.*",
138+
),
139+
(
140+
[
141+
"-L{SOCKET_NAME}",
142+
"nonexistant_session",
143+
"-c",
144+
"print(str(server.socket_name))",
145+
],
146+
[],
147+
{},
148+
{"session_name": "nonexistant_session"},
149+
exc.TmuxpException,
150+
"Session not found: nonexistant_session",
151+
),
152+
(
153+
[
154+
"-L{SOCKET_NAME}",
155+
"{SESSION_NAME}",
156+
"nonexistant_window",
157+
"-c",
158+
"print(str(server.socket_name))",
159+
],
160+
[],
161+
{},
162+
{"window_name": "nonexistant_window"},
163+
exc.TmuxpException,
164+
"Window not found: {WINDOW_NAME}",
165+
),
166+
],
167+
)
168+
def test_shell_target_missing(
169+
cli_cmd: t.List[str],
170+
cli_args: t.List[str],
171+
inputs: t.List[t.Any],
172+
env: t.Dict[t.Any, t.Any],
173+
template_ctx: t.Dict[str, str],
174+
exception: t.Union[
175+
t.Type[exc.TmuxpException], t.Type[subprocess.CalledProcessError]
176+
],
177+
message: str,
178+
socket_name: str,
179+
server: "Server",
180+
session: Session,
181+
tmp_path: pathlib.Path,
182+
monkeypatch: pytest.MonkeyPatch,
183+
capsys: pytest.CaptureFixture,
184+
) -> None:
185+
monkeypatch.setenv("HOME", str(tmp_path))
186+
window_name = "my_window"
187+
window = session.new_window(window_name=window_name)
188+
window.split_window()
189+
190+
assert server.socket_name is not None
191+
assert session.name is not None
192+
193+
template_ctx.update(
194+
dict(
195+
SOCKET_NAME=server.socket_name,
196+
SESSION_NAME=session.name,
197+
WINDOW_NAME=template_ctx.get("window_name", window_name),
198+
)
199+
)
200+
cli_args = cli_cmd + [cli_arg.format(**template_ctx) for cli_arg in cli_args]
201+
202+
for k, v in env.items():
203+
monkeypatch.setenv(k, v.format(**template_ctx))
204+
205+
monkeypatch.chdir(tmp_path)
206+
207+
if exception is not None:
208+
with pytest.raises(exception, match=message.format(**template_ctx)):
209+
cli.cli(cli_args)
210+
else:
211+
cli.cli(cli_args)
212+
result = capsys.readouterr()
213+
assert message.format(**template_ctx) in result.out
214+
215+
216+
@pytest.mark.parametrize(
217+
"cli_cmd",
218+
[
219+
# ['shell'],
220+
# ['shell', '--pdb'),
221+
["shell", "--code"],
222+
# ['shell', '--bpython'],
223+
# ['shell', '--ptipython'],
224+
# ['shell', '--ptpython'],
225+
# ['shell', '--ipython'],
226+
],
227+
)
228+
@pytest.mark.parametrize(
229+
"cli_args,inputs,env,message",
230+
[
231+
(
232+
[
233+
"-L{SOCKET_NAME}",
234+
],
235+
[],
236+
{},
237+
"(InteractiveConsole)",
238+
),
239+
(
240+
[
241+
"-L{SOCKET_NAME}",
242+
],
243+
[],
244+
{"PANE_ID": "{PANE_ID}"},
245+
"(InteractiveConsole)",
246+
),
247+
],
248+
)
249+
def test_shell_interactive(
250+
cli_cmd: t.List[str],
251+
cli_args: t.List[str],
252+
inputs: t.List[t.Any],
253+
env: t.Dict[str, str],
254+
message: str,
255+
server: "Server",
256+
session: Session,
257+
tmp_path: pathlib.Path,
258+
monkeypatch: pytest.MonkeyPatch,
259+
capsys: pytest.CaptureFixture,
260+
) -> None:
261+
monkeypatch.setenv("HOME", str(tmp_path))
262+
window_name = "my_window"
263+
window = session.new_window(window_name=window_name)
264+
window.split_window()
265+
266+
assert window.attached_pane is not None
267+
268+
template_ctx = dict(
269+
SOCKET_NAME=server.socket_name,
270+
SESSION_NAME=session.name,
271+
WINDOW_NAME=window_name,
272+
PANE_ID=window.attached_pane.id,
273+
SERVER_SOCKET_NAME=server.socket_name,
274+
)
275+
276+
cli_args = cli_cmd + [cli_arg.format(**template_ctx) for cli_arg in cli_args]
277+
278+
for k, v in env.items():
279+
monkeypatch.setenv(k, v.format(**template_ctx))
280+
281+
monkeypatch.chdir(tmp_path)
282+
monkeypatch.setattr("sys.stdin", io.StringIO("exit()\r"))
283+
try:
284+
cli.cli(cli_args)
285+
except SystemExit:
286+
pass
287+
result = capsys.readouterr()
288+
assert message.format(**template_ctx) in result.err

0 commit comments

Comments
 (0)
Please sign in to comment.