Coverage for tests/output/test_prompts.py: 86%

67 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-09 12:09 +0100

1from __future__ import annotations 

2 

3import io 

4from pathlib import Path 

5from typing import Iterator 

6 

7import pytest 

8from hypothesis import assume 

9from hypothesis import given 

10from hypothesis import HealthCheck 

11from hypothesis import settings 

12from hypothesis import strategies as st 

13from pytest import CaptureFixture 

14from pytest import MonkeyPatch 

15 

16from harbor_cli.output.prompts import float_prompt 

17from harbor_cli.output.prompts import int_prompt 

18from harbor_cli.output.prompts import path_prompt 

19from harbor_cli.output.prompts import str_prompt 

20 

21# TODO: test defaults 

22 

23 

24def leading_newline() -> Iterator[str]: 

25 """Yields a leading newline and then no leading newline. 

26 

27 This helps us test whether or not empty inputs prompts the user to 

28 input again. 

29 """ 

30 yield "\n" 

31 yield "" 

32 

33 

34@pytest.mark.skip(reason="Flaky test in CI. Need to investigate.") 

35@pytest.mark.parametrize("leading_newline", leading_newline()) 

36@given(st.text(min_size=1)) 

37@settings(suppress_health_check=[HealthCheck.function_scoped_fixture]) 

38def test_str_prompt(monkeypatch: MonkeyPatch, leading_newline: str, text: str) -> None: 

39 assume(not text.isspace()) # not testing pure whitespace 

40 stdin_str = leading_newline + text + "\n" 

41 monkeypatch.setattr("sys.stdin", io.StringIO(stdin_str)) 

42 # Result is always stripped of whitespace, and newline = enter 

43 # So anything after \n is 

44 expect = next(t.strip() for t in text.split("\n") if t) 

45 assert str_prompt("foo") == expect 

46 

47 

48@pytest.mark.skip(reason="Flaky test in CI. Need to investigate.") 

49@given(st.text()) 

50@settings(suppress_health_check=[HealthCheck.function_scoped_fixture]) 

51def test_str_prompt_empty_ok(monkeypatch: MonkeyPatch, text: str) -> None: 

52 stdin_str = text + "\n" 

53 monkeypatch.setattr("sys.stdin", io.StringIO(stdin_str)) 

54 # Result is always stripped of whitespace, and newline = enter 

55 # So anything after \n is ignored 

56 assert str_prompt("foo", empty_ok=True) == text.split("\n")[0].strip() 

57 

58 

59@pytest.mark.parametrize("leading_newline", leading_newline()) 

60@pytest.mark.parametrize("leading_float", ["", "3.14159265358979\n"]) 

61@given(st.integers()) 

62@settings(suppress_health_check=[HealthCheck.function_scoped_fixture]) 

63def test_int_prompt( 

64 monkeypatch: MonkeyPatch, 

65 # Leading newline prompts for new input 

66 leading_newline: str, 

67 # Floating point numbers are invalid, and will prompt for new input 

68 leading_float: str, 

69 inp: int, 

70) -> None: 

71 stdin_str = leading_newline + leading_float + str(inp) + "\n" 

72 monkeypatch.setattr("sys.stdin", io.StringIO(stdin_str)) 

73 assert int_prompt("foo") == inp 

74 

75 

76@pytest.mark.parametrize("leading_newline", leading_newline()) 

77@given(st.floats(allow_nan=False)) 

78@settings(suppress_health_check=[HealthCheck.function_scoped_fixture]) 

79def test_float_prompt( 

80 monkeypatch: MonkeyPatch, capsys: CaptureFixture, leading_newline: str, inp: float 

81) -> None: 

82 # so we can test that empty input prompts again 

83 stdin_str = leading_newline + str(inp) + "\n" 

84 monkeypatch.setattr("sys.stdin", io.StringIO(stdin_str)) 

85 assert float_prompt("foo") == inp 

86 if leading_newline: 

87 # Rich prints this message to stdout for some reason 

88 assert "Please enter a number" in capsys.readouterr().out 

89 

90 

91@pytest.mark.parametrize("leading_newline", leading_newline()) 

92def test_float_prompt_nan( 

93 monkeypatch: MonkeyPatch, leading_newline: str, capsys: CaptureFixture 

94) -> None: 

95 # if we give it a nan, it will prompt for new input 

96 # so we need to give it a valid input after that 

97 stdin_str = leading_newline + "nan\n" + "0.0\n" 

98 monkeypatch.setattr("sys.stdin", io.StringIO(stdin_str)) 

99 assert float_prompt("foo") == 0.0 

100 stdout, stderr = capsys.readouterr() 

101 assert "NaN" in stderr 

102 if leading_newline: 

103 # Rich prints this message to stdout for some reason 

104 assert "Please enter a number" in stdout 

105 

106 

107def test_path_prompt(monkeypatch: MonkeyPatch, tmp_path: Path) -> None: 

108 p = tmp_path / "test.txt" 

109 p = p.resolve().absolute() 

110 monkeypatch.setattr("sys.stdin", io.StringIO(f"{p}\n")) 

111 assert path_prompt("foo") == p