diff --git a/CHANGELOG.md b/CHANGELOG.md index d3f838be7d..f16ac4dbe3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `SelectionList` option IDs are usable as soon as the widget is instantiated https://github.com/Textualize/textual/issues/3903 - Fix issue with `Strip.crop` when crop window start aligned with strip end https://github.com/Textualize/textual/pull/3998 - Fixed Strip.crop_extend https://github.com/Textualize/textual/pull/4011 +- Widgets could be created with IDs that you couldn't query back https://github.com/Textualize/textual/issues/3954 ## [0.47.1] - 2023-01-05 diff --git a/tests/css/test_parse.py b/tests/css/test_parse.py index febe4f06bb..2d6aeef002 100644 --- a/tests/css/test_parse.py +++ b/tests/css/test_parse.py @@ -3,8 +3,8 @@ import pytest from textual.color import Color -from textual.css.errors import UnresolvedVariableError -from textual.css.parse import substitute_references +from textual.css.errors import InvalidIDError, UnresolvedVariableError +from textual.css.parse import substitute_references, validate_identifier from textual.css.scalar import Scalar, Unit from textual.css.stylesheet import Stylesheet, StylesheetParseError from textual.css.tokenize import tokenize @@ -1272,3 +1272,40 @@ def test_parse_bad_pseudo_selector_with_suggestion(): stylesheet.parse() assert error.value.start == (2, 7) + + +@pytest.mark.parametrize( + "identifier", + [ + "the", + "quick", + "brown", + "f0x", + "jump5", + "ov3r", + "_the__", + "l4zy_", + "_d0g", + ], +) +def test_identifier_validation_passes(identifier: str): + assert validate_identifier(identifier) == identifier + + +@pytest.mark.parametrize( + "identifier", + [ + " the", + "quick ", + "bro wn", + "f0x&", + "+jump5", + "0v3r", + "—the", + "läzy_", + "_d0g!", + ], +) +def test_identifier_validation_fails(identifier: str): + with pytest.raises(InvalidIDError): + validate_identifier(identifier) diff --git a/tests/test_dom.py b/tests/test_dom.py index 6f06fb8091..d4dc4336dd 100644 --- a/tests/test_dom.py +++ b/tests/test_dom.py @@ -1,6 +1,6 @@ import pytest -from textual.css.errors import StyleValueError +from textual.css.errors import InvalidIDError, StyleValueError from textual.dom import BadIdentifier, DOMNode @@ -259,3 +259,24 @@ def test_walk_children_with_self_breadth(search): ] assert children == ["f", "e", "d", "c", "b", "a"] + + +@pytest.mark.parametrize( + "identifier", + [ + " bad", + " terrible ", + "worse! ", + "&ersand", + "amper&sand", + "ampersand&", + "2_leading_digits", + "água", # water + "cão", # dog + "@'/.23", + ], +) +def test_id_validation(identifier: str): + """Regression test for https://github.com/Textualize/textual/issues/3954.""" + with pytest.raises(InvalidIDError): + DOMNode(id=identifier)