|
| 1 | +"""Structural API contract tests. |
| 2 | +
|
| 3 | +These tests assert invariants about the library's surface — method coverage, |
| 4 | +class relationships, etc. — rather than testing runtime behaviour. |
| 5 | +""" |
| 6 | + |
| 7 | +from __future__ import annotations |
| 8 | + |
| 9 | +import inspect |
| 10 | + |
| 11 | +from yamltrip.document import Document |
| 12 | +from yamltrip.editor import Editor |
| 13 | + |
| 14 | +# Document methods that Editor intentionally does not expose: |
| 15 | +# dump / dumps — Editor owns the write path; callers don't call these directly. |
| 16 | +# has_anchors — read-only introspection, not a mutation. |
| 17 | +# query_pretty — read-only introspection, not a mutation. |
| 18 | +_DOCUMENT_ONLY = frozenset({"dump", "dumps", "has_anchors", "query_pretty"}) |
| 19 | + |
| 20 | + |
| 21 | +def _public_methods(cls: type) -> set[str]: |
| 22 | + return { |
| 23 | + name |
| 24 | + for name, _ in inspect.getmembers(cls, predicate=callable) |
| 25 | + if not name.startswith("_") |
| 26 | + } |
| 27 | + |
| 28 | + |
| 29 | +class TestEditorDocumentMethodCoverage: |
| 30 | + """Every public Document method must have a corresponding Editor wrapper, |
| 31 | + except for those explicitly listed in _DOCUMENT_ONLY.""" |
| 32 | + |
| 33 | + def test_editor_exposes_all_document_mutation_methods(self): |
| 34 | + doc_methods = _public_methods(Document) |
| 35 | + ed_methods = _public_methods(Editor) |
| 36 | + missing = (doc_methods - _DOCUMENT_ONLY) - ed_methods |
| 37 | + assert not missing, ( |
| 38 | + f"Editor is missing wrappers for Document methods: {sorted(missing)}\n" |
| 39 | + "Add the wrapper or add the method name to _DOCUMENT_ONLY if intentional." |
| 40 | + ) |
| 41 | + |
| 42 | + def test_document_only_set_is_accurate(self): |
| 43 | + """Fail if _DOCUMENT_ONLY names a method that Editor actually does expose, |
| 44 | + so the exclusion list doesn't silently become stale.""" |
| 45 | + ed_methods = _public_methods(Editor) |
| 46 | + stale = _DOCUMENT_ONLY & ed_methods |
| 47 | + assert not stale, ( |
| 48 | + f"_DOCUMENT_ONLY lists methods that Editor already exposes: {sorted(stale)}\n" |
| 49 | + "Remove them from _DOCUMENT_ONLY." |
| 50 | + ) |
0 commit comments