Files
rose-ash/blog/tests/test_lexical_to_sx.py
giles b0920a1121 Rename all 1,169 components to path-based names with namespace support
Component names now reflect filesystem location using / as path separator
and : as namespace separator for shared components:
  ~sx-header → ~layouts/header
  ~layout-app-body → ~shared:layout/app-body
  ~blog-admin-dashboard → ~admin/dashboard

209 files, 4,941 replacements across all services.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:00:12 +00:00

295 lines
9.4 KiB
Python

"""Unit tests for the Lexical JSON → sx converter."""
from __future__ import annotations
import sys
import os
import pytest
# Add project root so shared.sx.html_to_sx resolves, plus the ghost dir.
_project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
sys.path.insert(0, _project_root)
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "bp", "blog", "ghost"))
from lexical_to_sx import lexical_to_sx
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _doc(*children):
"""Wrap children in a minimal Lexical document."""
return {"root": {"children": list(children)}}
def _text(s, fmt=0):
return {"type": "text", "text": s, "format": fmt}
def _paragraph(*children):
return {"type": "paragraph", "children": list(children)}
def _heading(tag, *children):
return {"type": "heading", "tag": tag, "children": list(children)}
def _link(url, *children):
return {"type": "link", "url": url, "children": list(children)}
# ---------------------------------------------------------------------------
# Basic text
# ---------------------------------------------------------------------------
class TestBasicText:
def test_empty_doc(self):
result = lexical_to_sx(_doc())
assert result == '(<> (p ""))'
def test_single_paragraph(self):
result = lexical_to_sx(_doc(_paragraph(_text("Hello"))))
assert result == '(p "Hello")'
def test_two_paragraphs(self):
result = lexical_to_sx(_doc(
_paragraph(_text("Hello")),
_paragraph(_text("World")),
))
assert "(p " in result
assert '"Hello"' in result
assert '"World"' in result
def test_heading(self):
result = lexical_to_sx(_doc(_heading("h2", _text("Title"))))
assert result == '(h2 "Title")'
def test_h3(self):
result = lexical_to_sx(_doc(_heading("h3", _text("Sub"))))
assert result == '(h3 "Sub")'
# ---------------------------------------------------------------------------
# Formatting
# ---------------------------------------------------------------------------
class TestFormatting:
def test_bold(self):
result = lexical_to_sx(_doc(_paragraph(_text("hi", 1))))
assert "(strong " in result
def test_italic(self):
result = lexical_to_sx(_doc(_paragraph(_text("hi", 2))))
assert "(em " in result
def test_strikethrough(self):
result = lexical_to_sx(_doc(_paragraph(_text("hi", 4))))
assert "(s " in result
def test_bold_italic(self):
result = lexical_to_sx(_doc(_paragraph(_text("hi", 3))))
assert "(strong " in result
assert "(em " in result
def test_code(self):
result = lexical_to_sx(_doc(_paragraph(_text("x", 16))))
assert "(code " in result
# ---------------------------------------------------------------------------
# Links
# ---------------------------------------------------------------------------
class TestLinks:
def test_link(self):
result = lexical_to_sx(_doc(
_paragraph(_link("https://example.com", _text("click")))
))
assert '(a :href "https://example.com"' in result
assert '"click"' in result
# ---------------------------------------------------------------------------
# Lists
# ---------------------------------------------------------------------------
class TestLists:
def test_unordered_list(self):
result = lexical_to_sx(_doc({
"type": "list", "listType": "bullet",
"children": [
{"type": "listitem", "children": [_text("one")]},
{"type": "listitem", "children": [_text("two")]},
]
}))
assert "(ul " in result
assert "(li " in result
assert '"one"' in result
def test_ordered_list(self):
result = lexical_to_sx(_doc({
"type": "list", "listType": "number",
"children": [
{"type": "listitem", "children": [_text("first")]},
]
}))
assert "(ol " in result
# ---------------------------------------------------------------------------
# Block elements
# ---------------------------------------------------------------------------
class TestBlocks:
def test_hr(self):
result = lexical_to_sx(_doc({"type": "horizontalrule"}))
assert result == "(hr)"
def test_quote(self):
result = lexical_to_sx(_doc({
"type": "quote", "children": [_text("wisdom")]
}))
assert '(blockquote "wisdom")' == result
def test_codeblock(self):
result = lexical_to_sx(_doc({
"type": "codeblock", "code": "print('hi')", "language": "python"
}))
assert '(pre (code :class "language-python"' in result
assert "print" in result
# ---------------------------------------------------------------------------
# Cards
# ---------------------------------------------------------------------------
class TestCards:
def test_image(self):
result = lexical_to_sx(_doc({
"type": "image", "src": "photo.jpg", "alt": "test"
}))
assert '(~kg_cards/kg-image :src "photo.jpg" :alt "test")' == result
def test_image_wide_with_caption(self):
result = lexical_to_sx(_doc({
"type": "image", "src": "p.jpg", "alt": "",
"cardWidth": "wide", "caption": "Fig 1"
}))
assert ':width "wide"' in result
assert ':caption "Fig 1"' in result
def test_image_html_caption(self):
result = lexical_to_sx(_doc({
"type": "image", "src": "p.jpg", "alt": "",
"caption": 'Photo by <a href="https://x.com">Author</a>'
}))
assert ':caption (<> "Photo by " (a :href "https://x.com" "Author"))' in result
def test_bookmark(self):
result = lexical_to_sx(_doc({
"type": "bookmark", "url": "https://example.com",
"metadata": {"title": "Example", "description": "A site"}
}))
assert "(~kg_cards/kg-bookmark " in result
assert ':url "https://example.com"' in result
assert ':title "Example"' in result
def test_callout(self):
result = lexical_to_sx(_doc({
"type": "callout", "backgroundColor": "blue",
"calloutEmoji": "💡",
"children": [_text("Note")]
}))
assert "(~kg_cards/kg-callout " in result
assert ':color "blue"' in result
def test_button(self):
result = lexical_to_sx(_doc({
"type": "button", "buttonText": "Click",
"buttonUrl": "https://example.com"
}))
assert "(~kg_cards/kg-button " in result
assert ':text "Click"' in result
def test_toggle(self):
result = lexical_to_sx(_doc({
"type": "toggle", "heading": "FAQ",
"children": [_text("Answer")]
}))
assert "(~kg_cards/kg-toggle " in result
assert ':heading "FAQ"' in result
def test_html(self):
result = lexical_to_sx(_doc({
"type": "html", "html": "<div>custom</div>"
}))
assert result == '(~kg_cards/kg-html (div "custom"))'
def test_embed(self):
result = lexical_to_sx(_doc({
"type": "embed", "html": "<iframe></iframe>",
"caption": "Video"
}))
assert "(~kg_cards/kg-embed " in result
assert ':caption "Video"' in result
def test_markdown(self):
result = lexical_to_sx(_doc({
"type": "markdown", "markdown": "**bold** text"
}))
assert result.startswith("(~kg_cards/kg-md ")
assert "(p " in result
assert "(strong " in result
def test_video(self):
result = lexical_to_sx(_doc({
"type": "video", "src": "v.mp4", "cardWidth": "wide"
}))
assert "(~kg_cards/kg-video " in result
assert ':width "wide"' in result
def test_audio(self):
result = lexical_to_sx(_doc({
"type": "audio", "src": "s.mp3", "title": "Song", "duration": 195
}))
assert "(~kg_cards/kg-audio " in result
assert ':duration "3:15"' in result
def test_file(self):
result = lexical_to_sx(_doc({
"type": "file", "src": "f.pdf", "fileName": "doc.pdf",
"fileSize": 2100000
}))
assert "(~kg_cards/kg-file " in result
assert ':filename "doc.pdf"' in result
assert "MB" in result
def test_paywall(self):
result = lexical_to_sx(_doc({"type": "paywall"}))
assert result == "(~kg_cards/kg-paywall)"
# ---------------------------------------------------------------------------
# Escaping
# ---------------------------------------------------------------------------
class TestEscaping:
def test_quotes_in_text(self):
result = lexical_to_sx(_doc(_paragraph(_text('He said "hello"'))))
assert '\\"hello\\"' in result
def test_backslash_in_text(self):
result = lexical_to_sx(_doc(_paragraph(_text("a\\b"))))
assert "a\\\\b" in result
# ---------------------------------------------------------------------------
# JSON string input
# ---------------------------------------------------------------------------
class TestJsonString:
def test_string_input(self):
import json
doc = _doc(_paragraph(_text("test")))
result = lexical_to_sx(json.dumps(doc))
assert '(p "test")' == result