tests for box model

This commit is contained in:
Will McGugan
2022-04-21 12:16:05 +01:00
parent 4980488973
commit c68d6e8d0e
5 changed files with 195 additions and 9 deletions

View File

@@ -26,7 +26,7 @@ Widget {
#thing2 { #thing2 {
border: solid white; border: solid white;
/* outline: heavy blue; */ /* outline: heavy blue; */
height: 10;
padding: 1 2; padding: 1 2;
box-sizing: border-box; box-sizing: border-box;
@@ -39,7 +39,7 @@ Widget {
#thing3 { #thing3 {
height: 10;
margin: 1; margin: 1;
background:blue; background:blue;
align-horizontal: center; align-horizontal: center;

View File

@@ -8,7 +8,7 @@
.list-item { .list-item {
height: 8; height: 8;
width:100%;
min-width: 80; min-width: 80;
background: dark_blue; background: dark_blue;
} }

View File

@@ -40,7 +40,9 @@ def get_box_model(
is_content_box = styles.box_sizing == "content-box" is_content_box = styles.box_sizing == "content-box"
gutter = styles.padding + styles.border.spacing gutter = styles.padding + styles.border.spacing
if not has_rule("width") or styles.width.is_auto: if not has_rule("width"):
width = container_size.width
elif styles.width.is_auto:
# When width is auto, we want enough space to always fit the content # When width is auto, we want enough space to always fit the content
width = get_content_width(container_size, parent_size) width = get_content_width(container_size, parent_size)
if not is_content_box: if not is_content_box:
@@ -50,7 +52,9 @@ def get_box_model(
else: else:
width = styles.width.resolve_dimension(container_size, parent_size) width = styles.width.resolve_dimension(container_size, parent_size)
if not has_rule("height") or styles.height.is_auto: if not has_rule("height"):
height = container_size.height
elif styles.height.is_auto:
height = get_content_height(container_size, parent_size) height = get_content_height(container_size, parent_size)
if not is_content_box: if not is_content_box:
height += gutter.height height += gutter.height

View File

@@ -194,10 +194,10 @@ class StylesBase(ABC):
box_sizing = StringEnumProperty(VALID_BOX_SIZING, "border-box") box_sizing = StringEnumProperty(VALID_BOX_SIZING, "border-box")
width = ScalarProperty(percent_unit=Unit.WIDTH) width = ScalarProperty(percent_unit=Unit.WIDTH)
height = ScalarProperty(percent_unit=Unit.HEIGHT) height = ScalarProperty(percent_unit=Unit.HEIGHT)
min_width = ScalarProperty(percent_unit=Unit.WIDTH) min_width = ScalarProperty(percent_unit=Unit.WIDTH, allow_auto=False)
min_height = ScalarProperty(percent_unit=Unit.HEIGHT) min_height = ScalarProperty(percent_unit=Unit.HEIGHT, allow_auto=False)
max_width = ScalarProperty(percent_unit=Unit.WIDTH) max_width = ScalarProperty(percent_unit=Unit.WIDTH, allow_auto=False)
max_height = ScalarProperty(percent_unit=Unit.HEIGHT) max_height = ScalarProperty(percent_unit=Unit.HEIGHT, allow_auto=False)
dock = DockProperty() dock = DockProperty()
docks = DocksProperty() docks = DocksProperty()

182
tests/test_box_model.py Normal file
View File

@@ -0,0 +1,182 @@
from __future__ import annotations
from textual.box_model import BoxModel, get_box_model
from textual.css.styles import Styles
from textual.geometry import Size, Spacing
def test_content_box():
styles = Styles()
styles.width = 10
styles.height = 8
styles.padding = 1
styles.border = ("solid", "red")
# border-box is default
assert styles.box_sizing == "border-box"
def get_auto_width(container: Size, parent: Size) -> int:
assert False, "must not be called"
def get_auto_height(container: Size, parent: Size) -> int:
assert False, "must not be called"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
# Size should be inclusive of padding / border
assert box_model == BoxModel(Size(10, 8), Spacing(0, 0, 0, 0))
# Switch to content-box
styles.box_sizing = "content-box"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
# width and height have added padding / border to accommodate content
assert box_model == BoxModel(Size(14, 12), Spacing(0, 0, 0, 0))
def test_width():
"""Test width settings."""
styles = Styles()
def get_auto_width(container: Size, parent: Size) -> int:
return 10
def get_auto_height(container: Size, parent: Size) -> int:
return 10
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(60, 20), Spacing(0, 0, 0, 0))
# Add a margin and check that it is reported
styles.margin = (1, 2, 3, 4)
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(60, 20), Spacing(1, 2, 3, 4))
styles.width = "auto"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
# Setting width to auto should call get_auto_width
assert box_model == BoxModel(Size(10, 20), Spacing(1, 2, 3, 4))
# Set width to 100 vw which should make it the width of the parent
styles.width = "100vw"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(80, 20), Spacing(1, 2, 3, 4))
# Set the width to 100% should make it fill the container size
styles.width = "100%"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(60, 20), Spacing(1, 2, 3, 4))
styles.width = "100vw"
styles.max_width = "50%"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(30, 20), Spacing(1, 2, 3, 4))
def test_height():
"""Test width settings."""
styles = Styles()
def get_auto_width(container: Size, parent: Size) -> int:
return 10
def get_auto_height(container: Size, parent: Size) -> int:
return 10
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(60, 20), Spacing(0, 0, 0, 0))
# Add a margin and check that it is reported
styles.margin = (1, 2, 3, 4)
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(60, 20), Spacing(1, 2, 3, 4))
# Set width to 100 vw which should make it the width of the parent
styles.height = "100vh"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(60, 24), Spacing(1, 2, 3, 4))
# Set the width to 100% should make it fill the container size
styles.height = "100%"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(60, 20), Spacing(1, 2, 3, 4))
styles.height = "100vh"
styles.max_height = "50%"
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(60, 10), Spacing(1, 2, 3, 4))
def test_max():
"""Check that max_width and max_height are respected."""
styles = Styles()
styles.width = 100
styles.height = 80
styles.max_width = 40
styles.max_height = 30
def get_auto_width(container: Size, parent: Size) -> int:
assert False, "must not be called"
def get_auto_height(container: Size, parent: Size) -> int:
assert False, "must not be called"
box_model = get_box_model(
styles, Size(40, 30), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(40, 30), Spacing(0, 0, 0, 0))
def test_min():
"""Check that min_width and min_height are respected."""
styles = Styles()
styles.width = 10
styles.height = 5
styles.min_width = 40
styles.min_height = 30
def get_auto_width(container: Size, parent: Size) -> int:
assert False, "must not be called"
def get_auto_height(container: Size, parent: Size) -> int:
assert False, "must not be called"
box_model = get_box_model(
styles, Size(40, 30), Size(80, 24), get_auto_width, get_auto_height
)
assert box_model == BoxModel(Size(40, 30), Spacing(0, 0, 0, 0))