prompt-toolkit / python-prompt-toolkit

Library for building powerful interactive command line applications in Python
https://python-prompt-toolkit.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
9.28k stars 715 forks source link

Prompt test with backspace+validator #1613

Open vallsv opened 2 years ago

vallsv commented 2 years ago

Hi,

I try to setup unit tests on some code based on prompt. But i am not able to write backspace to the input stream with validator. It sounds like after the first \n aborted by the validator, the \b behave like a left arrow key.

I don't have such behaviour outside of the unittest.

from prompt_toolkit.shortcuts import PromptSession
from prompt_toolkit.input import create_pipe_input
from prompt_toolkit.output import DummyOutput
from prompt_toolkit.validation import Validator, ValidationError

def test_prompt_session():
    """Copy paste of the example provided by prompt toolkit + backspace"""
    with create_pipe_input() as inp:
        inp.send_text("hello\b\n")
        session = PromptSession(
            input=inp,
            output=DummyOutput(),
        )

        result = session.prompt()

    assert result == "hell"

def test_prompt_session2():
    class NameValidator(Validator):
        def validate(self, document):
            text = document.text.lower()
            if not text.isidentifier():
                raise ValidationError(
                    message="The input must be an identifier"
                )

    with create_pipe_input() as inp:
        session = PromptSession(
            input=inp,
            output=DummyOutput(),
            validator=NameValidator()
        )
        inp.send_text("1t\n\b\ba\n")

        result = session.prompt()

    assert result == "a"

The result it

>       assert result == "a"
E       AssertionError: assert 'a1t' == 'a'
E         - a
E         + a1t

Do you have any idea what's wrong or how i should check such key sequence?

jonathanslenders commented 2 years ago

@vallsv,

It looks that the reason here is the \n that accepts the input which causes the input to be validated, and because of that, move the cursor to the start of the line. So, the backspace doesn't have any effect there. A cursor_position can be set as part of the ValidationError.

vallsv commented 2 years ago

Thanks a lot for the feedback.

But i have checked again with a raw ptpython shell. And the behaviour is not the same. The return key do not move the cursor at start. In fact i guess after each key press the validator is executed. Could it be something setup by ptpython itself?

Else, ill try to return the actual cursor position as you explained, that's not a big deal. Or i anyway can try to setup a test based on this known behaviour. Thanks a lot.