Skip to content

Commit 3c1cdbe

Browse files
committed
docs(examples): Add comprehensive examples for waiter utility
- Move example tests to tests/examples/test/test_waiter.py - Add examples for all wait functions including the fluent API - Ensure proper typing and None checks throughout examples - Demonstrate wait_for_any_content and wait_for_all_content with different patterns - Show fluent API chaining with configuration options
1 parent ff8ffcf commit 3c1cdbe

File tree

1 file changed

+182
-0
lines changed

1 file changed

+182
-0
lines changed
+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#!/usr/bin/env python
2+
"""
3+
Examples of using the libtmux waiter API for testing.
4+
5+
This file demonstrates various ways to use the waiter utility
6+
for waiting on pane content in tmux sessions.
7+
"""
8+
9+
from __future__ import annotations
10+
11+
import re
12+
import typing as t
13+
14+
import libtmux
15+
from libtmux.test.waiter import (
16+
ContentMatchType,
17+
WaitResult,
18+
expect,
19+
wait_for_all_content,
20+
wait_for_any_content,
21+
wait_for_pane_content,
22+
wait_until_pane_ready,
23+
)
24+
25+
if t.TYPE_CHECKING:
26+
from libtmux.pane import Pane
27+
28+
29+
def run_basic_example(server: libtmux.Server) -> None:
30+
"""Demonstrate basic waiting for pane content."""
31+
session = server.new_session("waiter-example")
32+
window = session.active_window
33+
pane: Pane = window.active_pane # type: ignore
34+
35+
# Run a command
36+
pane.send_keys("echo 'Hello, world!'", enter=True)
37+
38+
# Wait for the output to appear
39+
wait_for_pane_content(pane, "Hello, world!")
40+
41+
# Wait for shell prompt
42+
wait_until_pane_ready(pane)
43+
44+
45+
def run_fluent_api_example(server: libtmux.Server) -> None:
46+
"""Demonstrate the fluent API for waiting on pane content."""
47+
session = server.new_session("waiter-fluent-example")
48+
pane: Pane = t.cast("Pane", session.active_window.active_pane)
49+
50+
# Run a command
51+
pane.send_keys("for i in {1..5}; do echo $i; sleep 0.1; done", enter=True)
52+
53+
# Use the fluent API for better readability
54+
(
55+
expect(pane)
56+
.with_timeout(2.0)
57+
.wait_for_regex(r"\b[35]\b") # Wait for either 3 or 5 to appear
58+
)
59+
60+
# Wait for completion without raising an exception
61+
pane.send_keys("sleep 1 && echo 'Completed'", enter=True)
62+
result2: WaitResult = (
63+
expect(pane)
64+
.without_raising()
65+
.with_timeout(0.5) # Short timeout to demo timeout handling
66+
.wait_for_text("Completed")
67+
)
68+
69+
if result2.success:
70+
pass
71+
72+
# Wait again with longer timeout
73+
expect(pane).with_timeout(2.0).wait_for_text("Completed")
74+
75+
76+
def run_any_content_example(server: libtmux.Server) -> None:
77+
"""Demonstrate waiting for any of multiple patterns."""
78+
session = server.new_session("waiter-any-example")
79+
window = session.active_window
80+
pane: Pane = window.active_pane # type: ignore
81+
82+
# Run a command that will produce one of several outputs
83+
pane.send_keys("echo 'Error: Connection failed'", enter=True)
84+
85+
# Wait for any of multiple patterns
86+
result: WaitResult = wait_for_any_content(
87+
pane,
88+
["Success", "Error:", "timeout"],
89+
ContentMatchType.CONTAINS,
90+
)
91+
92+
if (
93+
result.success
94+
and result.matched_content is not None
95+
and "Error" in str(result.matched_content)
96+
):
97+
pass
98+
99+
100+
def run_all_content_example(server: libtmux.Server) -> None:
101+
"""Demonstrate waiting for all patterns to appear."""
102+
session = server.new_session("waiter-all-example")
103+
window = session.active_window
104+
pane: Pane = window.active_pane # type: ignore
105+
106+
# Run commands that will produce multiple outputs
107+
pane.send_keys("echo 'Database connected'; echo 'Server started'", enter=True)
108+
109+
# Wait for all patterns to appear
110+
result: WaitResult = wait_for_all_content(
111+
pane,
112+
["Database connected", "Server started"],
113+
ContentMatchType.CONTAINS,
114+
)
115+
116+
if result.success:
117+
pass
118+
119+
120+
def run_mixed_type_example(server: libtmux.Server) -> None:
121+
"""Demonstrate using different match types together."""
122+
session = server.new_session("waiter-mixed-example")
123+
window = session.active_window
124+
pane: Pane = window.active_pane # type: ignore
125+
126+
# Run a command
127+
pane.send_keys("echo '10 items found in database'", enter=True)
128+
129+
# Wait with mixed pattern types
130+
wait_for_any_content(
131+
pane,
132+
[
133+
"exact match", # Will not match
134+
"items found", # Will match as substring
135+
re.compile(r"\d+ items"), # Will match as regex
136+
lambda lines: len(lines) > 0, # Will match as predicate
137+
],
138+
[
139+
ContentMatchType.EXACT,
140+
ContentMatchType.CONTAINS,
141+
ContentMatchType.REGEX,
142+
ContentMatchType.PREDICATE,
143+
],
144+
)
145+
146+
147+
def clean_up(server: libtmux.Server) -> None:
148+
"""Clean up test sessions."""
149+
for prefix in [
150+
"waiter-example",
151+
"waiter-fluent-example",
152+
"waiter-any-example",
153+
"waiter-all-example",
154+
"waiter-mixed-example",
155+
]:
156+
for session in server.sessions:
157+
if session.name is not None and session.name.startswith(prefix):
158+
session.kill()
159+
160+
161+
def main() -> None:
162+
"""Run all examples."""
163+
server = libtmux.Server()
164+
165+
try:
166+
run_basic_example(server)
167+
168+
run_fluent_api_example(server)
169+
170+
run_any_content_example(server)
171+
172+
run_all_content_example(server)
173+
174+
run_mixed_type_example(server)
175+
176+
finally:
177+
# Make sure to clean up
178+
clean_up(server)
179+
180+
181+
if __name__ == "__main__":
182+
main()

0 commit comments

Comments
 (0)