"""Tests for the pure XML tree utilities (mgf.vm.core.common.xml).

These assert the construct/manipulate/serialize surface. There is
deliberately no parse function to test — parsing untrusted XML is an
adapter concern (defusedxml), not core's.
"""

from __future__ import annotations

import xml.etree.ElementTree as ET

import pytest

from mgf.vm.core.common.xml import (
    XmlElement,
    find_first,
    require_child,
    serialize,
)


def _tree() -> ET.Element:
    root = ET.Element("domain")
    name = ET.SubElement(root, "name")
    name.text = "vm1"
    devices = ET.SubElement(root, "devices")
    ET.SubElement(devices, "disk")
    return root


def test_xml_element_is_the_stdlib_element_type() -> None:
    assert XmlElement is ET.Element


def test_serialize_returns_str_by_default() -> None:
    out = serialize(ET.Element("name"))
    assert isinstance(out, str)
    assert out == "<name />"


def test_serialize_roundtrips_content() -> None:
    out = serialize(_tree())
    assert "<name>vm1</name>" in out
    assert "<disk />" in out


def test_serialize_bytes_with_real_encoding() -> None:
    out = serialize(ET.Element("x"), encoding="utf-8")
    assert isinstance(out, bytes)
    assert b"<x />" in out


def test_find_first_hit_and_miss() -> None:
    root = _tree()
    assert find_first(root, "name") is not None
    assert find_first(root, "name").text == "vm1"  # type: ignore[union-attr]
    assert find_first(root, "nonexistent") is None


def test_require_child_returns_element() -> None:
    root = _tree()
    el = require_child(root, "devices")
    assert el.tag == "devices"


def test_require_child_raises_keyerror_when_absent() -> None:
    with pytest.raises(KeyError, match="missing"):
        require_child(_tree(), "missing")
