Skip to content

Commit 0f216ce

Browse files
committed
tests: extract code examples from docs/pytest-plugin into real tests
1 parent 65e9de8 commit 0f216ce

File tree

6 files changed

+445
-0
lines changed

6 files changed

+445
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""Examples of testing with complex window layouts."""
2+
3+
from __future__ import annotations
4+
5+
import time
6+
7+
from libtmux.constants import PaneDirection
8+
9+
10+
def test_complex_layouts(session) -> None:
11+
"""Test creating and interacting with complex window layouts."""
12+
# Create a window with multiple panes in a specific layout
13+
window = session.new_window(window_name="complex-layout")
14+
15+
# Start with a simple pane
16+
main_pane = window.active_pane
17+
18+
# Split into a left pane and right column
19+
left_pane = main_pane
20+
right_top = window.split(direction=PaneDirection.Right, percent=50)
21+
22+
# Split the right column into top and bottom
23+
right_bottom = right_top.split(direction=PaneDirection.Below, percent=50)
24+
25+
# Apply a layout
26+
window.select_layout("main-vertical")
27+
28+
# Verify the layout was applied
29+
current_layout = window.get("window_layout")
30+
assert current_layout is not None, "Layout was not set"
31+
32+
# Send unique commands to each pane for identification
33+
left_pane.send_keys("echo 'Left Pane'", enter=True)
34+
right_top.send_keys("echo 'Right Top'", enter=True)
35+
right_bottom.send_keys("echo 'Right Bottom'", enter=True)
36+
37+
time.sleep(0.5)
38+
39+
# Verify each pane has the correct content
40+
assert any("Left Pane" in line for line in left_pane.capture_pane())
41+
assert any("Right Top" in line for line in right_top.capture_pane())
42+
assert any("Right Bottom" in line for line in right_bottom.capture_pane())
43+
44+
45+
def test_tiled_layout(session) -> None:
46+
"""Test the tiled layout with multiple panes."""
47+
window = session.new_window(window_name="tiled-layout")
48+
49+
# Create multiple panes
50+
pane1 = window.active_pane
51+
pane2 = window.split(direction=PaneDirection.Right)
52+
pane3 = pane1.split(direction=PaneDirection.Below)
53+
pane4 = pane2.split(direction=PaneDirection.Below)
54+
55+
# Apply the tiled layout
56+
window.select_layout("tiled")
57+
58+
# Verify the layout was applied
59+
current_layout = window.get("window_layout")
60+
assert current_layout is not None, "Layout was not set"
61+
62+
# Send unique commands to each pane
63+
pane1.send_keys("echo 'Pane 1'", enter=True)
64+
pane2.send_keys("echo 'Pane 2'", enter=True)
65+
pane3.send_keys("echo 'Pane 3'", enter=True)
66+
pane4.send_keys("echo 'Pane 4'", enter=True)
67+
68+
time.sleep(0.5)
69+
70+
# Verify each pane has the correct content
71+
assert any("Pane 1" in line for line in pane1.capture_pane())
72+
assert any("Pane 2" in line for line in pane2.capture_pane())
73+
assert any("Pane 3" in line for line in pane3.capture_pane())
74+
assert any("Pane 4" in line for line in pane4.capture_pane())
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""Examples of using TestServer directly."""
2+
3+
from __future__ import annotations
4+
5+
import pytest
6+
7+
from libtmux.pytest_plugin import TestServer
8+
9+
10+
@pytest.fixture
11+
def custom_server():
12+
"""Create a custom server with specific parameters."""
13+
with TestServer(
14+
socket_name="custom-socket",
15+
config_file=None,
16+
colors=256,
17+
focused=True,
18+
) as server:
19+
yield server
20+
21+
22+
def test_custom_server_config(custom_server) -> None:
23+
"""Test a server with custom configuration."""
24+
# Verify server is running
25+
assert custom_server.is_alive()
26+
27+
# Verify custom socket name
28+
assert "custom-socket" in custom_server.socket_path
29+
30+
# Create a session
31+
session = custom_server.new_session(session_name="custom-test")
32+
assert session.name == "custom-test"
33+
34+
# Get color configuration
35+
colors = session.server.show_option("default-terminal")
36+
assert colors is not None
37+
38+
39+
def test_testserver_direct_usage() -> None:
40+
"""Test using TestServer directly as a context manager."""
41+
with TestServer() as server:
42+
# Create a session
43+
session = server.new_session(session_name="direct-test")
44+
assert session.name == "direct-test"
45+
46+
# Create multiple windows
47+
windows = []
48+
for i in range(3):
49+
window = session.new_window(window_name=f"window-{i}")
50+
windows.append(window)
51+
52+
# Verify windows were created
53+
assert len(session.windows) >= 3
54+
for i, window in enumerate(windows):
55+
assert f"window-{i}" == window.window_name
56+
57+
# Server is automatically cleaned up outside the context
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""Examples of operations with tmux panes."""
2+
3+
from __future__ import annotations
4+
5+
import time
6+
7+
from libtmux.constants import PaneDirection
8+
9+
10+
def test_pane_functions(pane) -> None:
11+
"""Test basic pane functions."""
12+
# Send a command to the pane
13+
pane.send_keys("echo 'Hello from pane'", enter=True)
14+
15+
# Give the command time to execute
16+
time.sleep(0.5)
17+
18+
# Capture and verify the output
19+
output = pane.capture_pane()
20+
assert any("Hello from pane" in line for line in output)
21+
22+
23+
def test_window_functions(window) -> None:
24+
"""Test basic window functions."""
25+
# Get the active pane
26+
pane = window.active_pane
27+
assert pane is not None
28+
29+
# Split the window
30+
window.split_window()
31+
assert len(window.panes) == 2
32+
33+
34+
def test_pane_resizing(window) -> None:
35+
"""Test resizing panes."""
36+
# Start with a single pane
37+
original_pane = window.active_pane
38+
39+
# Split horizontally
40+
second_pane = window.split(direction=PaneDirection.Right, percent=50)
41+
assert len(window.panes) == 2
42+
43+
# Resize the first pane to be larger
44+
original_pane.resize(width=60)
45+
time.sleep(0.5)
46+
47+
# Get updated dimensions
48+
dimensions1 = original_pane.dimensions
49+
dimensions2 = second_pane.dimensions
50+
51+
# The first pane should be wider
52+
assert dimensions1["width"] > dimensions2["width"]
53+
54+
# Now resize the second pane to be larger
55+
second_pane.resize(width=60)
56+
time.sleep(0.5)
57+
58+
# Get updated dimensions
59+
dimensions1 = original_pane.dimensions
60+
dimensions2 = second_pane.dimensions
61+
62+
# The second pane should now be wider
63+
assert dimensions2["width"] > dimensions1["width"]
64+
65+
66+
def test_pane_capturing(pane) -> None:
67+
"""Test capturing pane content in different formats."""
68+
# Send multiple lines of content
69+
pane.send_keys("echo 'Line 1'", enter=True)
70+
pane.send_keys("echo 'Line 2'", enter=True)
71+
pane.send_keys("echo 'Line 3'", enter=True)
72+
time.sleep(0.5)
73+
74+
# Capture as a list of lines
75+
output_lines = pane.capture_pane()
76+
assert isinstance(output_lines, list)
77+
assert any("Line 1" in line for line in output_lines)
78+
assert any("Line 2" in line for line in output_lines)
79+
assert any("Line 3" in line for line in output_lines)
80+
81+
# Capture as a single string
82+
output_str = pane.capture_pane(as_str=True)
83+
assert isinstance(output_str, str)
84+
assert "Line 1" in output_str
85+
assert "Line 2" in output_str
86+
assert "Line 3" in output_str
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""Examples of controlling processes in tmux panes."""
2+
3+
from __future__ import annotations
4+
5+
import time
6+
7+
8+
def test_process_detection(pane) -> None:
9+
"""Test detecting running processes in a pane."""
10+
# Start a long-running process
11+
pane.send_keys("sleep 10", enter=True)
12+
time.sleep(0.5)
13+
14+
# Get information about the running process
15+
ps_output = pane.cmd("ps", "-o", "pid,command").stdout
16+
17+
# Verify the sleep command is running
18+
assert any("sleep 10" in line for line in ps_output)
19+
20+
# Kill the process
21+
pane.send_keys(chr(3), literal=True) # Send Ctrl+C
22+
time.sleep(0.5)
23+
24+
# Verify the process has stopped
25+
ps_output = pane.cmd("ps", "-o", "pid,command").stdout
26+
assert not any("sleep 10" in line for line in ps_output)
27+
28+
29+
def test_command_output_scrollback(pane) -> None:
30+
"""Test handling command output that exceeds visible pane height."""
31+
# Generate a lot of output
32+
pane.send_keys('for i in $(seq 1 100); do echo "Line $i"; done', enter=True)
33+
time.sleep(1.0)
34+
35+
# Capture all the scrollback buffer
36+
output = pane.capture_pane(start="-100")
37+
38+
# Check that we have captured a large portion of the output
39+
assert len(output) > 50
40+
41+
# Verify the beginning and end of the captured output
42+
final_lines = [line for line in output if "Line " in line]
43+
if final_lines:
44+
line_numbers = [
45+
int(line.split("Line ")[1])
46+
for line in final_lines
47+
if line.split("Line ")[1].isdigit()
48+
]
49+
if line_numbers:
50+
assert max(line_numbers) > min(line_numbers)
51+
52+
# Clear the scrollback buffer
53+
pane.clear()
54+
time.sleep(0.5)
55+
56+
# Verify the buffer is now empty or only has the prompt
57+
cleared_output = pane.capture_pane()
58+
assert len([line for line in cleared_output if line.strip()]) <= 1
59+
60+
61+
def test_running_background_process(pane) -> None:
62+
"""Test running a process in the background."""
63+
# Start a background process that writes to a file
64+
pane.send_keys("touch /tmp/background_test.txt", enter=True)
65+
pane.send_keys(
66+
'(for i in $(seq 1 5); do echo "Update $i" >> /tmp/background_test.txt; sleep 1; done) &',
67+
enter=True,
68+
)
69+
time.sleep(0.5)
70+
71+
# Check the file periodically
72+
for _attempt in range(5):
73+
pane.send_keys("cat /tmp/background_test.txt", enter=True)
74+
time.sleep(1.0)
75+
output = pane.capture_pane()
76+
if any("Update 3" in line for line in output):
77+
break
78+
79+
# Verify we got at least some updates
80+
assert any("Update" in line for line in output)
81+
82+
# Clean up
83+
pane.send_keys("rm /tmp/background_test.txt", enter=True)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""Examples of testing across tmux server restarts."""
2+
3+
from __future__ import annotations
4+
5+
import time
6+
7+
import libtmux
8+
9+
10+
def test_persist_across_restart(session) -> None:
11+
"""Test functionality across server restarts."""
12+
# Set up initial state
13+
window = session.new_window(window_name="persist-test")
14+
pane = window.active_pane
15+
pane.send_keys("echo 'Data to persist' > /tmp/test-data.txt", enter=True)
16+
time.sleep(0.5)
17+
18+
# Get server info for reconnecting
19+
socket_path = session.server.socket_path
20+
session_id = session.id
21+
22+
# Kill the server
23+
session.server.kill_server()
24+
25+
# Create a new server with the same socket
26+
new_server = libtmux.Server(socket_path=socket_path)
27+
new_server.new_session(session_name="restart-test")
28+
29+
# Verify data persisted
30+
new_session = new_server.get_by_id(session_id)
31+
assert new_session is None # Old session should not exist
32+
33+
# But our file should still exist
34+
new_pane = new_server.sessions[0].attached_window.active_pane
35+
new_pane.send_keys("cat /tmp/test-data.txt", enter=True)
36+
time.sleep(0.5)
37+
38+
output = new_pane.capture_pane()
39+
assert any("Data to persist" in line for line in output)
40+
41+
# Clean up
42+
new_pane.send_keys("rm /tmp/test-data.txt", enter=True)

0 commit comments

Comments
 (0)