import unittest from django.template.exceptions import TemplateDoesNotExist from django.test import SimpleTestCase from django_courriel.md import MarkdownTemplate from django_courriel.validation import ( InvalidAddressError, InvalidFrontMatter, ValidAddress, ValidAddressList, ) class MarkdownTemplateTest(SimpleTestCase): def test_init_valid(self): """A valid markdown template initializes with metadata and markdown body.""" template = MarkdownTemplate("minimal.md") self.assertEqual(template.template_name, "minimal.md") self.assertIn("subject", template.metadata) self.assertEqual(template.metadata["subject"], "Hello") self.assertIn("Hello world !", template.md_body) def test_init_template_does_not_exist(self): """Instantiating with an unresolvable template raises TemplateDoesNotExist.""" with self.assertRaises(TemplateDoesNotExist): MarkdownTemplate("does_not_exist.md") def test_init_missing_front_matter(self): """A template without frontmatter delimiters raises InvalidFrontMatter.""" with self.assertRaises(InvalidFrontMatter): MarkdownTemplate("missing_front_matter.md") def test_init_invalid_front_matter(self): """A template with malformed frontmatter raises InvalidFrontMatter.""" with self.assertRaises(InvalidFrontMatter): MarkdownTemplate("invalid_front_matter.md") def test_init_missing_subject(self): """A template frontmatter without a 'subject' key raises InvalidFrontMatter.""" with self.assertRaises(InvalidFrontMatter) as ctx: MarkdownTemplate("missing_subject.md") self.assertIn("subject", str(ctx.exception).lower()) def test_from_email_none_when_omitted(self): """When from_email is not specified in frontmatter, getter returns None.""" template = MarkdownTemplate("minimal.md") self.assertIsNone(template.from_email) def test_from_email_valid(self): """When from_email is valid in frontmatter, getter returns a ValidAddress instance.""" template = MarkdownTemplate("valid_from_email.md") self.assertIsInstance(template.from_email, ValidAddress) self.assertEqual(template.from_email.display_name, "Victor Hugo") self.assertEqual(template.from_email.addr_spec, "hugo@les-miserables.fr") def test_from_email_invalid_raises_error(self): """When from_email is invalid in frontmatter, __init__ raises InvalidAddressError.""" with self.assertRaises(InvalidAddressError): MarkdownTemplate("invalid_from_email.md") def test_recipient_addresses_empty_when_omitted_or_empty(self): """When to, cc, bcc, reply_to are omitted or empty, getters return empty ValidAddressList instances.""" template = MarkdownTemplate("minimal.md") self.assertIsInstance(template.to, ValidAddressList) self.assertEqual(len(template.to), 0) self.assertIsInstance(template.cc, ValidAddressList) self.assertEqual(len(template.cc), 0) self.assertIsInstance(template.bcc, ValidAddressList) self.assertEqual(len(template.bcc), 0) self.assertIsInstance(template.reply_to, ValidAddressList) self.assertEqual(len(template.reply_to), 0) def test_recipient_addresses_valid(self): """When address lists or single addresses are defined, getters return ValidAddressList.""" template = MarkdownTemplate("valid_addresses.md") self.assertIsInstance(template.to, ValidAddressList) self.assertEqual(len(template.to), 2) self.assertEqual(template.to[0].display_name, "Victor Hugo") self.assertEqual(template.to[1].addr_spec, "antoine@saint-exupery.aero") self.assertIsInstance(template.cc, ValidAddressList) self.assertEqual(len(template.cc), 1) self.assertEqual(template.cc[0].addr_spec, "cesaire@cahiers.net") self.assertIsInstance(template.bcc, ValidAddressList) self.assertEqual(len(template.bcc), 1) self.assertEqual(template.bcc[0].addr_spec, "boris@vian.jazz") self.assertIsInstance(template.reply_to, ValidAddressList) self.assertEqual(len(template.reply_to), 1) self.assertEqual(template.reply_to[0].addr_spec, "contact@example.org") def test_recipient_addresses_invalid_raises_error(self): """When any recipient contains an invalid address, __init__ raises InvalidAddressError.""" with self.assertRaises(InvalidAddressError): MarkdownTemplate("invalid_recipient.md") @unittest.skip("Will be implemented in the rendering slice") def test_subject_rendering(self): raise NotImplementedError()