mirror of
https://github.com/django-helpdesk/django-helpdesk.git
synced 2025-07-21 16:07:15 +02:00
261 lines
9.6 KiB
Python
261 lines
9.6 KiB
Python
# vim: set fileencoding=utf-8 :
|
|
|
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
|
from django.test import override_settings, TestCase
|
|
from django.urls import reverse
|
|
from django.utils.encoding import smart_str
|
|
from helpdesk import lib, models
|
|
import os
|
|
import shutil
|
|
from tempfile import gettempdir
|
|
from unittest import mock
|
|
from unittest.case import skip
|
|
from django.contrib.auth import get_user_model
|
|
|
|
|
|
MEDIA_DIR = os.path.join(gettempdir(), "helpdesk_test_media")
|
|
|
|
|
|
@override_settings(MEDIA_ROOT=MEDIA_DIR)
|
|
class AttachmentIntegrationTests(TestCase):
|
|
fixtures = ["emailtemplate.json"]
|
|
|
|
def setUp(self):
|
|
self.queue_public = models.Queue.objects.create(
|
|
title="Public Queue",
|
|
slug="pub_q",
|
|
allow_public_submission=True,
|
|
new_ticket_cc="new.public@example.com",
|
|
updated_ticket_cc="update.public@example.com",
|
|
)
|
|
|
|
self.queue_private = models.Queue.objects.create(
|
|
title="Private Queue",
|
|
slug="priv_q",
|
|
allow_public_submission=False,
|
|
new_ticket_cc="new.private@example.com",
|
|
updated_ticket_cc="update.private@example.com",
|
|
)
|
|
|
|
self.ticket_data = {
|
|
"title": "Test Ticket Title",
|
|
"body": "Test Ticket Desc",
|
|
"priority": 3,
|
|
"submitter_email": "submitter@example.com",
|
|
}
|
|
|
|
def test_create_pub_ticket_with_attachment(self):
|
|
test_file = SimpleUploadedFile(
|
|
"test_att.txt", b"attached file content", "text/plain"
|
|
)
|
|
post_data = self.ticket_data.copy()
|
|
post_data.update(
|
|
{
|
|
"queue": self.queue_public.id,
|
|
"attachment": test_file,
|
|
}
|
|
)
|
|
|
|
# Ensure ticket form submits with attachment successfully
|
|
response = self.client.post(reverse("helpdesk:home"), post_data, follow=True)
|
|
self.assertContains(response, test_file.name)
|
|
|
|
# Ensure attachment is available with correct content
|
|
att = models.FollowUpAttachment.objects.get(
|
|
followup__ticket=response.context["ticket"]
|
|
)
|
|
with open(os.path.join(MEDIA_DIR, att.file.name)) as file_on_disk:
|
|
disk_content = file_on_disk.read()
|
|
self.assertEqual(disk_content, "attached file content")
|
|
|
|
def test_create_pub_ticket_with_attachment_utf8(self):
|
|
test_file = SimpleUploadedFile("ß°äöü.txt", "โจ".encode("utf-8"), "text/utf-8")
|
|
post_data = self.ticket_data.copy()
|
|
post_data.update(
|
|
{
|
|
"queue": self.queue_public.id,
|
|
"attachment": test_file,
|
|
}
|
|
)
|
|
|
|
# Ensure ticket form submits with attachment successfully
|
|
response = self.client.post(reverse("helpdesk:home"), post_data, follow=True)
|
|
self.assertContains(response, test_file.name)
|
|
|
|
# Ensure attachment is available with correct content
|
|
att = models.FollowUpAttachment.objects.get(
|
|
followup__ticket=response.context["ticket"]
|
|
)
|
|
with open(
|
|
os.path.join(MEDIA_DIR, att.file.name), encoding="utf-8"
|
|
) as file_on_disk:
|
|
disk_content = smart_str(file_on_disk.read(), "utf-8")
|
|
self.assertEqual(disk_content, "โจ")
|
|
|
|
|
|
@override_settings(MEDIA_ROOT=MEDIA_DIR)
|
|
class AttachmentIntegrationStaffTests(TestCase):
|
|
def setUp(self):
|
|
self.ticket = models.Ticket.objects.create(
|
|
queue=models.Queue.objects.create(),
|
|
title="Test attachments via ticket update",
|
|
)
|
|
self.default_update_post_data = {
|
|
"queue": self.ticket.queue_id,
|
|
"title": self.ticket.title,
|
|
"priority": self.ticket.priority,
|
|
}
|
|
|
|
def loginUser(self, is_staff=True):
|
|
"""Create a staff user and login"""
|
|
User = get_user_model()
|
|
self.user = User.objects.create(
|
|
username="User_1",
|
|
is_staff=is_staff,
|
|
)
|
|
self.user.set_password("pass")
|
|
self.user.save()
|
|
self.client.login(username="User_1", password="pass")
|
|
|
|
def test_update_ticket_with_attachment_valid_extension(self):
|
|
self.loginUser(is_staff=True)
|
|
file_content = "staff attached file content"
|
|
test_file = SimpleUploadedFile(
|
|
"test_staff_att.txt", bytes(file_content, "utf-8"), "text/plain"
|
|
)
|
|
post_data = {
|
|
"attachment": test_file,
|
|
**self.default_update_post_data,
|
|
}
|
|
# Ensure ticket form submits with attachment successfully
|
|
self.client.post(
|
|
reverse(
|
|
"helpdesk:update",
|
|
kwargs={"ticket_id": self.ticket.id},
|
|
),
|
|
post_data,
|
|
follow=True,
|
|
)
|
|
# Ensure attachment is available with correct content
|
|
att = models.FollowUpAttachment.objects.get(followup__ticket=self.ticket)
|
|
with open(os.path.join(MEDIA_DIR, att.file.name)) as file_on_disk:
|
|
disk_content = file_on_disk.read()
|
|
self.assertEqual(disk_content, file_content)
|
|
|
|
def test_update_ticket_with_attachment_invalid_extension(self):
|
|
self.loginUser(is_staff=True)
|
|
file_content = "staff attached file content with invalid extension"
|
|
file_extension = ".crash"
|
|
test_file = SimpleUploadedFile(
|
|
f"test_staff_att{file_extension}",
|
|
bytes(file_content, "utf-8"),
|
|
"text/plain",
|
|
)
|
|
post_data = {
|
|
"attachment": test_file,
|
|
**self.default_update_post_data,
|
|
}
|
|
# Ensure ticket form submits with attachment successfully
|
|
response = self.client.post(
|
|
reverse(
|
|
"helpdesk:update",
|
|
kwargs={"ticket_id": self.ticket.id},
|
|
),
|
|
post_data,
|
|
follow=True,
|
|
)
|
|
error_msg = response.context_data["form"].errors["attachment"][0]
|
|
self.assertTrue(
|
|
file_extension in error_msg,
|
|
"Response indicates there were no errors attaching illegal file extension",
|
|
)
|
|
# Ensure attachment is not uploaded
|
|
has_att = models.FollowUpAttachment.objects.filter(
|
|
followup__ticket=self.ticket
|
|
).exists()
|
|
self.assertFalse(has_att, "File was attached with invalid extension")
|
|
|
|
|
|
@mock.patch.object(models.FollowUp, "save", autospec=True)
|
|
@mock.patch.object(models.FollowUpAttachment, "save", autospec=True)
|
|
@mock.patch.object(models.Ticket, "save", autospec=True)
|
|
@mock.patch.object(models.Queue, "save", autospec=True)
|
|
class AttachmentUnitTests(TestCase):
|
|
def setUp(self):
|
|
self.file_attrs = {
|
|
"filename": "°ßäöü.txt",
|
|
"content": "โจ".encode("utf-8"),
|
|
"content-type": "text/utf8",
|
|
}
|
|
self.test_file = SimpleUploadedFile.from_dict(self.file_attrs)
|
|
self.follow_up = models.FollowUp.objects.create(
|
|
ticket=models.Ticket.objects.create(queue=models.Queue.objects.create())
|
|
)
|
|
|
|
@skip("Rework with model relocation")
|
|
def test_unicode_attachment_filename(
|
|
self, mock_att_save, mock_queue_save, mock_ticket_save, mock_follow_up_save
|
|
):
|
|
"""check utf-8 data is parsed correctly"""
|
|
filename, fileobj = lib.process_attachments(self.follow_up, [self.test_file])[0]
|
|
mock_att_save.assert_called_with(
|
|
file=self.test_file,
|
|
filename=self.file_attrs["filename"],
|
|
mime_type=self.file_attrs["content-type"],
|
|
size=len(self.file_attrs["content"]),
|
|
followup=self.follow_up,
|
|
)
|
|
self.assertEqual(filename, self.file_attrs["filename"])
|
|
|
|
def test_autofill(
|
|
self, mock_att_save, mock_queue_save, mock_ticket_save, mock_follow_up_save
|
|
):
|
|
"""check utf-8 data is parsed correctly"""
|
|
obj = models.FollowUpAttachment.objects.create(
|
|
followup=self.follow_up, file=self.test_file
|
|
)
|
|
obj.save()
|
|
self.assertEqual(obj.file.name, self.file_attrs["filename"])
|
|
self.assertEqual(obj.file.size, len(self.file_attrs["content"]))
|
|
self.assertEqual(obj.file.file.content_type, "text/utf8")
|
|
|
|
def test_kbi_attachment(
|
|
self, mock_att_save, mock_queue_save, mock_ticket_save, mock_follow_up_save
|
|
):
|
|
"""check utf-8 data is parsed correctly"""
|
|
|
|
kbcategory = models.KBCategory.objects.create(
|
|
title="Title", slug="slug", description="Description"
|
|
)
|
|
kbitem = models.KBItem.objects.create(
|
|
category=kbcategory, title="Title", question="Question", answer="Answer"
|
|
)
|
|
|
|
obj = models.KBIAttachment.objects.create(kbitem=kbitem, file=self.test_file)
|
|
obj.save()
|
|
self.assertEqual(obj.filename, self.file_attrs["filename"])
|
|
self.assertEqual(obj.file.size, len(self.file_attrs["content"]))
|
|
self.assertEqual(obj.mime_type, "text/plain")
|
|
|
|
@skip("model in lib not patched")
|
|
@override_settings(MEDIA_ROOT=MEDIA_DIR)
|
|
def test_unicode_filename_to_filesystem(
|
|
self, mock_att_save, mock_queue_save, mock_ticket_save, mock_follow_up_save
|
|
):
|
|
"""don't mock saving to filesystem to test file renames caused by storage layer"""
|
|
filename, fileobj = lib.process_attachments(self.follow_up, [self.test_file])[0]
|
|
# Attachment object was zeroth positional arg (i.e. self) of att.save
|
|
# call
|
|
attachment_obj = mock_att_save.return_value
|
|
|
|
mock_att_save.assert_called_once_with(attachment_obj)
|
|
self.assertIsInstance(attachment_obj, models.FollowUpAttachment)
|
|
self.assertEqual(attachment_obj.filename, self.file_attrs["filename"])
|
|
|
|
|
|
def tearDownModule():
|
|
try:
|
|
shutil.rmtree(MEDIA_DIR)
|
|
except OSError:
|
|
pass
|