File: test_box_model.py

package info (click to toggle)
textual 2.1.2-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,080 kB
  • sloc: python: 85,423; lisp: 1,669; makefile: 101
file content (190 lines) | stat: -rw-r--r-- 6,239 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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
from __future__ import annotations

from fractions import Fraction

from textual.box_model import BoxModel
from textual.geometry import Size, Spacing
from textual.widget import Widget


def test_content_box():
    one = Fraction(1)

    class TestWidget(Widget):
        def get_content_width(self, container: Size, parent: Size) -> int:
            assert False, "must not be called"

        def get_content_height(self, container: Size, parent: Size) -> int:
            assert False, "must not be called"

    widget = TestWidget()

    # border-box is default
    assert widget.styles.box_sizing == "border-box"

    widget.styles.width = 10
    widget.styles.height = 8
    widget.styles.padding = 1
    widget.styles.border = ("solid", "red")

    box_model = widget._get_box_model(
        Size(60, 20),
        Size(80, 24),
        one,
        one,
    )
    # Size should be inclusive of padding / border
    assert box_model == BoxModel(Fraction(10), Fraction(8), Spacing(0, 0, 0, 0))

    # Switch to content-box
    widget.styles.box_sizing = "content-box"

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    # width and height have added padding / border to accommodate content
    assert box_model == BoxModel(Fraction(14), Fraction(12), Spacing(0, 0, 0, 0))


def test_width():
    """Test width settings."""

    one = Fraction(1)

    class TestWidget(Widget):
        def get_content_width(self, container: Size, parent: Size) -> int:
            return 10

        def get_content_height(self, container: Size, parent: Size, width: int) -> int:
            return 10

    widget = TestWidget()
    styles = widget.styles
    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(60), Fraction(20), Spacing(0, 0, 0, 0))

    # Add a margin and check that it is reported
    styles.margin = (1, 2, 3, 4)

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))

    # Set width to auto-detect
    styles.width = "auto"

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    # Setting width to auto should call get_auto_width
    assert box_model == BoxModel(Fraction(10), Fraction(16), Spacing(1, 2, 3, 4))

    # Set width to 100 vw which should make it the width of the parent
    styles.width = "100vw"

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(80), Fraction(16), Spacing(1, 2, 3, 4))

    # Set the width to 100% should make it fill the container size
    styles.width = "100%"

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))

    styles.width = "100vw"
    styles.max_width = "50%"

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(27), Fraction(16), Spacing(1, 2, 3, 4))


def test_height():
    """Test height settings."""

    one = Fraction(1)

    class TestWidget(Widget):
        def get_content_width(self, container: Size, parent: Size) -> int:
            return 10

        def get_content_height(self, container: Size, parent: Size, width: int) -> int:
            return 10

    widget = TestWidget()
    styles = widget.styles

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(60), Fraction(20), Spacing(0, 0, 0, 0))

    # Add a margin and check that it is reported
    styles.margin = (1, 2, 3, 4)

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))

    # Set height to 100 vw which should make it the height of the parent
    styles.height = "100vh"

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(54), Fraction(24), Spacing(1, 2, 3, 4))

    # Set the height to 100% should make it fill the container size
    styles.height = "100%"

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))

    styles.height = "auto"
    styles.margin = 2

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    print(box_model)
    assert box_model == BoxModel(Fraction(56), Fraction(10), Spacing(2, 2, 2, 2))

    styles.margin = 1, 2, 3, 4
    styles.height = "100vh"
    styles.max_height = "50%"

    box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(54), Fraction(8), Spacing(1, 2, 3, 4))


def test_max():
    """Check that max_width and max_height are respected."""
    one = Fraction(1)

    class TestWidget(Widget):
        def get_content_width(self, container: Size, parent: Size) -> int:
            assert False, "must not be called"

        def get_content_height(self, container: Size, parent: Size, width: int) -> int:
            assert False, "must not be called"

    widget = TestWidget()
    styles = widget.styles

    styles.width = 100
    styles.height = 80
    styles.max_width = 40
    styles.max_height = 30

    box_model = widget._get_box_model(Size(40, 30), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(40), Fraction(30), Spacing(0, 0, 0, 0))


def test_min():
    """Check that min_width and min_height are respected."""

    one = Fraction(1)

    class TestWidget(Widget):
        def get_content_width(self, container: Size, parent: Size) -> int:
            assert False, "must not be called"

        def get_content_height(self, container: Size, parent: Size, width: int) -> int:
            assert False, "must not be called"

    widget = TestWidget()
    styles = widget.styles
    styles.width = 10
    styles.height = 5
    styles.min_width = 40
    styles.min_height = 30

    box_model = widget._get_box_model(Size(40, 30), Size(80, 24), one, one)
    assert box_model == BoxModel(Fraction(40), Fraction(30), Spacing(0, 0, 0, 0))