6
6
from __future__ import annotations
7
7
8
8
from functools import partial
9
+ import io
10
+ import sys
9
11
10
12
import pytest
11
13
12
14
from prompt_toolkit .clipboard import ClipboardData , InMemoryClipboard
15
+ from prompt_toolkit .data_structures import Size
13
16
from prompt_toolkit .enums import EditingMode
14
17
from prompt_toolkit .filters import ViInsertMode
15
18
from prompt_toolkit .history import InMemoryHistory
18
21
from prompt_toolkit .key_binding .bindings .named_commands import prefix_meta
19
22
from prompt_toolkit .key_binding .key_bindings import KeyBindings
20
23
from prompt_toolkit .output import DummyOutput
24
+ from prompt_toolkit .output .plain_text import PlainTextOutput
25
+ from prompt_toolkit .output .vt100 import Vt100_Output
21
26
from prompt_toolkit .shortcuts import PromptSession
22
27
23
28
@@ -29,6 +34,33 @@ def _history():
29
34
return h
30
35
31
36
37
+ def _feed_cli_with_password (text , check_line_ending = True , hide_password = False ):
38
+ """
39
+ Create a Prompt, feed it with a given user input considered
40
+ to be a password, and then return the CLI output to the caller.
41
+
42
+ This returns an Output object.
43
+ """
44
+
45
+ # If the given text doesn't end with a newline, the interface won't finish.
46
+ if check_line_ending :
47
+ assert text .endswith ("\r " )
48
+
49
+ output = PlainTextOutput (stdout = io .StringIO ())
50
+
51
+ with create_pipe_input () as inp :
52
+ inp .send_text (text )
53
+ session = PromptSession (
54
+ input = inp ,
55
+ output = output ,
56
+ is_password = True ,
57
+ hide_password = hide_password ,
58
+ )
59
+
60
+ _ = session .prompt ()
61
+ return output
62
+
63
+
32
64
def _feed_cli_with_input (
33
65
text ,
34
66
editing_mode = EditingMode .EMACS ,
@@ -42,7 +74,7 @@ def _feed_cli_with_input(
42
74
Create a Prompt, feed it with the given user input and return the CLI
43
75
object.
44
76
45
- This returns a (result , Application) tuple.
77
+ This returns a (Document , Application, Output ) tuple.
46
78
"""
47
79
# If the given text doesn't end with a newline, the interface won't finish.
48
80
if check_line_ending :
@@ -64,6 +96,33 @@ def _feed_cli_with_input(
64
96
return session .default_buffer .document , session .app
65
97
66
98
99
+ def test_visible_password ():
100
+ # Both the `result` and the `cli.current_buffer` displays the password in plain-text,
101
+ # but that's not what the user sees on screen.
102
+ password = "secret-value\r "
103
+ output = _feed_cli_with_password (password , hide_password = False )
104
+ output .stdout .seek (0 ) # Reset the stream pointer
105
+ actual_output = output .stdout .read ().strip ()
106
+
107
+ # Test that the string is made up only of `*` characters
108
+ assert actual_output == "*" * len (actual_output ), actual_output
109
+
110
+ # Test that the string is long as much as the original password,
111
+ # minus the needed carriage return.
112
+ assert actual_output == "*" * len (password .strip ()), actual_output
113
+
114
+
115
+ def test_invisible_password ():
116
+ password = "secret-value\r "
117
+ output = _feed_cli_with_password (password , hide_password = True )
118
+ output .stdout .seek (0 ) # Reset the stream pointer
119
+ actual_output = output .stdout .read ().strip ()
120
+
121
+ # Test that, if the `hide_password` flag is set to True,
122
+ # then then prompt won't display anything in the output.
123
+ assert actual_output == "" , actual_output
124
+
125
+
67
126
def test_simple_text_input ():
68
127
# Simple text input, followed by enter.
69
128
result , cli = _feed_cli_with_input ("hello\r " )
0 commit comments