2022-07-22 03:26:41 +02:00
2022-04-11 00:16:54 +02:00
import base64
2022-06-30 23:43:22 +02:00
from collections import OrderedDict
2022-04-11 00:16:54 +02:00
from datetime import datetime
2022-07-22 03:26:41 +02:00
from django . contrib . auth . models import User
2022-06-30 23:43:22 +02:00
from django . core . files . uploadedfile import SimpleUploadedFile
from freezegun import freeze_time
2022-07-22 03:26:41 +02:00
from helpdesk . models import CustomField , Queue , Ticket
2022-04-11 00:16:54 +02:00
from rest_framework import HTTP_HEADER_ENCODING
from rest_framework . exceptions import ErrorDetail
2022-07-22 03:26:41 +02:00
from rest_framework . status import (
HTTP_200_OK ,
HTTP_201_CREATED ,
HTTP_204_NO_CONTENT ,
HTTP_400_BAD_REQUEST ,
HTTP_403_FORBIDDEN
)
2022-04-11 00:16:54 +02:00
from rest_framework . test import APITestCase
class TicketTest ( APITestCase ) :
2022-06-20 17:35:28 +02:00
due_date = datetime ( 2022 , 4 , 10 , 15 , 6 )
2022-04-11 00:16:54 +02:00
@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/ ' )
2022-04-22 20:52:51 +02:00
self . assertEqual ( response . status_code , HTTP_403_FORBIDDEN )
2022-04-11 00:16:54 +02:00
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/ ' )
2022-04-22 20:52:51 +02:00
self . assertEqual ( response . status_code , HTTP_403_FORBIDDEN )
2022-04-11 00:16:54 +02:00
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 \n Multi 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 ' )
2022-07-14 09:19:11 +02:00
self . assertEqual ( created_ticket . description ,
' Test description \n Multi lines ' )
2022-04-11 00:16:54 +02:00
self . assertEqual ( created_ticket . submitter_email , ' test@mail.com ' )
self . assertEqual ( created_ticket . priority , 4 )
2022-06-30 23:43:22 +02:00
self . assertEqual ( created_ticket . followup_set . count ( ) , 1 )
2022-04-11 00:16:54 +02:00
def test_create_api_ticket_with_basic_auth ( self ) :
username = ' admin '
password = ' admin '
2022-07-14 09:19:11 +02:00
User . objects . create_user (
username = username , password = password , is_staff = True )
2022-04-11 00:16:54 +02:00
test_user = User . objects . create_user ( username = ' test ' )
2022-07-14 09:19:11 +02:00
merge_ticket = Ticket . objects . create (
queue = self . queue , title = ' merge ticket ' )
2022-04-11 00:16:54 +02:00
# Generate base64 credentials string
credentials = f " { username } : { password } "
2022-07-14 09:19:11 +02:00
base64_credentials = base64 . b64encode ( credentials . encode (
HTTP_HEADER_ENCODING ) ) . decode ( HTTP_HEADER_ENCODING )
2022-04-11 00:16:54 +02:00
2022-07-14 09:19:11 +02:00
self . client . credentials (
HTTP_AUTHORIZATION = f " Basic { base64_credentials } " )
2022-04-11 00:16:54 +02:00
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 ,
2022-06-20 17:35:28 +02:00
' due_date ' : self . due_date ,
2022-04-11 00:16:54 +02:00
' 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 ' )
2022-07-14 09:19:11 +02:00
# resolution can not be set on creation
self . assertIsNone ( created_ticket . resolution )
2022-04-11 00:16:54 +02:00
self . assertEqual ( created_ticket . assigned_to , test_user )
self . assertEqual ( created_ticket . submitter_email , ' test@mail.com ' )
self . assertEqual ( created_ticket . priority , 1 )
2022-07-14 09:19:11 +02:00
# 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 )
2022-06-20 17:35:28 +02:00
self . assertEqual ( created_ticket . due_date , self . due_date )
2022-07-14 09:19:11 +02:00
# merged_to can not be set on creation
self . assertIsNone ( created_ticket . merged_to )
2022-04-11 00:16:54 +02:00
def test_edit_api_ticket ( self ) :
staff_user = User . objects . create_user ( username = ' admin ' , is_staff = True )
2022-07-14 09:19:11 +02:00
test_ticket = Ticket . objects . create (
queue = self . queue , title = ' Test ticket ' )
2022-04-11 00:16:54 +02:00
test_user = User . objects . create_user ( username = ' test ' )
2022-07-14 09:19:11 +02:00
merge_ticket = Ticket . objects . create (
queue = self . queue , title = ' merge ticket ' )
2022-04-11 00:16:54 +02:00
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 ,
2022-06-20 17:35:28 +02:00
' due_date ' : self . due_date ,
2022-04-11 00:16:54 +02:00
' 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 )
2022-06-20 17:35:28 +02:00
self . assertEqual ( test_ticket . due_date , self . due_date )
2022-04-11 00:16:54 +02:00
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 )
2022-07-14 09:19:11 +02:00
test_ticket = Ticket . objects . create (
queue = self . queue , title = ' Test ticket ' )
2022-04-11 00:16:54 +02:00
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 )
2022-07-14 09:19:11 +02:00
test_ticket = Ticket . objects . create (
queue = self . queue , title = ' Test ticket ' )
2022-04-11 00:16:54 +02:00
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 ( ) )
2022-06-30 23:43:22 +02:00
@freeze_time ( ' 2022-06-30 23:09:44 ' )
2022-04-11 00:16:54 +02:00
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 '''
2022-07-14 09:19:11 +02:00
CustomField . objects . create (
name = field_type , label = field_display , data_type = field_type , * * extra_data )
2022-04-11 00:16:54 +02:00
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 \n Multi lines ' ,
' submitter_email ' : ' test@mail.com ' ,
' priority ' : 4
} )
self . assertEqual ( response . status_code , HTTP_400_BAD_REQUEST )
2022-07-14 09:19:11 +02:00
self . assertEqual ( response . data , { ' custom_integer ' : [ ErrorDetail (
string = ' This field is required. ' , code = ' required ' ) ] } )
2022-04-11 00:16:54 +02:00
# Test creation with custom field values
response = self . client . post ( ' /api/tickets/ ' , {
' queue ' : self . queue . id ,
' title ' : ' Test title ' ,
' description ' : ' Test description \n Multi lines ' ,
' submitter_email ' : ' test@mail.com ' ,
' priority ' : 4 ,
' custom_varchar ' : ' test ' ,
' custom_text ' : ' multi \n line ' ,
' 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 \n Multi lines ' ,
' resolution ' : None ,
' submitter_email ' : ' test@mail.com ' ,
' assigned_to ' : None ,
' status ' : 1 ,
' on_hold ' : False ,
' priority ' : 4 ,
' due_date ' : None ,
' merged_to ' : None ,
2022-06-30 23:43:22 +02:00
' followup_set ' : [ OrderedDict ( [
( ' id ' , 1 ) ,
( ' ticket ' , 1 ) ,
2023-11-29 23:03:09 +01:00
( ' user ' , 1 ) ,
2022-06-30 23:43:22 +02:00
( ' title ' , ' Ticket Opened ' ) ,
( ' comment ' , ' Test description \n Multi lines ' ) ,
( ' public ' , True ) ,
( ' new_status ' , None ) ,
( ' time_spent ' , None ) ,
2023-11-29 23:03:09 +01:00
( ' followupattachment_set ' , [ ] ) ,
( ' date ' , ' 2022-06-30T23:09:44 ' ) ,
( ' message_id ' , None ) ,
2022-06-30 23:43:22 +02:00
] ) ] ,
2022-04-11 00:16:54 +02:00
' custom_varchar ' : ' test ' ,
' custom_text ' : ' multi \n line ' ,
' 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 '
} )
2022-06-30 23:43:22 +02:00
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 )
2022-07-14 09:19:11 +02:00
test_file = SimpleUploadedFile (
' file.jpg ' , b ' file_content ' , content_type = ' image/jpg ' )
2022-06-30 23:43:22 +02:00
response = self . client . post ( ' /api/tickets/ ' , {
' queue ' : self . queue . id ,
' title ' : ' Test title ' ,
' description ' : ' Test description \n Multi 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 ' )
2022-07-14 09:19:11 +02:00
self . assertEqual ( created_ticket . description ,
' Test description \n Multi lines ' )
2022-06-30 23:43:22 +02:00
self . assertEqual ( created_ticket . submitter_email , ' test@mail.com ' )
self . assertEqual ( created_ticket . priority , 4 )
self . assertEqual ( created_ticket . followup_set . count ( ) , 1 )
2022-07-14 09:19:11 +02:00
self . assertEqual ( created_ticket . followup_set . get (
) . followupattachment_set . count ( ) , 1 )
2022-06-30 23:43:22 +02:00
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 ' )
2022-07-14 09:19:11 +02:00
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 ' )
2022-06-30 23:43:22 +02:00
response = self . client . post ( ' /api/followups/ ' , {
' ticket ' : ticket . id ,
' title ' : ' Test ' ,
' comment ' : ' Test answer \n Multi 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 \n Multi lines ' )
self . assertEqual ( created_followup . followupattachment_set . count ( ) , 2 )
2022-07-14 09:19:11 +02:00
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 ' )
2023-11-26 13:52:10 +01:00
class UserTicketTest ( APITestCase ) :
def setUp ( self ) :
self . queue = Queue . objects . create ( title = ' Test queue ' )
self . user = User . objects . create_user ( username = ' test ' )
self . client . force_authenticate ( self . user )
def test_get_user_tickets ( self ) :
user = User . objects . create_user ( username = ' test2 ' , email = " foo@example.com " )
ticket_1 = Ticket . objects . create (
queue = self . queue , title = ' Test 1 ' ,
submitter_email = " foo@example.com " )
ticket_2 = Ticket . objects . create (
queue = self . queue , title = ' Test 2 ' ,
submitter_email = " bar@example.com " )
ticket_3 = Ticket . objects . create (
queue = self . queue , title = ' Test 3 ' ,
submitter_email = " foo@example.com " )
self . client . force_authenticate ( user )
response = self . client . get ( ' /api/user_tickets/ ' )
self . assertEqual ( response . status_code , HTTP_200_OK )
self . assertEqual ( len ( response . data [ " results " ] ) , 2 )
self . assertEqual ( response . data [ " results " ] [ 0 ] [ ' id ' ] , ticket_3 . id )
self . assertEqual ( response . data [ " results " ] [ 1 ] [ ' id ' ] , ticket_1 . id )
def test_staff_user ( self ) :
staff_user = User . objects . create_user ( username = ' test2 ' , is_staff = True , email = " staff@example.com " )
ticket_1 = Ticket . objects . create (
queue = self . queue , title = ' Test 1 ' ,
submitter_email = " staff@example.com " )
ticket_2 = Ticket . objects . create (
queue = self . queue , title = ' Test 2 ' ,
submitter_email = " foo@example.com " )
self . client . force_authenticate ( staff_user )
response = self . client . get ( ' /api/user_tickets/ ' )
self . assertEqual ( response . status_code , HTTP_200_OK )
self . assertEqual ( len ( response . data [ " results " ] ) , 1 )
def test_not_logged_in_user ( self ) :
ticket_1 = Ticket . objects . create (
queue = self . queue , title = ' Test 1 ' ,
submitter_email = " ex@example.com " )
self . client . logout ( )
response = self . client . get ( ' /api/user_tickets/ ' )
self . assertEqual ( response . status_code , HTTP_403_FORBIDDEN )