from fractions import Fraction import pytest from textual._resolve import resolve, resolve_fraction_unit from textual.css.scalar import Scalar from textual.geometry import Size from textual.widget import Widget def test_resolve_empty(): assert resolve([], 10, 1, Size(20, 10), Size(80, 24)) == [] @pytest.mark.parametrize( "scalars,total,gutter,result", [ (["10"], 100, 0, [(0, 10)]), ( ["10", "20"], 100, 0, [(0, 10), (10, 20)], ), ( ["10", "20"], 100, 1, [(0, 10), (11, 20)], ), ( ["10", "1fr"], 100, 1, [(0, 10), (11, 89)], ), ( ["1fr", "1fr"], 100, 0, [(0, 50), (50, 50)], ), ( ["3", "1fr", "1fr", "1"], 100, 1, [(0, 3), (4, 46), (51, 47), (99, 1)], ), ], ) def test_resolve(scalars, total, gutter, result): assert ( resolve( [Scalar.parse(scalar) for scalar in scalars], total, gutter, Size(40, 20), Size(80, 24), ) == result ) async def test_resolve_fraction_unit(): """Test resolving fraction units in combination with minimum widths.""" widget1 = Widget() widget2 = Widget() widget3 = Widget() widget1.styles.width = "1fr" widget1.styles.min_width = 20 widget2.styles.width = "2fr" widget2.styles.min_width = 10 widget3.styles.width = "1fr" styles = (widget1.styles, widget2.styles, widget3.styles) # Try with width 80. # Fraction unit should one fourth of width assert resolve_fraction_unit( styles, Size(80, 24), Size(80, 24), Fraction(80), resolve_dimension="width", ) == Fraction(20) # Try with width 50 # First widget is fixed at 20 # Remaining three widgets have 30 to play with # Fraction is 10 assert resolve_fraction_unit( styles, Size(80, 24), Size(80, 24), Fraction(50), resolve_dimension="width", ) == Fraction(10) # Try with width 35 # First widget fixed at 20 # Fraction is 5 assert resolve_fraction_unit( styles, Size(80, 24), Size(80, 24), Fraction(35), resolve_dimension="width", ) == Fraction(5) # Try with width 32 # First widget fixed at 20 # Second widget is fixed at 10 # Remaining widget has all the space # Fraction is 2 assert resolve_fraction_unit( styles, Size(80, 24), Size(80, 24), Fraction(32), resolve_dimension="width", ) == Fraction(2) async def test_resolve_fraction_unit_stress_test(): """Check for zero division errors.""" # https://github.com/Textualize/textual/issues/2673 widget = Widget() styles = widget.styles styles.width = "1fr" # We're mainly checking for the absence of zero division errors, # which is a reoccurring theme for this code. for remaining_space in range(1, 51, 10): for max_width in range(1, remaining_space): styles.max_width = max_width for width in range(1, remaining_space, 2): size = Size(width, 24) resolved_unit = resolve_fraction_unit( [styles, styles, styles], size, size, Fraction(remaining_space), "width", ) assert resolved_unit <= remaining_space async def test_resolve_issue_2502(): """Test https://github.com/Textualize/textual/issues/2502""" widget = Widget() widget.styles.width = "1fr" widget.styles.min_width = 11 assert isinstance( resolve_fraction_unit( (widget.styles,), Size(80, 24), Size(80, 24), Fraction(10), resolve_dimension="width", ), Fraction, )