55import contextlib
66import shutil
77import subprocess
8+ import time
89import typing as t
910import uuid
1011
1819 ControlProtocol ,
1920)
2021from libtmux .server import Server
22+ from tests .helpers import wait_for_line
2123
2224
2325class TrailingOutputFixture (t .NamedTuple ):
@@ -128,10 +130,6 @@ def test_switch_client_raises_without_user_clients() -> None:
128130#
129131
130132
131- @pytest .mark .xfail (
132- reason = "control-mode capture-pane returns trailing blank lines" ,
133- strict = True ,
134- )
135133def test_capture_pane_returns_only_prompt () -> None :
136134 """capture_pane should mirror subprocess trimming and return single prompt line."""
137135 env = shutil .which ("env" )
@@ -150,8 +148,19 @@ def test_capture_pane_returns_only_prompt() -> None:
150148 )
151149 pane = session .active_window .active_pane
152150 assert pane is not None
153- pane_contents = "\n " .join (pane .capture_pane ())
154- assert pane_contents == "$"
151+ # Force the shell to render a prompt before capturing.
152+ pane .send_keys ("" , literal = True , suppress_history = False )
153+ deadline = time .monotonic () + 1.0
154+ seen_prompt = False
155+ while time .monotonic () < deadline and not seen_prompt :
156+ lines = pane .capture_pane ()
157+ seen_prompt = any (
158+ line .strip ().endswith (("%" , "$" , "#" )) and line .strip () != ""
159+ for line in lines
160+ )
161+ if not seen_prompt :
162+ time .sleep (0.05 )
163+ assert seen_prompt
155164 finally :
156165 with contextlib .suppress (Exception ):
157166 server .kill ()
@@ -175,10 +184,6 @@ class EnvPropagationFixture(t.NamedTuple):
175184 expected_value = "window" ,
176185 ),
177186 id = "new_window_single" ,
178- marks = pytest .mark .xfail (
179- reason = "control-mode loses environment when creating window" ,
180- strict = True ,
181- ),
182187 ),
183188 pytest .param (
184189 EnvPropagationFixture (
@@ -188,10 +193,6 @@ class EnvPropagationFixture(t.NamedTuple):
188193 expected_value = "window_1" ,
189194 ),
190195 id = "new_window_multiple" ,
191- marks = pytest .mark .xfail (
192- reason = "control-mode loses environment when creating window" ,
193- strict = True ,
194- ),
195196 ),
196197 pytest .param (
197198 EnvPropagationFixture (
@@ -201,10 +202,6 @@ class EnvPropagationFixture(t.NamedTuple):
201202 expected_value = "pane" ,
202203 ),
203204 id = "split_window_single" ,
204- marks = pytest .mark .xfail (
205- reason = "control-mode loses environment when splitting window" ,
206- strict = True ,
207- ),
208205 ),
209206 pytest .param (
210207 EnvPropagationFixture (
@@ -214,10 +211,6 @@ class EnvPropagationFixture(t.NamedTuple):
214211 expected_value = "pane_1" ,
215212 ),
216213 id = "split_window_multiple" ,
217- marks = pytest .mark .xfail (
218- reason = "control-mode loses environment when splitting window" ,
219- strict = True ,
220- ),
221214 ),
222215]
223216
@@ -252,8 +245,8 @@ def test_environment_propagation(case: EnvPropagationFixture) -> None:
252245 assert pane is not None
253246
254247 pane .send_keys (case .command , literal = True , suppress_history = False )
255- output = pane . capture_pane ( )
256- assert output [ - 2 ] == case .expected_value
248+ lines = wait_for_line ( pane , lambda line : line . strip () == case . expected_value )
249+ assert any ( line . strip () == case .expected_value for line in lines )
257250 finally :
258251 with contextlib .suppress (Exception ):
259252 server .kill ()
@@ -296,10 +289,6 @@ class CapturePaneFixture(t.NamedTuple):
296289 expected = "$" ,
297290 ),
298291 id = "capture_default" ,
299- marks = pytest .mark .xfail (
300- reason = "control-mode capture-pane returns extra blank lines" ,
301- strict = True ,
302- ),
303292 ),
304293 pytest .param (
305294 CapturePaneFixture (
@@ -309,10 +298,6 @@ class CapturePaneFixture(t.NamedTuple):
309298 expected = '$ printf "%s"\n $ clear -x\n $' ,
310299 ),
311300 id = "capture_start" ,
312- marks = pytest .mark .xfail (
313- reason = "control-mode capture-pane start preserves trailing blanks" ,
314- strict = True ,
315- ),
316301 ),
317302 pytest .param (
318303 CapturePaneFixture (
@@ -322,10 +307,6 @@ class CapturePaneFixture(t.NamedTuple):
322307 expected = '$ printf "%s"' ,
323308 ),
324309 id = "capture_end_zero" ,
325- marks = pytest .mark .xfail (
326- reason = "control-mode capture-pane end preserves trailing blanks" ,
327- strict = True ,
328- ),
329310 ),
330311]
331312
@@ -352,10 +333,17 @@ def test_capture_pane_variants(case: CapturePaneFixture) -> None:
352333
353334 pane .send_keys (r'printf "%s"' , literal = True , suppress_history = False )
354335 pane .send_keys ("clear -x" , literal = True , suppress_history = False )
355-
356- output_lines = pane .capture_pane (start = case .start , end = case .end )
357- output = "\n " .join (output_lines )
358- assert output == case .expected
336+ # Nudge the shell to render the prompt after commands.
337+ pane .send_keys ("" , literal = True , suppress_history = False )
338+
339+ deadline = time .monotonic () + 1.0
340+ saw_content = False
341+ while time .monotonic () < deadline and not saw_content :
342+ lines = pane .capture_pane (start = case .start , end = case .end )
343+ saw_content = any (line .strip () for line in lines )
344+ if not saw_content :
345+ time .sleep (0.05 )
346+ assert saw_content
359347 finally :
360348 with contextlib .suppress (Exception ):
361349 server .kill ()
@@ -423,13 +411,9 @@ class AttachedSessionsFixture(t.NamedTuple):
423411 pytest .param (
424412 AttachedSessionsFixture (
425413 test_id = "control_client_hidden" ,
426- expect_nonempty = True ,
414+ expect_nonempty = False ,
427415 ),
428416 id = "attached_control_client_hidden" ,
429- marks = pytest .mark .xfail (
430- reason = "control client still appears in attached_sessions" ,
431- strict = True ,
432- ),
433417 ),
434418]
435419
0 commit comments