File: test_patches.py

package info (click to toggle)
zabbix-cli 3.5.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,860 kB
  • sloc: python: 18,557; makefile: 3
file content (168 lines) | stat: -rw-r--r-- 5,042 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
from __future__ import annotations

import copy
from typing import Any

import pytest
import typer
import typer.rich_utils
from inline_snapshot import snapshot
from rich.color import Color
from rich.color import ColorType
from rich.console import Console
from rich.segment import Segment
from rich.style import Style
from typer.models import ParameterInfo
from zabbix_cli._patches import typer as typ
from zabbix_cli.exceptions import ZabbixCLIError
from zabbix_cli.pyzabbix.enums import APIStr
from zabbix_cli.pyzabbix.enums import APIStrEnum


def test_typer_patches_idempotent() -> None:
    # patch() runs all patching functions
    typ.patch()

    # Run each patching function again to ensure no errors are raised
    # very primitive test, but ensures that we can call it as many times
    # as we want without any obvious errors.
    typ.patch__get_rich_console()
    typ.patch_generate_enum_convertor()
    typ.patch_get_click_type()
    typ.patch_help_text_spacing()
    typ.patch_help_text_style()


def test_patch__get_rich_console(
    capsys: pytest.CaptureFixture, force_color: Any
) -> None:
    original = copy.deepcopy(typer.rich_utils._get_rich_console)
    typ.patch__get_rich_console()
    new = typer.rich_utils._get_rich_console
    assert original != new

    original_val = original()
    new_val = new()
    assert original_val != new_val

    assert isinstance(original_val, Console)
    assert isinstance(new_val, Console)

    # Test some styles
    to_render = "[option]foo[/] [metavar]bar[/]"
    rendered = new_val.render(to_render)
    assert list(rendered) == snapshot(
        [
            Segment(
                text="foo",
                style=Style(
                    color=Color("cyan", ColorType.STANDARD, number=6), bold=True
                ),
            ),
            Segment(text=" ", style=Style()),
            Segment(
                text="bar",
                style=Style(
                    color=Color("yellow", ColorType.STANDARD, number=3), bold=True
                ),
            ),
            Segment(text="\n"),
        ]
    )

    # Flush capture buffer
    capsys.readouterr()
    new_val.print(to_render)
    assert capsys.readouterr().out == snapshot(
        "\x1b[1;36mfoo\x1b[0m \x1b[1;33mbar\x1b[0m\n"
    )


def test_patch_generate_enum_convertor() -> None:
    original = copy.deepcopy(typer.main.generate_enum_convertor)
    typ.patch_generate_enum_convertor()
    new = typer.main.generate_enum_convertor
    assert original != new

    class APIEnum(APIStrEnum):
        FOO = APIStr("foo", 0)
        BAR = APIStr("bar", 1)

    converter = new(APIEnum)
    assert converter("foo") == APIEnum.FOO
    assert converter("bar") == APIEnum.BAR
    assert converter(0) == APIEnum.FOO
    assert converter(1) == APIEnum.BAR
    assert converter("0") == APIEnum.FOO
    assert converter("1") == APIEnum.BAR

    with pytest.raises(ZabbixCLIError):
        assert converter("baz")
    with pytest.raises(ZabbixCLIError):
        assert converter(2)
    with pytest.raises(ZabbixCLIError):
        assert converter("2")


def test_patch_get_click_type() -> None:
    original = copy.deepcopy(typer.main.get_click_type)
    typ.patch_get_click_type()
    new = typer.main.get_click_type
    assert original != new

    class APIEnum(APIStrEnum):
        FOO = APIStr("foo", 0)
        BAR = APIStr("bar", 1)

    assert new(
        annotation=APIEnum, parameter_info=ParameterInfo()
    ).to_info_dict() == snapshot(
        {
            "param_type": "Choice",
            "name": "choice",
            "choices": ["foo", "bar", "0", "1"],
            "case_sensitive": True,
        }
    )

    assert new(
        annotation=APIEnum, parameter_info=ParameterInfo(case_sensitive=False)
    ).to_info_dict() == snapshot(
        {
            "param_type": "Choice",
            "name": "choice",
            "choices": ["foo", "bar", "0", "1"],
            "case_sensitive": False,
        }
    )


def test_patch_help_text_spacing(ctx: typer.Context) -> None:
    original = copy.deepcopy(typer.rich_utils._get_help_text)
    typ.patch_help_text_spacing()
    new = typer.rich_utils._get_help_text
    assert original != new

    ctx.command.help = "This is the first line.\n\nThis is the last line."
    help_text = new(obj=ctx.command, markup_mode="rich")
    console = typer.rich_utils._get_rich_console()
    assert list(console.render(help_text)) == snapshot(
        [
            Segment(text="This is the first line."),
            Segment(text="\n"),
            Segment(text=""),
            Segment(text="\n"),
            Segment(text="This is the last line."),
            Segment(text="\n"),
        ]
    )


def test_patch_help_text_style() -> None:
    # No in-depth testing here - just ensure that the function
    # sets the style we expect.
    # test_patch_help_text_spacing() tests the actual rendering.
    typ.patch_help_text_style()
    style = typer.rich_utils.STYLE_HELPTEXT
    assert style != "dim"
    assert style == snapshot("")