diff --git a/tests/test_rawcli.py b/tests/test_rawcli.py index edcbed2..87438f6 100644 --- a/tests/test_rawcli.py +++ b/tests/test_rawcli.py @@ -931,3 +931,65 @@ class TestKeyBindings: digit[ch].handler(SimpleNamespace(current_buffer=buf, app=app, data=ch)) assert buf.text == "00000100" assert len(fired) == 8 # one insert_text per digit (0 with document=) + + +class TestRawcliLiveSession: + """End-to-end through the REAL PromptSession run() builds (real key bindings + RawCompleter + + complete_while_typing), driven by a prompt_toolkit pipe input that simulates TTY keystrokes. + Exercises the actual rawcli input stack; no device needed for the input layer.""" + + @staticmethod + def _run_keys(keys): + import asyncio + from prompt_toolkit import PromptSession + from prompt_toolkit.input import create_pipe_input + from prompt_toolkit.output import DummyOutput + from prompt_toolkit.key_binding import KeyBindings + from pm3py.cli.rawcli.entry import install_key_bindings + from pm3py.cli.rawcli.completer import RawCompleter + state = RawSession() + comp = RawCompleter(state) + queried = [] + _orig = comp.get_completions + def _rec(document, event): + queried.append(document.text) + yield from _orig(document, event) + comp.get_completions = _rec + kb = KeyBindings() + install_key_bindings(kb, state) + # PromptSession.prompt() runs asyncio.run() internally, which nulls the current-loop + # pointer; save/restore it so the shared-loop `_run` convention in other test files isn't + # poisoned (see tests/test_pyws_plugin.py). + try: + prev_loop = asyncio.get_event_loop() + except RuntimeError: + prev_loop = None + try: + with create_pipe_input() as inp: + session = PromptSession(key_bindings=kb, completer=comp, complete_while_typing=True, + input=inp, output=DummyOutput()) + inp.send_text(keys + "\r") + line = session.prompt("> ") + finally: + if prev_loop is not None and not prev_loop.is_closed(): + asyncio.set_event_loop(prev_loop) + return line, queried + + def test_accepted_line_across_input_paths(self): + # the change touched the digit handler; confirm every input path still yields the right line + toggle = "\x14" # Ctrl-t entry-mode toggle + for keys, expect in [("3004", "30 04"), + (toggle + "00000100", "00000100"), + ("30" + toggle + "00000100", "30 00000100"), + ("read(4)", "read(4)"), + ("identify", "identify")]: + line, _ = self._run_keys(keys) + assert line == expect, f"{keys!r} -> {line!r} != {expect!r}" + + def test_live_completion_fires_during_binary_entry(self): + # the fix, in the real session: the completer is queried with the byte-line text while + # typing binary (0 queries before the fix, since buf.document= reset complete_state) + line, queried = self._run_keys("\x14" + "00000100") + byte_q = [q for q in queried if q and q.replace(" ", "").strip("01") == ""] + assert line == "00000100" + assert byte_q, "completer never queried for byte-line text — live menu not firing"