Repository: svthalia/concrexit

Issue:
Add testing to see if pages load correctly
### Is your feature request related to a problem? Please describe.
As #1461 showed, it seems that it is possible for fairly critical page load errors (in this case, `GET /events/`) to slip through testing.

### Describe the solution you'd like
I would like more tests added, to increase robustness and reduce the chance of an edit of templates etc to break pages. In this case, it would be adding tests to see if pages load correctly.

### Motivation
#1461 showed that this can be a real issue. Making sure that testing is comprehensive can prevent issues like this from getting merged in the future.


Discussion:

Resolving patch:
diff --git a/website/thaliawebsite/apps.py b/website/thaliawebsite/apps.py
new file mode 100644
--- /dev/null
+++ b/website/thaliawebsite/apps.py
@@ -0,0 +1,29 @@
+import logging
+import os
+from subprocess import Popen
+
+from django.apps import AppConfig
+from django.conf import settings
+
+logger = logging.getLogger(__name__)
+
+
+class ThaliaWebsiteConfig(AppConfig):
+    name = "thaliawebsite"
+
+    def ready(self):
+        if (
+            settings.DJANGO_ENV in ["production", "staging"]
+            and os.environ.get("MANAGE_PY", "0") == "0"
+        ):
+            logger.info("Telling systemd we're ready")
+            try:
+                Popen(
+                    [
+                        "/run/current-system/sw/bin/systemd-notify",
+                        "--ready",
+                        "--status=App registry populated",
+                    ]
+                )
+            except Exception as e:  # pylint: disable=broad-except
+                logger.exception(e)
diff --git a/website/thaliawebsite/settings.py b/website/thaliawebsite/settings.py
--- a/website/thaliawebsite/settings.py
+++ b/website/thaliawebsite/settings.py
@@ -381,7 +381,7 @@ def from_env(
     # Our apps
     # Directly link to the app config when applicable as recommended
     # by the docs: https://docs.djangoproject.com/en/2.0/ref/applications/
-    "thaliawebsite",  # include for admin settings
+    "thaliawebsite.apps.ThaliaWebsiteConfig",  # include for admin settings
     # Load django.contrib.admin after thaliawebsite so the admin page gets modified
     "django.contrib.admin",
     "pushnotifications.apps.PushNotificationsConfig",


Test patch:
diff --git a/nix/test.nix b/nix/test.nix
new file mode 100644
--- /dev/null
+++ b/nix/test.nix
@@ -0,0 +1,48 @@
+{ ... }:
+{
+  name = "concrexit";
+
+  machine = { ... }: {
+    imports = [ ./configuration.nix ];
+
+    concrexit.ssl = false;
+  };
+
+  testScript = { nodes }: ''
+    def remove_prefix(text, prefix):
+        if text.startswith(prefix):
+            return text[len(prefix) :]
+        return text
+
+
+    machine.wait_for_unit("concrexit.service")
+    machine.wait_for_open_port(80)
+    machine.wait_for_open_port(${toString nodes.machine.config.concrexit.app-port})
+
+    machine.succeed("GSUITE_MEMBERS_AUTOSYNC=0 concrexit-manage createfixtures -a 2>&1")
+
+    import xml.etree.ElementTree as ET
+    import os.path
+
+    machine.succeed("curl --fail 'http://localhost/'")
+
+    sitemap_xml = machine.succeed("curl --fail 'http://localhost/sitemap.xml'")
+    root = ET.fromstring(sitemap_xml)
+    urls = []
+    for child in root:
+        url = child.find("{http://www.sitemaps.org/schemas/sitemap/0.9}loc")
+        urls.append(url.text)
+
+    # Only get one url per boring suffix (e.g. only one event etc.)
+    urls = sorted(sorted((url, len(url.split("/"))) for url in urls), key=lambda x: x[1])
+    last_url = urls[0]
+    for url in urls[1:]:
+        if last_url[1] == url[1] and re.fullmatch(
+            r"[\d\-]+",
+            remove_prefix(url[0], os.path.commonprefix([url[0], last_url[0]])).strip("/"),
+        ):
+            continue
+        machine.succeed(f"curl --fail '{url[0]}'")
+        last_url = url
+  '';
+}