"""Unit tests for ``openbb_sec.utils.xml_render``."""
from lxml import etree
from openbb_sec.utils import xml_render
from openbb_sec.utils.xml_render import (
_humanize,
_is_leaf,
_is_record,
_kv_table,
_local,
_records_table,
_text,
is_asset_data_root,
render_xml_as_html,
)
def _elem(xml: str):
"""Parse an XML fragment into a single element."""
return etree.fromstring(xml.encode("utf-8"))
def _render(xml: str, **kwargs):
"""Render an XML string fragment as HTML."""
return render_xml_as_html(xml.encode("utf-8"), **kwargs)
class TestLocalAndHumanize:
"""The local-name and label-humanizing helpers."""
def test_local_strips_namespace(self):
assert _local("{http://ns}AssetData") == "AssetData"
assert _local("plain") == "plain"
def test_local_non_string_is_none(self):
assert _local(123) is None
assert _local(etree.Comment) is None
def test_humanize_camel_and_snake(self):
assert _humanize("assetNumber") == "Asset Number"
assert _humanize("reporting_period") == "Reporting period"
assert _humanize("") == ""
class TestStructurePredicates:
"""Leaf / record / asset-data-root predicates."""
def test_is_leaf_and_record(self):
record = _elem("12")
assert _is_record(record) is True
assert _is_leaf(record) is False
leaf = record[0]
assert _is_leaf(leaf) is True
assert _is_record(leaf) is False
def test_record_requires_all_children_leaves(self):
nested = _elem("1")
assert _is_record(nested) is False
def test_is_asset_data_root(self):
assert is_asset_data_root("assetData") is True
assert is_asset_data_root("{http://www.sec.gov/edgar/absee}foo") is True
assert is_asset_data_root("xbrl") is False
assert is_asset_data_root(123) is False
def test_text_trims_and_handles_empty(self):
assert _text(_elem(" hi ")) == "hi"
assert _text(_elem("")) == ""
class TestTableHelpers:
"""Direct rendering of record and key/value tables."""
def test_records_table_empty_members(self):
assert _records_table([]) == ""
def test_records_table_fills_missing_columns(self):
members = [
_elem("12"),
_elem("34"),
]
html = _records_table(members)
assert "
A | " in html
assert "B | " in html
assert "C | " in html
# The first record has no ``c`` and the second no ``b`` -> blank cells.
assert html.count(" | ") == 2
def test_kv_table(self):
html = _kv_table([("assetNumber", "1"), ("balance", "2")])
assert "Asset Number | " in html
assert "1 | " in html
class TestRenderAssetData:
"""Rendering ABS-EE asset-data documents as record tables."""
def test_renders_records_as_table(self):
html = _render(
""
"1100"
"2200"
""
)
assert html is not None
assert "Asset Data
" in html
assert "ob-tbl" in html
assert "Asset Number" in html
assert "100 | " in html
def test_simple_table_for_repeated_leaves(self):
html = _render("ab")
assert "Note
" in html
assert "a | " in html
assert "b | " in html
def test_single_leaf_renders_key_value(self):
html = _render("auto")
assert "ob-kv" in html
assert "auto | " in html
def test_nested_elements_recurse(self):
html = _render(
"v"
)
assert "Wrapper
" in html
assert "Inner
" in html
assert "v | " in html
def test_leaf_tail_text_renders_as_mapped_text_item(self):
html = _render(
""
"assetTypeNumber"
""
""
)
assert "ob-kv" in html
assert "Asset Type Number | " in html
assert "Asset Number Type - HCA indicates Hyundai Capital America." in html
def test_leaf_tail_only_uses_element_name_as_key(self):
html = _render(
""
""
""
""
)
assert "ob-kv" in html
assert "New Ex103tag1 | " in html
assert "Asset Number Type - HCA indicates Hyundai Capital America." in html
def test_mixed_group_recurses_each_member(self):
html = _render("1plain")
assert html.count("M
") == 2
def test_truncates_records_over_max_rows(self, monkeypatch):
monkeypatch.setattr(xml_render, "MAX_ROWS", 1)
html = _render(
"12"
)
assert "Showing the first 1 of 2 records." in html
class TestRenderComments:
"""Rendering document-level comment legends."""
def test_comments_legend_open_when_no_table(self):
html = _render(
"- value
"
)
assert "Document notes (2)" in html
assert "ob-note open" in html
assert "First note" in html
assert "Second note" in html
def test_comments_legend_collapsed_when_table_present(self):
html = _render(
""
"12"
)
assert "Document notes (1)" in html
assert "ob-note open" not in html
def test_nested_comment_is_rendered(self):
html = _render(
"- value
"
)
assert "inline note" in html
class TestRenderPreviewAndGuards:
"""Truncation previews and the not-renderable guard paths."""
def test_truncated_with_source_url_links_full_document(self):
html = _render(
"12",
source_url="https://www.sec.gov/a.xml",
truncated=True,
)
assert "open the full document" in html
assert "https://www.sec.gov/a.xml" in html
def test_truncated_without_source_url(self):
html = _render(
"12",
truncated=True,
)
assert "Showing a preview of a large file." in html
assert "1") is None
def test_empty_document_returns_none(self):
assert _render("") is None