Files
rose-ash/blog/tests/test_lexical_validator.py
giles 3809affcab
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m11s
Test dashboard: full menu system, all-service tests, filtering
- Run tests for all 10 services via per-service pytest subprocesses
- Group results by service with section headers
- Clickable summary cards filter by outcome (passed/failed/errors/skipped)
- Service filter nav using ~nav-link buttons in menu bar
- Full menu integration: ~header-row + ~header-child + ~menu-row
- Show logo image via cart-mini rendering
- Mount full service directories in docker-compose for test access
- Add 24 unit test files across 9 services

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:54:25 +00:00

84 lines
2.6 KiB
Python

"""Unit tests for lexical document validator."""
from __future__ import annotations
import pytest
from blog.bp.blog.ghost.lexical_validator import (
validate_lexical, ALLOWED_NODE_TYPES,
)
class TestValidateLexical:
def test_valid_empty_doc(self):
ok, reason = validate_lexical({"root": {"type": "root", "children": []}})
assert ok is True
assert reason is None
def test_non_dict_input(self):
ok, reason = validate_lexical("not a dict")
assert ok is False
assert "JSON object" in reason
def test_list_input(self):
ok, reason = validate_lexical([])
assert ok is False
def test_missing_root(self):
ok, reason = validate_lexical({"foo": "bar"})
assert ok is False
assert "'root'" in reason
def test_root_not_dict(self):
ok, reason = validate_lexical({"root": "string"})
assert ok is False
def test_valid_paragraph(self):
doc = {"root": {"type": "root", "children": [
{"type": "paragraph", "children": [
{"type": "text", "text": "hello"}
]}
]}}
ok, _ = validate_lexical(doc)
assert ok is True
def test_disallowed_type(self):
doc = {"root": {"type": "root", "children": [
{"type": "script"}
]}}
ok, reason = validate_lexical(doc)
assert ok is False
assert "Disallowed node type: script" in reason
def test_nested_disallowed_type(self):
doc = {"root": {"type": "root", "children": [
{"type": "paragraph", "children": [
{"type": "list", "children": [
{"type": "evil-widget"}
]}
]}
]}}
ok, reason = validate_lexical(doc)
assert ok is False
assert "evil-widget" in reason
def test_node_without_type_allowed(self):
"""Nodes with type=None are allowed by _walk."""
doc = {"root": {"type": "root", "children": [
{"children": []} # no "type" key
]}}
ok, _ = validate_lexical(doc)
assert ok is True
def test_all_allowed_types(self):
"""Every type in the allowlist should pass."""
for node_type in ALLOWED_NODE_TYPES:
doc = {"root": {"type": "root", "children": [
{"type": node_type, "children": []}
]}}
ok, reason = validate_lexical(doc)
assert ok is True, f"{node_type} should be allowed but got: {reason}"
def test_allowed_types_count(self):
"""Sanity: at least 30 types in the allowlist."""
assert len(ALLOWED_NODE_TYPES) >= 30