test: add _strip_html edge cases and config validation tests
strip_html: nested tags, malformed HTML, comments, entities. config: unknown key filtering, missing file, mixed valid/invalid.
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
"""Tests for configuration module."""
|
"""Tests for configuration module."""
|
||||||
|
|
||||||
from tuimble.config import AudioConfig, Config, PttConfig, ServerConfig
|
from tuimble.config import (
|
||||||
|
AudioConfig, Config, PttConfig, ServerConfig,
|
||||||
|
_load_section, load_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_default_config():
|
def test_default_config():
|
||||||
@@ -45,3 +48,47 @@ def test_server_cert_custom():
|
|||||||
srv = ServerConfig(certfile="/path/cert.pem", keyfile="/path/key.pem")
|
srv = ServerConfig(certfile="/path/cert.pem", keyfile="/path/key.pem")
|
||||||
assert srv.certfile == "/path/cert.pem"
|
assert srv.certfile == "/path/cert.pem"
|
||||||
assert srv.keyfile == "/path/key.pem"
|
assert srv.keyfile == "/path/key.pem"
|
||||||
|
|
||||||
|
|
||||||
|
# -- _load_section tests -----------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_section_filters_unknown_keys():
|
||||||
|
"""Unknown keys are silently dropped, valid keys are kept."""
|
||||||
|
result = _load_section(ServerConfig, {
|
||||||
|
"host": "example.com",
|
||||||
|
"typo_field": "oops",
|
||||||
|
"another_bad": 42,
|
||||||
|
})
|
||||||
|
assert result.host == "example.com"
|
||||||
|
assert result.port == 64738 # default preserved
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_section_empty_dict():
|
||||||
|
result = _load_section(PttConfig, {})
|
||||||
|
assert result.key == "f4"
|
||||||
|
assert result.mode == "toggle"
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_section_all_valid():
|
||||||
|
result = _load_section(PttConfig, {"key": "space", "mode": "hold"})
|
||||||
|
assert result.key == "space"
|
||||||
|
assert result.mode == "hold"
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_config_missing_file(tmp_path):
|
||||||
|
"""Missing config file returns defaults."""
|
||||||
|
cfg = load_config(tmp_path / "nonexistent.toml")
|
||||||
|
assert cfg.server.host == "localhost"
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_config_with_unknown_keys(tmp_path):
|
||||||
|
"""Config file with unknown keys loads without error."""
|
||||||
|
toml = tmp_path / "config.toml"
|
||||||
|
toml.write_text(
|
||||||
|
'[server]\nhost = "example.com"\nbogus = true\n'
|
||||||
|
'[ptt]\nfuture_option = "x"\n'
|
||||||
|
)
|
||||||
|
cfg = load_config(toml)
|
||||||
|
assert cfg.server.host == "example.com"
|
||||||
|
assert cfg.ptt.key == "f4" # default, not overwritten
|
||||||
|
|||||||
59
tests/test_strip_html.py
Normal file
59
tests/test_strip_html.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
"""Tests for _strip_html edge cases."""
|
||||||
|
|
||||||
|
from tuimble.app import _strip_html
|
||||||
|
|
||||||
|
|
||||||
|
def test_plain_text_unchanged():
|
||||||
|
assert _strip_html("hello world") == "hello world"
|
||||||
|
|
||||||
|
|
||||||
|
def test_simple_tags_stripped():
|
||||||
|
assert _strip_html("<b>bold</b>") == "bold"
|
||||||
|
|
||||||
|
|
||||||
|
def test_nested_tags():
|
||||||
|
assert _strip_html("<div><p>text</p></div>") == "text"
|
||||||
|
|
||||||
|
|
||||||
|
def test_self_closing_tags():
|
||||||
|
assert _strip_html("line<br/>break") == "linebreak"
|
||||||
|
|
||||||
|
|
||||||
|
def test_entities_unescaped():
|
||||||
|
assert _strip_html("& < >") == "& < >"
|
||||||
|
|
||||||
|
|
||||||
|
def test_html_entities_in_tags():
|
||||||
|
assert _strip_html("<b>&</b>") == "&"
|
||||||
|
|
||||||
|
|
||||||
|
def test_mumble_style_message():
|
||||||
|
"""Typical Mumble chat message with anchor tag."""
|
||||||
|
msg = '<a href="https://example.com">link text</a> and more'
|
||||||
|
assert _strip_html(msg) == "link text and more"
|
||||||
|
|
||||||
|
|
||||||
|
def test_img_tag_with_attributes():
|
||||||
|
assert _strip_html('before<img src="x.png" alt="pic"/>after') == "beforeafter"
|
||||||
|
|
||||||
|
|
||||||
|
def test_comment_stripped():
|
||||||
|
assert _strip_html("before<!-- comment -->after") == "beforeafter"
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_string():
|
||||||
|
assert _strip_html("") == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_only_tags():
|
||||||
|
assert _strip_html("<br><hr><img/>") == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_unclosed_tag():
|
||||||
|
"""Malformed HTML should not crash."""
|
||||||
|
result = _strip_html("<b>unclosed")
|
||||||
|
assert "unclosed" in result
|
||||||
|
|
||||||
|
|
||||||
|
def test_multiple_entities():
|
||||||
|
assert _strip_html(""quoted"") == '"quoted"'
|
||||||
Reference in New Issue
Block a user