<NME> tests.py
<BEF> """App related tests."""

from django.test import SimpleTestCase

from . import lib


from modoboa.admin import models as admin_models
from modoboa.lib.tests import ModoTestCase

from . import factories
from . import lib


BAD_SPF_RECORDS = [
    ("a mx ~all", "Not an SPF record"),
    ("v=spf1 toto ~all", "Unknown mechanism toto"),
    ("v=spf1 ip4 -all", "Wrong ip4 mechanism syntax"),
    ("v=spf1 +ip4:1.1.1. +all", "Wrong IPv4 address format"),
    ("v=spf1 ip6 ~all", "Wrong ip6 mechanism syntax"),
    ("v=spf1 +ip6:x:: +all", "Wrong IPv6 address format"),
    ("v=spf1 a|domain.com ~all", "Invalid syntax for a mechanism"),
    ("v=spf1 a:domain.com/TOTO", "Invalid mask found TOTO"),
    ("v=spf1 a/1000", "Invalid mask found 1000"),
    ("v=spf1 mx:domain.com/TOTO", "Invalid mask found TOTO"),
    ("v=spf1 mx/1000", "Invalid mask found 1000"),
    ("v=spf1 ptr|test.com", "Invalid syntax for ptr mechanism"),
    "v=spf1 mx",
    "v=spf1 a ~all",
    "v=spf1 ip4:1.2.3.4 -all",
    # "v=spf1 ip4:1.2.3.4/16 -all",
    "v=spf1 ip6:fe80::9eb6:d0ff:fe8e:2807 -all",
    # "v=spf1 ip6:fe80::9eb6:d0ff:fe8e:2807/64 -all",
    "v=spf1 a -all",
    "v=spf1 a:example.com -all",
    "v=spf1 a:mailers.example.com -all",
    "v=spf1 ip4:1.2.3.4 -all",
    "v=spf1 ip4:1.2.3.4/16 -all",
    "v=spf1 ip6:fe80::9eb6:d0ff:fe8e:2807 -all",
    "v=spf1 ip6:fe80::9eb6:d0ff:fe8e:2807/64 -all",
    "v=spf1 a -all",
    "v=spf1 a:example.com -all",
    "v=spf1 a:mailers.example.com -all",
    "v=spf1 a/24 a:offsite.example.com/24 -all",
    "v=spf1 mx mx:deferrals.domain.com -all",
    "v=spf1 mx/24 mx:offsite.domain.com/24 -all",
    "v=spf1 ptr -all",
    "v=spf1 ptr:otherdomain.com -all",
    "v=spf1 exists:example.com -all",
    "v=spf1 include:example.com  -all",
    "v=spf1 ?include:example.com -all",
    "v=spf1 redirect=example.com",
    "v=spf1 exp=example.com",
]

BAD_DMARC_RECORDS = [
    ("", "Not a valid DMARC record"),
    ("v=DMARC1; test", "Invalid tag test"),
    ("v=DMARC1; test=toto", "Unknown tag test"),
    ("v=DMARC1; adkim=g", "Wrong value g for tag adkim"),
    ("v=DMARC1; rua=mail:toto@test.com",
     "Wrong value mail:toto@test.com for tag rua"),
    ("v=DMARC1; rf=afrf,toto", "Wrong value toto for tag rf"),
    ("v=DMARC1; ri=XXX", "Wrong value XXX for tag ri: not an integer"),
    ("v=DMARC1; pct=-1", "Wrong value -1 for tag pct: less than 0"),
    ("v=DMARC1; pct=1000", "Wrong value 1000 for tag pct: greater than 100"),
    ("v=DMARC1; pct=100", "Missing required p tag"),
]

GOOD_DMARC_RECORDS = [
    "v=DMARC1; p=reject;; pct=100",
    "v=DMARC1; p=quarantine; sp=none; adkim=s; aspf=s; "
    "rua=mailto:dmarc-aggrep@ngyn.org; ruf=mailto:toto@test.com!24m; "
    "rf=afrf; pct=100; ri=86400"
]

BAD_DKIM_RECORDS = [
    ("", "Not a valid DKIM record"),
    ("v=DKIM1; toto;p=XXX", "Invalid tag toto"),
    ("v=DKIM1;;k=rsa", "No key found in record"),
]


class LibTestCase(SimpleTestCase):
    """TestCase for library methods."""

    @mock.patch('modoboa.admin.lib.get_dns_records')
    def test_get_record_type_value(self, mock_get_dns_records):
        mock_get_dns_records.return_value = [
            TXT("IN", "TXT", ["v=spf1 mx -all"]),
            TXT("IN", "TXT", ["v=DKIM1 p=XXXXX", "YYYYY"]),
            TXT("IN", "TXT", ["v=DMARC1 p=reject"]),
        ]
        self.assertEqual(
            lib.get_spf_record("example.com"), "v=spf1 mx -all"
        )
        self.assertEqual(
            lib.get_dkim_record("example.com", "mail"), "v=DKIM1 p=XXXXXYYYYY"
        )
            self.assertEqual(str(ctx.exception), record[1])
        key = lib.check_dkim_syntax("v=DKIM1;p=XXX123")
        self.assertEqual(key, "XXX123")
            error="Public key mismatchs",
            domain__name="test.com"
        )
        cls.ac_rec = factories.DNSRecordFactory(
            type="autoconfig", value="1.2.3.4", is_valid=True,
            domain__name="test.com"
        )

    def test_record_detail_view(self):
        url = reverse("dnstools:dns_record_detail", args=[self.spf_rec.pk])
        response = self.client.get(url)
        self.assertContains(
            response, "A DNS record has been found and is valid")
        url = reverse("dnstools:dns_record_detail", args=[self.dmarc_rec.pk])
        response = self.client.get(url)
        self.assertContains(response, "Not a DMARC record")

    def test_autoconfig_record_status_view(self):
        url = reverse(
            "dnstools:autoconfig_records_status", args=[self.ac_rec.domain.pk])
        response = self.client.get(url)
        self.assertContains(response, "autoconfig record (Mozilla) found")
        self.assertContains(
            response, "autodiscover record (Microsoft) not found")

    def test_domain_dns_configuration(self):
        url = reverse(
            "dnstools:domain_dns_configuration", args=[self.ac_rec.domain.pk])
        response = self.client.get(url)
        self.assertContains(response, "[IP address of your Modoboa server]")


class DomainTestCase(ModoTestCase):

    def test_dns_global_status(self):
        admin_factories.MXRecordFactory.create(
            domain__name="test.com", name="mail.test.com",
            updated=timezone.now())
        domain = admin_models.Domain.objects.get(name="test.com")
        self.assertEqual(domain.dns_global_status, "critical")

        factories.DNSRecordFactory.create(
            type="spf", value="v=SPF1 mx -all", is_valid=True,
            domain__name="test.com"
        )
        self.assertEqual(domain.dns_global_status, "critical")

        factories.DNSRecordFactory(
            type="dkim", value="12345", is_valid=True,
            domain__name="test.com"
        )
        self.assertEqual(domain.dns_global_status, "critical")

        factories.DNSRecordFactory(
            type="dmarc", value="XXX", is_valid=True,
            domain__name="test.com"
        )
        self.assertEqual(domain.dns_global_status, "critical")

        factories.DNSRecordFactory(
            type="autoconfig", value="1.2.3.4", is_valid=True,
            domain__name="test.com"
        )
        self.assertEqual(domain.dns_global_status, "critical")

        factories.DNSRecordFactory(
            type="autodiscover", value="1.2.3.4", is_valid=True,
            domain__name="test.com"
        )
        self.assertEqual(domain.dns_global_status, "ok")

<MSG> Improved coverage and added FR translation.

<DFF> @@ -1,7 +1,11 @@
 """App related tests."""
 
+from django.urls import reverse
 from django.test import SimpleTestCase
 
+from modoboa.lib.tests import ModoTestCase
+
+from . import factories
 from . import lib
 
 
@@ -28,9 +32,9 @@ GOOD_SPF_RECORDS = [
     "v=spf1 mx",
     "v=spf1 a ~all",
     "v=spf1 ip4:1.2.3.4 -all",
-    # "v=spf1 ip4:1.2.3.4/16 -all",
+    "v=spf1 ip4:1.2.3.4/16 -all",
     "v=spf1 ip6:fe80::9eb6:d0ff:fe8e:2807 -all",
-    # "v=spf1 ip6:fe80::9eb6:d0ff:fe8e:2807/64 -all",
+    "v=spf1 ip6:fe80::9eb6:d0ff:fe8e:2807/64 -all",
     "v=spf1 a -all",
     "v=spf1 a:example.com -all",
     "v=spf1 a:mailers.example.com -all",
@@ -100,3 +104,47 @@ class TestCase(SimpleTestCase):
             self.assertEqual(str(ctx.exception), record[1])
         key = lib.check_dkim_syntax("v=DKIM1;p=XXX123")
         self.assertEqual(key, "XXX123")
+
+
+class ViewsTestCase(ModoTestCase):
+    """A test case for views."""
+
+    @classmethod
+    def setUpTestData(cls):
+        """Create some records."""
+        super(ViewsTestCase, cls).setUpTestData()
+        cls.spf_rec = factories.DNSRecordFactory(
+            type="spf", value="v=SPF1 mx -all", is_valid=True,
+            domain__name="test.com"
+        )
+        cls.dmarc_rec = factories.DNSRecordFactory(
+            type="dmarc", value="XXX", is_valid=False,
+            error="Not a DMARC record",
+            domain__name="test.com"
+        )
+        cls.dkim_rec = factories.DNSRecordFactory(
+            type="dkim", value="12345", is_valid=False,
+            error="Public key mismatchs",
+            domain__name="test.com"
+        )
+        cls.ac_rec = factories.DNSRecordFactory(
+            type="autoconfig", value="1.2.3.4", is_valid=True,
+            domain__name="test.com"
+        )
+
+    def test_record_detail_view(self):
+        url = reverse("dnstools:dns_record_detail", args=[self.spf_rec.pk])
+        response = self.client.get(url)
+        self.assertContains(
+            response, "A DNS record has been found and is valid")
+        url = reverse("dnstools:dns_record_detail", args=[self.dmarc_rec.pk])
+        response = self.client.get(url)
+        self.assertContains(response, "Not a DMARC record")
+
+    def test_autoconfig_record_status_view(self):
+        url = reverse(
+            "dnstools:autoconfig_records_status", args=[self.ac_rec.domain.pk])
+        response = self.client.get(url)
+        self.assertContains(response, "autoconfig record (Mozilla) found")
+        self.assertContains(
+            response, "autodiscover record (Microsoft) not found")

Improved coverage and added FR translation.