import unittest from publication_meta import ( clean, mark_blocked, mark_published, mark_publishing, parse_meta, same_meta, ) PENDING = "anwarpy: status=pending | access=vip | category=أدوات | queued_at=2026-10-09T15:12:00+03:00" class PublicationMetaTests(unittest.TestCase): def test_parses_pending_and_normalizes_formatting_controls(self): raw = "\ufeffanwarpy:\u00a0status=pending | access=vip | category=أدوات | queued_at=2026-10-09T15:12:00+03:00\u200f" meta = parse_meta(raw) self.assertEqual(meta["status"], "pending") self.assertEqual(meta["category"], "أدوات") def test_rejects_invalid_values_and_dates(self): for raw in ( PENDING.replace("access=vip", "access=paid"), PENDING.replace("category=أدوات", "category=عام"), PENDING.replace("2026-10-09", "2026-13-45"), PENDING.replace("+03:00", ""), ): with self.subTest(raw=raw): with self.assertRaises(ValueError): parse_meta(raw) def test_rejects_invalid_state_shapes(self): with self.assertRaisesRegex(ValueError, "slug"): parse_meta(PENDING.replace("status=pending", "status=publishing")) with self.assertRaisesRegex(ValueError, "blocked_reason"): parse_meta(PENDING.replace("status=pending", "status=blocked")) with self.assertRaisesRegex(ValueError, "not allowed"): parse_meta(PENDING + " | url=https://anwarpy.ai/posts/example") def test_transitions_reparse_raw_input(self): publishing = mark_publishing(PENDING, "arabic-ai-guide") self.assertEqual(parse_meta(publishing)["status"], "publishing") published = mark_published( publishing, "2026-10-09T12:20:11+00:00", "https://anwarpy.ai/posts/arabic-ai-guide", ) self.assertEqual(parse_meta(published)["status"], "published") def test_blocked_is_terminal_and_carries_a_bounded_reason(self): blocked = mark_blocked(PENDING, "cover") self.assertEqual(parse_meta(blocked)["blocked_reason"], "cover") with self.assertRaises(ValueError): mark_blocked(PENDING, "network") def test_canonical_url_and_slug_are_exact(self): publishing = mark_publishing(PENDING, "arabic-ai-guide") for url in ( "http://anwarpy.ai/posts/arabic-ai-guide", "https://www.anwarpy.ai/posts/arabic-ai-guide", "https://anwarpy.ai/posts/arabic-ai-guide/", "https://anwarpy.ai/posts/other", ): with self.subTest(url=url): with self.assertRaises(ValueError): mark_published(publishing, "2026-10-09T15:20:11+03:00", url) with self.assertRaises(ValueError): mark_publishing(PENDING, "عنوان-عربي") def test_readback_comparison_is_semantic_after_cleaning(self): formatted = "\u200fanwarpy: status=pending|access=vip|category=أدوات|queued_at=2026-10-09T15:12:00+03:00" self.assertTrue(same_meta(PENDING, formatted)) self.assertEqual(clean("\ufeff أداة\u00a0"), "أداة") if __name__ == "__main__": unittest.main()