FIX 1: _content_has_local_images and extract_local_images now skip lines inside ``` fences so a local-image ref inside a code block is not treated as real. FIX 2: md_translate.translate() tracks fence state; callout/columns/mention transforms are suppressed for lines inside ``` ... ``` blocks (pass verbatim). FIX 3: main() catches NtnUploadError and prints a clean error + e.stderr before sys.exit(1); body moved to _main_body(parser, args). FIX 4: ntn_files.upload() raises NtnUploadError on empty stdout instead of IndexError, giving a clean message combined with FIX 3. FIX 5: Removed unused write_to_page() (both page paths are inlined). FIX 6: create_page_markdown() omits the 'markdown' key when value is falsy, avoiding empty-markdown sends on DB rows created without --file/--stdin. FIX 7: CLAUDE.md documents --allow-deleting-content scope (markdown engine only). TDD: Added test_fence_passthrough_no_transform (md_translate, suite now 8) and test_local_image_inside_fence_ignored (engine_routing, suite now 6). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
98 lines
3.4 KiB
Python
98 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Tests for markdown transport helpers — run with `python test_engine_routing.py`."""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
|
|
import _notion_compat as compat
|
|
import notion_writer
|
|
|
|
|
|
def _fake_client():
|
|
c = mock.MagicMock()
|
|
c.request.return_value = {"object": "page", "id": "p1"}
|
|
return c
|
|
|
|
|
|
def test_create_page_markdown():
|
|
c = _fake_client()
|
|
parent = {"type": "data_source_id", "data_source_id": "ds1"}
|
|
compat.create_page_markdown(c, parent, {"Name": {"title": []}}, "# Hi")
|
|
_, kwargs = c.request.call_args
|
|
assert kwargs["path"] == "pages"
|
|
assert kwargs["method"] == "POST"
|
|
assert kwargs["body"]["markdown"] == "# Hi"
|
|
assert kwargs["body"]["parent"] == parent
|
|
|
|
|
|
def test_append_markdown():
|
|
c = _fake_client()
|
|
compat.append_markdown(c, "page-123", "## More")
|
|
_, kwargs = c.request.call_args
|
|
assert kwargs["path"] == "pages/page-123/markdown"
|
|
assert kwargs["method"] == "PATCH"
|
|
assert kwargs["body"]["type"] == "insert_content"
|
|
assert kwargs["body"]["insert_content"]["content"] == "## More"
|
|
assert kwargs["body"]["insert_content"]["position"] == {"type": "end"}
|
|
|
|
|
|
def test_replace_markdown():
|
|
c = _fake_client()
|
|
compat.replace_markdown(c, "page-123", "# Fresh", allow_deleting=True)
|
|
_, kwargs = c.request.call_args
|
|
assert kwargs["path"] == "pages/page-123/markdown"
|
|
assert kwargs["body"]["type"] == "replace_content"
|
|
assert kwargs["body"]["replace_content"]["new_str"] == "# Fresh"
|
|
assert kwargs["body"]["replace_content"]["allow_deleting_content"] is True
|
|
|
|
|
|
def test_extract_local_images_splits():
|
|
content = ("# Title\n\n\n\n"
|
|
"\n\nbody")
|
|
without, imgs = notion_writer.extract_local_images(content)
|
|
assert imgs == [("local", "./b.png")]
|
|
assert "" not in without
|
|
assert "" in without # remote stays
|
|
|
|
|
|
def test_content_has_local_images():
|
|
assert notion_writer._content_has_local_images("") is True
|
|
assert notion_writer._content_has_local_images("") is False
|
|
assert notion_writer._content_has_local_images("no images") is False
|
|
|
|
|
|
def test_local_image_inside_fence_ignored():
|
|
"""A local image reference inside a fenced code block must NOT be detected
|
|
as a real image by _content_has_local_images or extracted by extract_local_images."""
|
|
fenced = "```markdown\n\n```"
|
|
assert notion_writer._content_has_local_images(fenced) is False, \
|
|
"_content_has_local_images should return False for image inside fence"
|
|
without, imgs = notion_writer.extract_local_images(fenced)
|
|
assert len(imgs) == 0, "extract_local_images should not extract image inside fence"
|
|
# The fenced lines (including the image line) should be preserved verbatim
|
|
assert "" in without, "fence content must be preserved in output"
|
|
|
|
|
|
def run_all():
|
|
tests = [
|
|
test_create_page_markdown,
|
|
test_append_markdown,
|
|
test_replace_markdown,
|
|
test_extract_local_images_splits,
|
|
test_content_has_local_images,
|
|
test_local_image_inside_fence_ignored,
|
|
]
|
|
for t in tests:
|
|
print(f"\n{t.__name__}")
|
|
t()
|
|
print("\n" + "=" * 50)
|
|
print(f"✅ All {len(tests)} tests passed")
|
|
print("=" * 50)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run_all()
|