Files
textual/tests/test_strip.py
2025-09-07 10:58:56 +01:00

206 lines
5.8 KiB
Python

import pytest
from rich.console import Console
from rich.segment import Segment
from rich.style import Style
from textual._segment_tools import NoCellPositionForIndex
from textual.color import Color
from textual.filter import Monochrome
from textual.strip import Strip
def test_cell_length() -> None:
strip = Strip([Segment("foo"), Segment("💩"), Segment("bar")])
assert strip._cell_length is None
assert strip.cell_length == 8
assert strip._cell_length == 8
def test_repr() -> None:
strip = Strip([Segment("foo")])
assert repr(strip) == "Strip([Segment('foo')], 3)"
def test_join() -> None:
strip1 = Strip([Segment("foo")])
strip2 = Strip([Segment("bar")])
strip = Strip.join([strip1, strip2])
assert len(strip) == 2
assert strip.cell_length == 6
assert list(strip) == [Segment("foo"), Segment("bar")]
def test_bool() -> None:
assert not Strip([])
assert Strip([Segment("foo")])
def test_iter() -> None:
assert list(Strip([])) == []
assert list(Strip([Segment("foo")])) == [Segment("foo")]
assert list(Strip([Segment("foo"), Segment("bar")])) == [
Segment("foo"),
Segment("bar"),
]
def test_len():
assert len(Strip([])) == 0
assert len(Strip([Segment("foo")])) == 1
assert len(Strip([Segment("foo"), Segment("bar")])) == 2
def test_reversed():
assert list(reversed(Strip([]))) == []
assert list(reversed(Strip([Segment("foo")]))) == [Segment("foo")]
assert list(reversed(Strip([Segment("foo"), Segment("bar")]))) == [
Segment("bar"),
Segment("foo"),
]
def test_eq():
assert Strip([]) == Strip([])
assert Strip([Segment("foo")]) == Strip([Segment("foo")])
assert Strip([Segment("foo")]) != Strip([Segment("bar")])
def test_adjust_cell_length():
assert Strip([]).adjust_cell_length(3) == Strip([Segment(" ")])
assert Strip([Segment("f")]).adjust_cell_length(3) == Strip(
[Segment("f"), Segment(" ")]
)
assert Strip([Segment("💩")]).adjust_cell_length(3) == Strip(
[Segment("💩"), Segment(" ")]
)
assert Strip([Segment("💩💩")]).adjust_cell_length(3) == Strip([Segment("💩 ")])
assert Strip([Segment("💩💩")]).adjust_cell_length(4) == Strip([Segment("💩💩")])
assert Strip([Segment("💩"), Segment("💩💩")]).adjust_cell_length(2) == Strip(
[Segment("💩")]
)
assert Strip([Segment("💩"), Segment("💩💩")]).adjust_cell_length(4) == Strip(
[Segment("💩"), Segment("💩")]
)
def test_extend_cell_length():
strip = Strip([Segment("foo"), Segment("bar")])
assert strip.extend_cell_length(3).text == "foobar"
assert strip.extend_cell_length(6).text == "foobar"
assert strip.extend_cell_length(7).text == "foobar "
assert strip.extend_cell_length(9).text == "foobar "
def test_simplify():
assert Strip([Segment("foo"), Segment("bar")]).simplify() == Strip(
[Segment("foobar")]
)
def test_apply_filter():
strip = Strip([Segment("foo", Style.parse("red"))])
expected = Strip([Segment("foo", Style.parse("#1b1b1b"))])
assert strip.apply_filter(Monochrome(), Color(0, 0, 0)) == expected
def test_style_links():
link_style = Style.on(click="clicked")
strip = Strip(
[
Segment("foo"),
Segment("bar", link_style),
Segment("baz"),
]
)
hover_style = Style(underline=True)
new_strip = strip.style_links(link_style._link_id, hover_style)
expected = Strip(
[
Segment("foo"),
Segment("bar", link_style + hover_style),
Segment("baz"),
]
)
assert new_strip == expected
def test_crop():
assert Strip([Segment("foo")]).crop(0, 3) == Strip([Segment("foo")])
assert Strip([Segment("foo")]).crop(0, 2) == Strip([Segment("fo")])
assert Strip([Segment("foo")]).crop(0, 1) == Strip([Segment("f")])
assert Strip([Segment("foo")]).crop(1, 3) == Strip([Segment("oo")])
assert Strip([Segment("foo")]).crop(1, 2) == Strip([Segment("o")])
assert Strip([Segment("foo")]).crop(1, 1) == Strip([])
assert Strip([Segment("foo💩"), Segment("b💩ar"), Segment("ba💩z")]).crop(
1, 6
) == Strip([Segment("oo💩"), Segment("b")])
@pytest.mark.parametrize(
"text,crop,output",
[
["foo", (0, 5), [Segment("foo")]],
["foo", (2, 5), [Segment("o")]],
["foo", (3, 5), []],
["foo", (4, 6), []],
],
)
def test_crop_out_of_bounds(text, crop, output):
assert Strip([Segment(text)]).crop(*crop) == Strip(output)
def test_divide():
assert Strip([Segment("foo")]).divide([1, 2]) == [
Strip([Segment("f")]),
Strip([Segment("o")]),
]
@pytest.mark.parametrize(
"index,cell_position",
[
(0, 0),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 6),
(6, 8),
(7, 10),
(8, 11),
(9, 12),
(10, 13),
(11, 14),
],
)
def test_index_to_cell_position(index, cell_position):
strip = Strip([Segment("ab"), Segment("cd日本語ef"), Segment("gh")])
assert cell_position == strip.index_to_cell_position(index)
def test_index_cell_position_no_segments():
strip = Strip([])
with pytest.raises(NoCellPositionForIndex):
strip.index_to_cell_position(2)
def test_index_cell_position_index_too_large():
strip = Strip([Segment("abcdef"), Segment("ghi")])
with pytest.raises(NoCellPositionForIndex):
strip.index_to_cell_position(100)
def test_text():
assert Strip([]).text == ""
assert Strip([Segment("foo")]).text == "foo"
assert Strip([Segment("foo"), Segment("bar")]).text == "foobar"
def test_render_with_missing_style() -> None:
"""Test that render with segments that omit a style still work."""
strip = Strip([Segment("Hello")])
assert strip.render(Console()) == "Hello"