From 32edc094d52c750a1e8f5627be78fe4d16633d00 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Sun, 4 May 2025 11:23:10 +0200 Subject: [PATCH] Added more tests --- modoboa/webmail/tests/data.py | 13 +++++- modoboa/webmail/tests/test_viewsets.py | 62 +++++++++++++++++++++++++- modoboa/webmail/viewsets.py | 12 +++-- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/modoboa/webmail/tests/data.py b/modoboa/webmail/tests/data.py index bc50591ac..9cf9a3c1a 100644 --- a/modoboa/webmail/tests/data.py +++ b/modoboa/webmail/tests/data.py @@ -110,8 +110,17 @@ BODYSTRUCTURE_SAMPLE_WITH_FLAGS = [ b")", ] -BODYSTRUCTURE_EMPTY_MAIL = [ - b'33 (UID 33 BODYSTRUCTURE (("text" "plain" ("charset" "us-ascii") NIL NIL "quoted-printable" 0 0 NIL NIL NIL NIL)("application" "zip" ("name" "hotmail.com!ngyn.org!1435428000!1435514400.zip") NIL NIL "base64" 978 NIL ("attachment" ("filename" "hotmail.com!ngyn.org!1435428000!1435514400.zip")) NIL NIL) "mixed" ("boundary" "--boundary_32281_b52cf564-2a50-4f96-aeb0-ef5f83b05463") NIL NIL NIL))' +EMPTY_BODYSTRUCTURE = 'BODYSTRUCTURE (("text" "plain" ("charset" "us-ascii") NIL NIL "quoted-printable" 0 0 NIL NIL NIL NIL)("application" "zip" ("name" "hotmail.com!ngyn.org!1435428000!1435514400.zip") NIL NIL "base64" 978 NIL ("attachment" ("filename" "hotmail.com!ngyn.org!1435428000!1435514400.zip")) NIL NIL) "mixed" ("boundary" "--boundary_32281_b52cf564-2a50-4f96-aeb0-ef5f83b05463") NIL NIL NIL)' + +BODYSTRUCTURE_EMPTY_MAIL = [bytes(f"33 (UID 33 {EMPTY_BODYSTRUCTURE})", "utf-8")] + +BODYSTRUCTURE_EMPTY_MAIL_WITH_HEADERS = [ + ( + bytes(f"33 (UID 33 {EMPTY_BODYSTRUCTURE}", "utf-8") + + b" BODY[HEADER.FIELDS (FROM TO CC DATE SUBJECT)] {235}", + b"From: \r\nTo: \r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\nMessage-ID: \r\n\r\n", + ), + b")", ] EMPTY_BODY = [(b"33 (UID 33 BODY[1] {0}", b""), b")"] diff --git a/modoboa/webmail/tests/test_viewsets.py b/modoboa/webmail/tests/test_viewsets.py index 74a9d4c47..921014baa 100644 --- a/modoboa/webmail/tests/test_viewsets.py +++ b/modoboa/webmail/tests/test_viewsets.py @@ -89,12 +89,14 @@ class IMAP4Mock: elif uid == 33: if args[1] == "(BODYSTRUCTURE)": data = tests_data.BODYSTRUCTURE_EMPTY_MAIL + elif "HEADER.FIELDS" in args[1]: + data = tests_data.BODYSTRUCTURE_EMPTY_MAIL_WITH_HEADERS else: data = tests_data.EMPTY_BODY elif uid == 133872: data = tests_data.COMPLETE_MAIL return "OK", data - elif command == "STORE": + elif command in ["COPY", "STORE"]: return "OK", [] @@ -231,6 +233,64 @@ class UserEmailViewSetTestCase(WebmailTestCase): self.assertEqual(response.status_code, 200) self.assertIn("Message-ID", response.json()["source"]) + def test_delete(self): + self.authenticate() + url = reverse("v2:webmail-email-delete") + body = {"mailbox": "INBOX", "selection": [1]} + response = self.client.post(url, body, format="json") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()["count"], 1) + + body = {"mailbox": "INBOX", "selection": ["truc"]} + response = self.client.post(url, body, format="json") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()["count"], 0) + + def test_mark_as_junk(self): + self.authenticate() + url = reverse("v2:webmail-email-mark-as-junk") + body = {"mailbox": "INBOX", "selection": [1]} + response = self.client.post(url, body, format="json") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()["count"], 1) + + def test_mark_as_not_junk(self): + self.authenticate() + url = reverse("v2:webmail-email-mark-as-not-junk") + body = {"mailbox": "INBOX", "selection": [1]} + response = self.client.post(url, body, format="json") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()["count"], 1) + + def test_flag(self): + self.authenticate() + url = reverse("v2:webmail-email-flag") + for status in ["read", "unread", "flagged", "unflagged"]: + body = {"mailbox": "INBOX", "selection": [1], "status": status} + response = self.client.post(url, body, format="json") + self.assertEqual(response.status_code, 200) + + def test_content(self): + self.authenticate() + url = reverse("v2:webmail-email-content") + response = self.client.get(url) + self.assertEqual(response.status_code, 404) + + # Empty email + response = self.client.get(f"{url}?mailbox=INBOX&mailid=33") + self.assertEqual(response.status_code, 200) + self.assertIs(response.json()["body"], None) + + # Reply modifier + response = self.client.get(f"{url}?mailbox=INBOX&mailid=46931&context=reply") + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json()["subject"].startswith("Re:")) + + # Forward modifier + response = self.client.get(f"{url}?mailbox=INBOX&mailid=46932&context=forward") + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json()["subject"].startswith("Fwd:")) + class ComposeSessionViewSetTestCase(WebmailTestCase): diff --git a/modoboa/webmail/viewsets.py b/modoboa/webmail/viewsets.py index 2f58466a5..485572d78 100644 --- a/modoboa/webmail/viewsets.py +++ b/modoboa/webmail/viewsets.py @@ -126,27 +126,31 @@ class UserEmailViewSet(viewsets.GenericViewSet): page_num = int(request.GET.get("page", 1)) page = paginator.getpage(int(request.GET.get("page", 1))) if not page: - return response.Response( + serializer = self.get_serializer( { "count": 0, "first_index": 0, "last_index": 0, + "prev_page": None, + "next_page": None, "results": [], } ) + return response.Response(serializer.data) + content = imapc.fetch(page.id_start, page.id_stop, mbox=mailbox) content = [dict(msg) for msg in content] - results = serializers.EmailHeadersSerializer(content, many=True).data - return response.Response( + serializer = self.get_serializer( { "count": total, "first_index": page_num * messages_per_page, "last_index": (page_num * messages_per_page) + len(content), "prev_page": page.previous_page_number if page.has_previous else None, "next_page": page.next_page_number if page.has_next else None, - "results": results, + "results": content, } ) + return response.Response(serializer.data) def move_selection(self, request, destination: str) -> int: """Move selected messages to the given mailbox."""