Skip to content

Commit 49aa016

Browse files
committed
tests(pane): Add capture_frame() flag forwarding tests
why: Verify that capture_frame() correctly forwards all capture_pane() flags for proper behavior in snapshot testing scenarios. what: - Add CaptureFrameFlagCase NamedTuple for parametrized tests - Add 4 test cases covering key flag behaviors - Test escape_sequences, join_wrapped, preserve_trailing flags - Verify flag absence behavior (no_escape_sequences)
1 parent 557681c commit 49aa016

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed

tests/test_pane_capture_frame.py

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,3 +685,181 @@ def content_ready() -> bool:
685685

686686
# Compare against snapshot
687687
assert frame == snapshot
688+
689+
690+
# =============================================================================
691+
# Flag Forwarding Tests
692+
# =============================================================================
693+
694+
695+
class CaptureFrameFlagCase(t.NamedTuple):
696+
"""Test case for capture_frame() flag forwarding to capture_pane()."""
697+
698+
test_id: str
699+
command: str
700+
escape_sequences: bool
701+
escape_non_printable: bool
702+
join_wrapped: bool
703+
preserve_trailing: bool
704+
trim_trailing: bool
705+
expected_pattern: str | None
706+
not_expected_pattern: str | None
707+
min_tmux_version: str | None
708+
709+
710+
CAPTURE_FRAME_FLAG_CASES: list[CaptureFrameFlagCase] = [
711+
CaptureFrameFlagCase(
712+
test_id="escape_sequences_color",
713+
command='printf "\\033[31mRED\\033[0m"',
714+
escape_sequences=True,
715+
escape_non_printable=False,
716+
join_wrapped=False,
717+
preserve_trailing=False,
718+
trim_trailing=False,
719+
expected_pattern=r"\x1b\[31m",
720+
not_expected_pattern=None,
721+
min_tmux_version=None,
722+
),
723+
CaptureFrameFlagCase(
724+
test_id="no_escape_sequences",
725+
command='printf "\\033[31mRED\\033[0m"',
726+
escape_sequences=False,
727+
escape_non_printable=False,
728+
join_wrapped=False,
729+
preserve_trailing=False,
730+
trim_trailing=False,
731+
expected_pattern=r"RED",
732+
not_expected_pattern=r"\x1b\[",
733+
min_tmux_version=None,
734+
),
735+
CaptureFrameFlagCase(
736+
test_id="join_wrapped_long_line",
737+
command="printf '%s' \"$(seq 1 30 | tr -d '\\n')\"",
738+
escape_sequences=False,
739+
escape_non_printable=False,
740+
join_wrapped=True,
741+
preserve_trailing=False,
742+
trim_trailing=False,
743+
# With join_wrapped, wrapped lines are joined - verify contiguous sequence
744+
expected_pattern=r"123456789101112131415161718192021222324252627282930",
745+
not_expected_pattern=None,
746+
min_tmux_version=None,
747+
),
748+
CaptureFrameFlagCase(
749+
test_id="preserve_trailing_spaces",
750+
command='printf "text \\n"',
751+
escape_sequences=False,
752+
escape_non_printable=False,
753+
join_wrapped=False,
754+
preserve_trailing=True,
755+
trim_trailing=False,
756+
expected_pattern=r"text ",
757+
not_expected_pattern=None,
758+
min_tmux_version=None,
759+
),
760+
]
761+
762+
763+
@pytest.mark.parametrize(
764+
list(CaptureFrameFlagCase._fields),
765+
CAPTURE_FRAME_FLAG_CASES,
766+
ids=[case.test_id for case in CAPTURE_FRAME_FLAG_CASES],
767+
)
768+
def test_capture_frame_flag_forwarding(
769+
test_id: str,
770+
command: str,
771+
escape_sequences: bool,
772+
escape_non_printable: bool,
773+
join_wrapped: bool,
774+
preserve_trailing: bool,
775+
trim_trailing: bool,
776+
expected_pattern: str | None,
777+
not_expected_pattern: str | None,
778+
min_tmux_version: str | None,
779+
session: Session,
780+
) -> None:
781+
"""Test that capture_frame() correctly forwards flags to capture_pane().
782+
783+
Parameters
784+
----------
785+
test_id : str
786+
Unique identifier for the test case.
787+
command : str
788+
Shell command to execute.
789+
escape_sequences : bool
790+
Include ANSI escape sequences.
791+
escape_non_printable : bool
792+
Escape non-printable characters.
793+
join_wrapped : bool
794+
Join wrapped lines.
795+
preserve_trailing : bool
796+
Preserve trailing spaces.
797+
trim_trailing : bool
798+
Trim trailing positions.
799+
expected_pattern : str | None
800+
Regex pattern expected in output.
801+
not_expected_pattern : str | None
802+
Regex pattern that should NOT be in output.
803+
min_tmux_version : str | None
804+
Minimum tmux version required.
805+
session : Session
806+
pytest fixture providing tmux session.
807+
"""
808+
import re
809+
810+
from libtmux.common import has_gte_version
811+
812+
if min_tmux_version and not has_gte_version(min_tmux_version):
813+
pytest.skip(f"Requires tmux {min_tmux_version}+")
814+
815+
env = shutil.which("env")
816+
assert env is not None
817+
818+
window = session.new_window(
819+
attach=True,
820+
window_name=f"flag_{test_id}",
821+
window_shell=f"{env} PS1='$ ' sh",
822+
)
823+
pane = window.active_pane
824+
assert pane is not None
825+
826+
# Wait for shell prompt
827+
def prompt_ready() -> bool:
828+
return "$" in "\n".join(pane.capture_pane())
829+
830+
retry_until(prompt_ready, 2, raises=True)
831+
832+
# Send command and wait for completion marker
833+
marker = f"__DONE_{test_id}__"
834+
pane.send_keys(f"{command}; echo {marker}", literal=True)
835+
836+
def marker_ready() -> bool:
837+
return marker in "\n".join(pane.capture_pane())
838+
839+
retry_until(marker_ready, 3, raises=True)
840+
841+
# Capture frame with specified flags
842+
frame = pane.capture_frame(
843+
content_width=80,
844+
content_height=24,
845+
escape_sequences=escape_sequences,
846+
escape_non_printable=escape_non_printable,
847+
join_wrapped=join_wrapped,
848+
preserve_trailing=preserve_trailing,
849+
trim_trailing=trim_trailing,
850+
)
851+
852+
# Get rendered content (without frame borders)
853+
rendered = frame.render()
854+
855+
# Verify expected pattern
856+
if expected_pattern:
857+
assert re.search(expected_pattern, rendered, re.DOTALL), (
858+
f"Expected pattern '{expected_pattern}' not found in:\n{rendered}"
859+
)
860+
861+
# Verify not_expected pattern is absent
862+
if not_expected_pattern:
863+
assert not re.search(not_expected_pattern, rendered, re.DOTALL), (
864+
f"Unexpected pattern '{not_expected_pattern}' found in:\n{rendered}"
865+
)

0 commit comments

Comments
 (0)