This commit is contained in:
@@ -54,11 +54,11 @@ class ArticleEditorTests(unittest.TestCase):
|
||||
values.update(overrides)
|
||||
return values
|
||||
|
||||
def test_current_site_article_records_and_controlled_tags_load(self) -> None:
|
||||
def test_current_site_article_records_and_tracked_tags_load(self) -> None:
|
||||
repository = ArticleRepository(Path(__file__).resolve().parents[1])
|
||||
entries = repository.list_entries()
|
||||
self.assertGreaterEqual(len(entries), 7)
|
||||
self.assertGreaterEqual(len(repository.tags), 45)
|
||||
self.assertGreaterEqual(len(repository.tags), 40)
|
||||
self.assertTrue(all(entry.document.get("kicker") == "Article" for entry in entries))
|
||||
for entry in entries:
|
||||
with self.subTest(slug=entry.slug):
|
||||
@@ -126,9 +126,23 @@ class ArticleEditorTests(unittest.TestCase):
|
||||
self.repository.delete_entry(entry)
|
||||
self.assertTrue(entry.path.is_file())
|
||||
|
||||
def test_unapproved_tag_is_rejected(self) -> None:
|
||||
with self.assertRaisesRegex(ArticleEditorError, "unapproved tag"):
|
||||
self.repository.create_entry("test-entry", self.values(tags="invented"))
|
||||
def test_freeform_tags_are_normalized_deduplicated_and_do_not_create_records(self) -> None:
|
||||
entry = self.repository.create_entry(
|
||||
"test-entry", self.values(tags="writing, Weird Experiment, weird-experiment")
|
||||
)
|
||||
|
||||
self.assertEqual(entry.document.get("tags"), "writing, weird-experiment")
|
||||
self.assertFalse((self.site_root / "content" / "tags" / "weird-experiment").exists())
|
||||
|
||||
def test_loading_and_saving_preserves_tracked_and_freeform_tags(self) -> None:
|
||||
entry = self.repository.create_entry(
|
||||
"test-entry", self.values(tags="writing, retrocomputing")
|
||||
)
|
||||
values = self.repository.values_for(entry.document)
|
||||
values["summary"] = "Edited without changing tags."
|
||||
saved = self.repository.save_entry(entry, values)
|
||||
|
||||
self.assertEqual(saved.document.get("tags"), "writing, retrocomputing")
|
||||
|
||||
def test_cover_image_is_copied_renamed_referenced_and_reopened(self) -> None:
|
||||
entry = self.repository.create_entry("test-entry", self.values())
|
||||
|
||||
@@ -54,11 +54,11 @@ class BlogEditorTests(unittest.TestCase):
|
||||
values.update(overrides)
|
||||
return values
|
||||
|
||||
def test_current_site_blog_records_and_controlled_tags_load(self) -> None:
|
||||
def test_current_site_blog_records_and_tracked_tags_load(self) -> None:
|
||||
repository = BlogRepository(Path(__file__).resolve().parents[1])
|
||||
entries = repository.list_entries()
|
||||
self.assertGreaterEqual(len(entries), 7)
|
||||
self.assertGreaterEqual(len(repository.tags), 45)
|
||||
self.assertGreaterEqual(len(repository.tags), 40)
|
||||
self.assertTrue(all(entry.document.get("kicker") == "Blog" for entry in entries))
|
||||
for entry in entries:
|
||||
with self.subTest(slug=entry.slug):
|
||||
@@ -126,9 +126,23 @@ class BlogEditorTests(unittest.TestCase):
|
||||
self.repository.delete_entry(entry)
|
||||
self.assertTrue(entry.path.is_file())
|
||||
|
||||
def test_unapproved_tag_is_rejected(self) -> None:
|
||||
with self.assertRaisesRegex(BlogEditorError, "unapproved tag"):
|
||||
self.repository.create_entry("test-entry", self.values(tags="invented"))
|
||||
def test_freeform_tags_are_normalized_deduplicated_and_do_not_create_records(self) -> None:
|
||||
entry = self.repository.create_entry(
|
||||
"test-entry", self.values(tags="writing, Weird Experiment, weird-experiment")
|
||||
)
|
||||
|
||||
self.assertEqual(entry.document.get("tags"), "writing, weird-experiment")
|
||||
self.assertFalse((self.site_root / "content" / "tags" / "weird-experiment").exists())
|
||||
|
||||
def test_loading_and_saving_preserves_tracked_and_freeform_tags(self) -> None:
|
||||
entry = self.repository.create_entry(
|
||||
"test-entry", self.values(tags="writing, retrocomputing")
|
||||
)
|
||||
values = self.repository.values_for(entry.document)
|
||||
values["summary"] = "Edited without changing tags."
|
||||
saved = self.repository.save_entry(entry, values)
|
||||
|
||||
self.assertEqual(saved.document.get("tags"), "writing, retrocomputing")
|
||||
|
||||
def test_slug_suggestion_matches_repository_style(self) -> None:
|
||||
self.assertEqual(suggest_slug("We’re Testing: A GUI!"), "were-testing-a-gui")
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
import unittest
|
||||
import uuid
|
||||
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
|
||||
|
||||
from tag_editor import TagEditorError, TagRepository, suggest_slug # noqa: E402
|
||||
|
||||
|
||||
class TagEditorTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
cache_root = Path(__file__).resolve().parents[1] / ".cache"
|
||||
cache_root.mkdir(exist_ok=True)
|
||||
self.site_root = cache_root / f"tag-editor-test-{uuid.uuid4().hex}"
|
||||
(self.site_root / "content" / "tags" / "writing").mkdir(parents=True)
|
||||
(self.site_root / "content" / "blog" / "existing-entry").mkdir(parents=True)
|
||||
(self.site_root / "models").mkdir()
|
||||
(self.site_root / "Test.lektorproject").write_text(
|
||||
"[project]\nname = Test\n", encoding="utf-8"
|
||||
)
|
||||
(self.site_root / "content" / "tags" / "contents.lr").write_text(
|
||||
"_model: tag-index\n---\ntitle: Tags\n", encoding="utf-8"
|
||||
)
|
||||
(self.site_root / "content" / "tags" / "writing" / "contents.lr").write_text(
|
||||
"_model: tag\n---\ntitle: Writing\n---\nsummary: Writing and editing.\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
self.entry_path = (
|
||||
self.site_root / "content" / "blog" / "existing-entry" / "contents.lr"
|
||||
)
|
||||
self.entry_path.write_text(
|
||||
"_model: entry\n---\ntitle: Existing\n---\ntags: writing, retrocomputing\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
shutil.copy2(
|
||||
Path(__file__).resolve().parents[1] / "models" / "tag.ini",
|
||||
self.site_root / "models" / "tag.ini",
|
||||
)
|
||||
self.repository = TagRepository(self.site_root)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
shutil.rmtree(self.site_root)
|
||||
|
||||
def test_current_tracked_tag_records_load(self) -> None:
|
||||
repository = TagRepository(Path(__file__).resolve().parents[1])
|
||||
tags = repository.list_tags()
|
||||
self.assertGreaterEqual(len(tags), 40)
|
||||
self.assertTrue(all(tag.title and tag.summary for tag in tags))
|
||||
|
||||
def test_create_tracks_slug_without_rewriting_existing_content(self) -> None:
|
||||
before = self.entry_path.read_bytes()
|
||||
|
||||
tag = self.repository.create_tag(
|
||||
"retrocomputing", "Retrocomputing", "Older computers and their software."
|
||||
)
|
||||
|
||||
self.assertEqual(tag.slug, "retrocomputing")
|
||||
self.assertEqual(self.entry_path.read_bytes(), before)
|
||||
self.assertIn("_model: tag\n---\ntitle: Retrocomputing\n", tag.original_text)
|
||||
with self.assertRaisesRegex(TagEditorError, "already exists"):
|
||||
self.repository.create_tag("retrocomputing", "Duplicate", "Duplicate summary.")
|
||||
|
||||
def test_edit_preserves_slug_and_unknown_fields(self) -> None:
|
||||
path = self.site_root / "content" / "tags" / "writing" / "contents.lr"
|
||||
text = path.read_text(encoding="utf-8").replace(
|
||||
"---\nsummary:", "---\neditor_note: preserve me\n---\nsummary:"
|
||||
)
|
||||
path.write_text(text, encoding="utf-8")
|
||||
tag = self.repository.load_tag("writing")
|
||||
|
||||
saved = self.repository.save_tag(tag, "Writing & Editing", "An updated summary.")
|
||||
|
||||
self.assertEqual(saved.slug, "writing")
|
||||
self.assertIn("editor_note: preserve me", saved.original_text)
|
||||
self.assertIn("title: Writing & Editing", saved.original_text)
|
||||
|
||||
def test_edit_detects_external_change(self) -> None:
|
||||
tag = self.repository.load_tag("writing")
|
||||
with tag.path.open("a", encoding="utf-8") as output:
|
||||
output.write("\n")
|
||||
with self.assertRaisesRegex(TagEditorError, "changed on disk"):
|
||||
self.repository.save_tag(tag, "Writing", "Changed summary.")
|
||||
|
||||
def test_untrack_removes_only_registry_record_and_keeps_entry_value(self) -> None:
|
||||
tag = self.repository.create_tag(
|
||||
"retrocomputing", "Retrocomputing", "Older computers and their software."
|
||||
)
|
||||
before = self.entry_path.read_bytes()
|
||||
|
||||
self.repository.untrack_tag(tag)
|
||||
|
||||
self.assertFalse(tag.path.parent.exists())
|
||||
self.assertEqual(self.entry_path.read_bytes(), before)
|
||||
self.assertIn("retrocomputing", self.entry_path.read_text(encoding="utf-8"))
|
||||
|
||||
def test_untrack_refuses_a_tag_directory_with_other_files(self) -> None:
|
||||
tag = self.repository.load_tag("writing")
|
||||
attachment = tag.path.parent / "unexpected.txt"
|
||||
attachment.write_text("keep", encoding="utf-8")
|
||||
|
||||
with self.assertRaisesRegex(TagEditorError, "files besides contents.lr"):
|
||||
self.repository.untrack_tag(tag)
|
||||
|
||||
self.assertTrue(tag.path.is_file())
|
||||
self.assertTrue(attachment.is_file())
|
||||
|
||||
def test_slug_validation_and_suggestion(self) -> None:
|
||||
self.assertEqual(suggest_slug("Retro Computing!"), "retro-computing")
|
||||
with self.assertRaisesRegex(TagEditorError, "lowercase"):
|
||||
self.repository.create_tag("Not Valid", "Invalid", "Invalid slug.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user