forked from extern/django-helpdesk
25542f929e
Will fail build if imports are not sorted correctly
362 lines
15 KiB
Python
362 lines
15 KiB
Python
|
|
import base64
|
|
from collections import OrderedDict
|
|
from datetime import datetime
|
|
from django.contrib.auth.models import User
|
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
|
from freezegun import freeze_time
|
|
from helpdesk.models import CustomField, Queue, Ticket
|
|
from rest_framework import HTTP_HEADER_ENCODING
|
|
from rest_framework.exceptions import ErrorDetail
|
|
from rest_framework.status import (
|
|
HTTP_200_OK,
|
|
HTTP_201_CREATED,
|
|
HTTP_204_NO_CONTENT,
|
|
HTTP_400_BAD_REQUEST,
|
|
HTTP_403_FORBIDDEN
|
|
)
|
|
from rest_framework.test import APITestCase
|
|
|
|
|
|
class TicketTest(APITestCase):
|
|
due_date = datetime(2022, 4, 10, 15, 6)
|
|
|
|
@classmethod
|
|
def setUpTestData(cls):
|
|
cls.queue = Queue.objects.create(
|
|
title='Test Queue',
|
|
slug='test-queue',
|
|
)
|
|
|
|
def test_create_api_ticket_not_authenticated_user(self):
|
|
response = self.client.post('/api/tickets/')
|
|
self.assertEqual(response.status_code, HTTP_403_FORBIDDEN)
|
|
|
|
def test_create_api_ticket_authenticated_non_staff_user(self):
|
|
non_staff_user = User.objects.create_user(username='test')
|
|
self.client.force_authenticate(non_staff_user)
|
|
response = self.client.post('/api/tickets/')
|
|
self.assertEqual(response.status_code, HTTP_403_FORBIDDEN)
|
|
|
|
def test_create_api_ticket_no_data(self):
|
|
staff_user = User.objects.create_user(username='test', is_staff=True)
|
|
self.client.force_authenticate(staff_user)
|
|
response = self.client.post('/api/tickets/')
|
|
self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)
|
|
self.assertEqual(response.data, {
|
|
'queue': [ErrorDetail(string='This field is required.', code='required')],
|
|
'title': [ErrorDetail(string='This field is required.', code='required')]
|
|
})
|
|
self.assertFalse(Ticket.objects.exists())
|
|
|
|
def test_create_api_ticket_wrong_date_format(self):
|
|
staff_user = User.objects.create_user(username='test', is_staff=True)
|
|
self.client.force_authenticate(staff_user)
|
|
response = self.client.post('/api/tickets/', {
|
|
'queue': self.queue.id,
|
|
'title': 'Test title',
|
|
'due_date': 'monday, 1st of may 2022'
|
|
})
|
|
self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)
|
|
self.assertEqual(response.data, {
|
|
'due_date': [ErrorDetail(string='Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].', code='invalid')]
|
|
})
|
|
self.assertFalse(Ticket.objects.exists())
|
|
|
|
def test_create_api_ticket_authenticated_staff_user(self):
|
|
staff_user = User.objects.create_user(username='test', is_staff=True)
|
|
self.client.force_authenticate(staff_user)
|
|
response = self.client.post('/api/tickets/', {
|
|
'queue': self.queue.id,
|
|
'title': 'Test title',
|
|
'description': 'Test description\nMulti lines',
|
|
'submitter_email': 'test@mail.com',
|
|
'priority': 4
|
|
})
|
|
self.assertEqual(response.status_code, HTTP_201_CREATED)
|
|
created_ticket = Ticket.objects.get()
|
|
self.assertEqual(created_ticket.title, 'Test title')
|
|
self.assertEqual(created_ticket.description,
|
|
'Test description\nMulti lines')
|
|
self.assertEqual(created_ticket.submitter_email, 'test@mail.com')
|
|
self.assertEqual(created_ticket.priority, 4)
|
|
self.assertEqual(created_ticket.followup_set.count(), 1)
|
|
|
|
def test_create_api_ticket_with_basic_auth(self):
|
|
username = 'admin'
|
|
password = 'admin'
|
|
User.objects.create_user(
|
|
username=username, password=password, is_staff=True)
|
|
|
|
test_user = User.objects.create_user(username='test')
|
|
merge_ticket = Ticket.objects.create(
|
|
queue=self.queue, title='merge ticket')
|
|
|
|
# Generate base64 credentials string
|
|
credentials = f"{username}:{password}"
|
|
base64_credentials = base64.b64encode(credentials.encode(
|
|
HTTP_HEADER_ENCODING)).decode(HTTP_HEADER_ENCODING)
|
|
|
|
self.client.credentials(
|
|
HTTP_AUTHORIZATION=f"Basic {base64_credentials}")
|
|
response = self.client.post(
|
|
'/api/tickets/',
|
|
{
|
|
'queue': self.queue.id,
|
|
'title': 'Title',
|
|
'description': 'Description',
|
|
'resolution': 'Resolution',
|
|
'assigned_to': test_user.id,
|
|
'submitter_email': 'test@mail.com',
|
|
'status': Ticket.RESOLVED_STATUS,
|
|
'priority': 1,
|
|
'on_hold': True,
|
|
'due_date': self.due_date,
|
|
'merged_to': merge_ticket.id
|
|
}
|
|
)
|
|
|
|
self.assertEqual(response.status_code, HTTP_201_CREATED)
|
|
created_ticket = Ticket.objects.last()
|
|
self.assertEqual(created_ticket.title, 'Title')
|
|
self.assertEqual(created_ticket.description, 'Description')
|
|
# resolution can not be set on creation
|
|
self.assertIsNone(created_ticket.resolution)
|
|
self.assertEqual(created_ticket.assigned_to, test_user)
|
|
self.assertEqual(created_ticket.submitter_email, 'test@mail.com')
|
|
self.assertEqual(created_ticket.priority, 1)
|
|
# on_hold is False on creation
|
|
self.assertFalse(created_ticket.on_hold)
|
|
# status is always open on creation
|
|
self.assertEqual(created_ticket.status, Ticket.OPEN_STATUS)
|
|
self.assertEqual(created_ticket.due_date, self.due_date)
|
|
# merged_to can not be set on creation
|
|
self.assertIsNone(created_ticket.merged_to)
|
|
|
|
def test_edit_api_ticket(self):
|
|
staff_user = User.objects.create_user(username='admin', is_staff=True)
|
|
test_ticket = Ticket.objects.create(
|
|
queue=self.queue, title='Test ticket')
|
|
|
|
test_user = User.objects.create_user(username='test')
|
|
merge_ticket = Ticket.objects.create(
|
|
queue=self.queue, title='merge ticket')
|
|
|
|
self.client.force_authenticate(staff_user)
|
|
response = self.client.put(
|
|
'/api/tickets/%d/' % test_ticket.id,
|
|
{
|
|
'queue': self.queue.id,
|
|
'title': 'Title',
|
|
'description': 'Description',
|
|
'resolution': 'Resolution',
|
|
'assigned_to': test_user.id,
|
|
'submitter_email': 'test@mail.com',
|
|
'status': Ticket.RESOLVED_STATUS,
|
|
'priority': 1,
|
|
'on_hold': True,
|
|
'due_date': self.due_date,
|
|
'merged_to': merge_ticket.id
|
|
}
|
|
)
|
|
|
|
self.assertEqual(response.status_code, HTTP_200_OK)
|
|
test_ticket.refresh_from_db()
|
|
self.assertEqual(test_ticket.title, 'Title')
|
|
self.assertEqual(test_ticket.description, 'Description')
|
|
self.assertEqual(test_ticket.resolution, 'Resolution')
|
|
self.assertEqual(test_ticket.assigned_to, test_user)
|
|
self.assertEqual(test_ticket.submitter_email, 'test@mail.com')
|
|
self.assertEqual(test_ticket.priority, 1)
|
|
self.assertTrue(test_ticket.on_hold)
|
|
self.assertEqual(test_ticket.status, Ticket.RESOLVED_STATUS)
|
|
self.assertEqual(test_ticket.due_date, self.due_date)
|
|
self.assertEqual(test_ticket.merged_to, merge_ticket)
|
|
|
|
def test_partial_edit_api_ticket(self):
|
|
staff_user = User.objects.create_user(username='admin', is_staff=True)
|
|
test_ticket = Ticket.objects.create(
|
|
queue=self.queue, title='Test ticket')
|
|
|
|
self.client.force_authenticate(staff_user)
|
|
response = self.client.patch(
|
|
'/api/tickets/%d/' % test_ticket.id,
|
|
{
|
|
'description': 'New description',
|
|
}
|
|
)
|
|
|
|
self.assertEqual(response.status_code, HTTP_200_OK)
|
|
test_ticket.refresh_from_db()
|
|
self.assertEqual(test_ticket.description, 'New description')
|
|
|
|
def test_delete_api_ticket(self):
|
|
staff_user = User.objects.create_user(username='admin', is_staff=True)
|
|
test_ticket = Ticket.objects.create(
|
|
queue=self.queue, title='Test ticket')
|
|
self.client.force_authenticate(staff_user)
|
|
response = self.client.delete('/api/tickets/%d/' % test_ticket.id)
|
|
self.assertEqual(response.status_code, HTTP_204_NO_CONTENT)
|
|
self.assertFalse(Ticket.objects.exists())
|
|
|
|
@freeze_time('2022-06-30 23:09:44')
|
|
def test_create_api_ticket_with_custom_fields(self):
|
|
# Create custom fields
|
|
for field_type, field_display in CustomField.DATA_TYPE_CHOICES:
|
|
extra_data = {}
|
|
if field_type in ('varchar', 'text'):
|
|
extra_data['max_length'] = 10
|
|
if field_type == 'integer':
|
|
# Set one field as required to test error if not provided
|
|
extra_data['required'] = True
|
|
if field_type == 'decimal':
|
|
extra_data['max_length'] = 7
|
|
extra_data['decimal_places'] = 3
|
|
if field_type == 'list':
|
|
extra_data['list_values'] = '''Green
|
|
Blue
|
|
Red
|
|
Yellow'''
|
|
CustomField.objects.create(
|
|
name=field_type, label=field_display, data_type=field_type, **extra_data)
|
|
|
|
staff_user = User.objects.create_user(username='test', is_staff=True)
|
|
self.client.force_authenticate(staff_user)
|
|
|
|
# Test creation without providing required field
|
|
response = self.client.post('/api/tickets/', {
|
|
'queue': self.queue.id,
|
|
'title': 'Test title',
|
|
'description': 'Test description\nMulti lines',
|
|
'submitter_email': 'test@mail.com',
|
|
'priority': 4
|
|
})
|
|
self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)
|
|
self.assertEqual(response.data, {'custom_integer': [ErrorDetail(
|
|
string='This field is required.', code='required')]})
|
|
|
|
# Test creation with custom field values
|
|
response = self.client.post('/api/tickets/', {
|
|
'queue': self.queue.id,
|
|
'title': 'Test title',
|
|
'description': 'Test description\nMulti lines',
|
|
'submitter_email': 'test@mail.com',
|
|
'priority': 4,
|
|
'custom_varchar': 'test',
|
|
'custom_text': 'multi\nline',
|
|
'custom_integer': '1',
|
|
'custom_decimal': '42.987',
|
|
'custom_list': 'Red',
|
|
'custom_boolean': True,
|
|
'custom_date': '2022-4-11',
|
|
'custom_time': '23:59:59',
|
|
'custom_datetime': '2022-4-10 18:27',
|
|
'custom_email': 'email@test.com',
|
|
'custom_url': 'http://django-helpdesk.readthedocs.org/',
|
|
'custom_ipaddress': '127.0.0.1',
|
|
'custom_slug': 'test-slug',
|
|
})
|
|
self.assertEqual(response.status_code, HTTP_201_CREATED)
|
|
# Check all fields with data returned from the response
|
|
self.assertEqual(response.data, {
|
|
'id': 1,
|
|
'queue': 1,
|
|
'title': 'Test title',
|
|
'description': 'Test description\nMulti lines',
|
|
'resolution': None,
|
|
'submitter_email': 'test@mail.com',
|
|
'assigned_to': None,
|
|
'status': 1,
|
|
'on_hold': False,
|
|
'priority': 4,
|
|
'due_date': None,
|
|
'merged_to': None,
|
|
'followup_set': [OrderedDict([
|
|
('id', 1),
|
|
('ticket', 1),
|
|
('date', '2022-06-30T23:09:44'),
|
|
('title', 'Ticket Opened'),
|
|
('comment', 'Test description\nMulti lines'),
|
|
('public', True),
|
|
('user', 1),
|
|
('new_status', None),
|
|
('message_id', None),
|
|
('time_spent', None),
|
|
('followupattachment_set', [])
|
|
])],
|
|
'custom_varchar': 'test',
|
|
'custom_text': 'multi\nline',
|
|
'custom_integer': 1,
|
|
'custom_decimal': '42.987',
|
|
'custom_list': 'Red',
|
|
'custom_boolean': True,
|
|
'custom_date': '2022-04-11',
|
|
'custom_time': '23:59:59',
|
|
'custom_datetime': '2022-04-10T18:27',
|
|
'custom_email': 'email@test.com',
|
|
'custom_url': 'http://django-helpdesk.readthedocs.org/',
|
|
'custom_ipaddress': '127.0.0.1',
|
|
'custom_slug': 'test-slug'
|
|
})
|
|
|
|
def test_create_api_ticket_with_attachment(self):
|
|
staff_user = User.objects.create_user(username='test', is_staff=True)
|
|
self.client.force_authenticate(staff_user)
|
|
test_file = SimpleUploadedFile(
|
|
'file.jpg', b'file_content', content_type='image/jpg')
|
|
response = self.client.post('/api/tickets/', {
|
|
'queue': self.queue.id,
|
|
'title': 'Test title',
|
|
'description': 'Test description\nMulti lines',
|
|
'submitter_email': 'test@mail.com',
|
|
'priority': 4,
|
|
'attachment': test_file
|
|
})
|
|
self.assertEqual(response.status_code, HTTP_201_CREATED)
|
|
created_ticket = Ticket.objects.get()
|
|
self.assertEqual(created_ticket.title, 'Test title')
|
|
self.assertEqual(created_ticket.description,
|
|
'Test description\nMulti lines')
|
|
self.assertEqual(created_ticket.submitter_email, 'test@mail.com')
|
|
self.assertEqual(created_ticket.priority, 4)
|
|
self.assertEqual(created_ticket.followup_set.count(), 1)
|
|
self.assertEqual(created_ticket.followup_set.get(
|
|
).followupattachment_set.count(), 1)
|
|
attachment = created_ticket.followup_set.get().followupattachment_set.get()
|
|
self.assertEqual(
|
|
attachment.file.name,
|
|
f'helpdesk/attachments/test-queue-1-{created_ticket.secret_key}/1/file.jpg'
|
|
)
|
|
|
|
def test_create_follow_up_with_attachments(self):
|
|
staff_user = User.objects.create_user(username='test', is_staff=True)
|
|
self.client.force_authenticate(staff_user)
|
|
ticket = Ticket.objects.create(queue=self.queue, title='Test')
|
|
test_file_1 = SimpleUploadedFile(
|
|
'file.jpg', b'file_content', content_type='image/jpg')
|
|
test_file_2 = SimpleUploadedFile(
|
|
'doc.pdf', b'Doc content', content_type='application/pdf')
|
|
|
|
response = self.client.post('/api/followups/', {
|
|
'ticket': ticket.id,
|
|
'title': 'Test',
|
|
'comment': 'Test answer\nMulti lines',
|
|
'attachments': [
|
|
test_file_1,
|
|
test_file_2
|
|
]
|
|
})
|
|
self.assertEqual(response.status_code, HTTP_201_CREATED)
|
|
created_followup = ticket.followup_set.last()
|
|
self.assertEqual(created_followup.title, 'Test')
|
|
self.assertEqual(created_followup.comment, 'Test answer\nMulti lines')
|
|
self.assertEqual(created_followup.followupattachment_set.count(), 2)
|
|
self.assertEqual(
|
|
created_followup.followupattachment_set.first().filename, 'doc.pdf')
|
|
self.assertEqual(
|
|
created_followup.followupattachment_set.first().mime_type, 'application/pdf')
|
|
self.assertEqual(
|
|
created_followup.followupattachment_set.last().filename, 'file.jpg')
|
|
self.assertEqual(
|
|
created_followup.followupattachment_set.last().mime_type, 'image/jpg')
|