@@ -323,231 +323,20 @@ def test_iter_notifications_survives_overflow(
323323 assert first.kind.name == "SESSIONS_CHANGED"
324324
325325
326- class SetClientFlagsCase(t.NamedTuple):
327- """Fixture for refresh-client flag construction."""
328-
329- test_id: str
330- kwargs: dict[str, t.Any]
331- expected_flags: set[str]
332- expect_run: bool
333-
334-
335- @pytest.mark.parametrize(
336- "case",
337- [
338- SetClientFlagsCase(
339- test_id="enable_no_output_with_pause",
340- kwargs={"no_output": True, "pause_after": 1},
341- expected_flags={"no-output", "pause-after=1"},
342- expect_run=True,
343- ),
344- SetClientFlagsCase(
345- test_id="disable_no_output_clear_pause",
346- kwargs={"no_output": False, "pause_after": 0},
347- expected_flags={"!no-output", "!pause-after"},
348- expect_run=True,
349- ),
350- SetClientFlagsCase(
351- test_id="wait_exit_and_read_only",
352- kwargs={"wait_exit": True, "read_only": True},
353- expected_flags={"wait-exit", "read-only"},
354- expect_run=True,
355- ),
356- SetClientFlagsCase(
357- test_id="clear_wait_exit",
358- kwargs={"wait_exit": False},
359- expected_flags={"!wait-exit"},
360- expect_run=True,
361- ),
362- SetClientFlagsCase(
363- test_id="toggle_misc_flags",
364- kwargs={"ignore_size": True, "active_pane": False},
365- expected_flags={"ignore-size", "!active-pane"},
366- expect_run=True,
367- ),
368- SetClientFlagsCase(
369- test_id="noop_when_no_flags",
370- kwargs={},
371- expected_flags=set(),
372- expect_run=False,
373- ),
374- ],
375- ids=lambda c: c.test_id,
376- )
377- def test_set_client_flags_builds_refresh_client(case: SetClientFlagsCase) -> None:
378- """set_client_flags should call refresh-client with correct flag string."""
379- engine = ControlModeEngine(start_threads=False)
380- calls: list[tuple[str, tuple[str, ...], tuple[str, ...]]] = []
381-
382- class DummyCmd:
383- stdout: t.ClassVar[list[str]] = []
384- stderr: t.ClassVar[list[str]] = []
385- returncode: t.ClassVar[int] = 0
386-
387- def fake_run(
388- cmd: str,
389- cmd_args: t.Sequence[str | int] | None = None,
390- server_args: t.Sequence[str | int] | None = None,
391- timeout: float | None = None,
392- ) -> DummyCmd:
393- cmd_args_tuple = tuple(str(a) for a in (cmd_args or ()))
394- server_args_tuple = tuple(str(a) for a in (server_args or ()))
395- calls.append((cmd, cmd_args_tuple, server_args_tuple))
396- return DummyCmd()
397-
398- engine.run = fake_run # type: ignore[assignment]
399-
400- engine.set_client_flags(**case.kwargs)
401-
402- if not case.expect_run:
403- assert calls == []
404- return
405-
406- assert len(calls) == 1
407- cmd, cmd_args, server_args = calls[0]
408- assert cmd == "refresh-client"
409- assert cmd_args and cmd_args[0] == "-f"
410- flags_str = cmd_args[1] if len(cmd_args) > 1 else ""
411- for flag in case.expected_flags:
412- assert flag in flags_str
413- assert server_args == ()
414-
415-
416326def test_set_client_flags_rejects_negative_pause() -> None:
417327 """pause_after must be non-negative."""
418328 engine = ControlModeEngine(start_threads=False)
419329 with pytest.raises(ValueError):
420330 engine.set_client_flags(pause_after=-1)
421331
422332
423- class PaneFlowCase(t.NamedTuple):
424- """Fixture for refresh-client -A flow control."""
425-
426- test_id: str
427- pane_id: str | int
428- state: str
429- expected_arg: str
430-
431-
432- @pytest.mark.parametrize(
433- "case",
434- [
435- PaneFlowCase(
436- test_id="resume_default",
437- pane_id="%1",
438- state="continue",
439- expected_arg="%1:continue",
440- ),
441- PaneFlowCase(
442- test_id="pause_pane",
443- pane_id=3,
444- state="pause",
445- expected_arg="3:pause",
446- ),
447- ],
448- ids=lambda c: c.test_id,
449- )
450- def test_set_pane_flow_builds_refresh_client(case: PaneFlowCase) -> None:
451- """set_pane_flow should build refresh-client -A args."""
452- engine = ControlModeEngine(start_threads=False)
453- calls: list[tuple[str, tuple[str, ...], tuple[str, ...]]] = []
454-
455- class DummyCmd:
456- stdout: t.ClassVar[list[str]] = []
457- stderr: t.ClassVar[list[str]] = []
458- returncode: t.ClassVar[int] = 0
459-
460- def fake_run(
461- cmd: str,
462- cmd_args: t.Sequence[str | int] | None = None,
463- server_args: t.Sequence[str | int] | None = None,
464- timeout: float | None = None,
465- ) -> DummyCmd:
466- cmd_args_tuple = tuple(str(a) for a in (cmd_args or ()))
467- server_args_tuple = tuple(str(a) for a in (server_args or ()))
468- calls.append((cmd, cmd_args_tuple, server_args_tuple))
469- return DummyCmd()
470-
471- engine.run = fake_run # type: ignore[assignment]
472-
473- engine.set_pane_flow(case.pane_id, state=case.state)
474-
475- assert calls
476- cmd, cmd_args, server_args = calls[0]
477- assert cmd == "refresh-client"
478- assert cmd_args == ("-A", case.expected_arg)
479- assert server_args == ()
480-
481-
482333def test_set_pane_flow_validates_state() -> None:
483334 """Invalid flow state should raise."""
484335 engine = ControlModeEngine(start_threads=False)
485336 with pytest.raises(ValueError):
486337 engine.set_pane_flow("%1", state="bad")
487338
488339
489- class SubscribeCase(t.NamedTuple):
490- """Fixture for refresh-client -B subscription arguments."""
491-
492- test_id: str
493- name: str
494- what: str | None
495- format: str | None
496- expected_args: tuple[str, ...]
497-
498-
499- @pytest.mark.parametrize(
500- "case",
501- [
502- SubscribeCase(
503- test_id="add_subscription",
504- name="focus",
505- what="%1",
506- format="#{pane_active}",
507- expected_args=("-B", "focus:%1:#{pane_active}"),
508- ),
509- SubscribeCase(
510- test_id="remove_subscription",
511- name="focus",
512- what=None,
513- format=None,
514- expected_args=("-B", "focus"),
515- ),
516- ],
517- ids=lambda c: c.test_id,
518- )
519- def test_subscribe_builds_refresh_client(case: SubscribeCase) -> None:
520- """Subscribe should wrap refresh-client -B calls."""
521- engine = ControlModeEngine(start_threads=False)
522- calls: list[tuple[str, tuple[str, ...], tuple[str, ...]]] = []
523-
524- class DummyCmd:
525- stdout: t.ClassVar[list[str]] = []
526- stderr: t.ClassVar[list[str]] = []
527- returncode: t.ClassVar[int] = 0
528-
529- def fake_run(
530- cmd: str,
531- cmd_args: t.Sequence[str | int] | None = None,
532- server_args: t.Sequence[str | int] | None = None,
533- timeout: float | None = None,
534- ) -> DummyCmd:
535- cmd_args_tuple = tuple(str(a) for a in (cmd_args or ()))
536- server_args_tuple = tuple(str(a) for a in (server_args or ()))
537- calls.append((cmd, cmd_args_tuple, server_args_tuple))
538- return DummyCmd()
539-
540- engine.run = fake_run # type: ignore[assignment]
541-
542- engine.subscribe(case.name, what=case.what, fmt=case.format)
543-
544- assert calls
545- cmd, cmd_args, server_args = calls[0]
546- assert cmd == "refresh-client"
547- assert cmd_args == case.expected_args
548- assert server_args == ()
549-
550-
551340class ScriptedStdin:
552341 """Fake stdin that can optionally raise BrokenPipeError on write."""
553342
0 commit comments