diff --git a/api/BusinessLogic/Tickets/NewTicketValidator.php b/api/BusinessLogic/Tickets/NewTicketValidator.php new file mode 100644 index 00000000..5f6d6a23 --- /dev/null +++ b/api/BusinessLogic/Tickets/NewTicketValidator.php @@ -0,0 +1,127 @@ +categoryRetriever = $categoryRetriever; + $this->banRetriever = $banRetriever; + $this->ticketValidators = $ticketValidators; + } + + /** + * @param $ticketRequest CreateTicketByCustomerModel + * @param $heskSettings array HESK settings + * @return ValidationModel If errorKeys is empty, validation successful. Otherwise invalid ticket + */ + function validateNewTicketForCustomer($ticketRequest, $heskSettings, $userContext) { + $TICKET_PRIORITY_CRITICAL = 0; + + $validationModel = new ValidationModel(); + + if ($ticketRequest->name === NULL || $ticketRequest->name == '') { + $validationModel->errorKeys[] = 'NO_NAME'; + } + + if (!Validators::validateEmail($ticketRequest->email, $heskSettings['multi_eml'], false)) { + $validationModel->errorKeys[] = 'INVALID_OR_MISSING_EMAIL'; + } + + $categoryId = intval($ticketRequest->category); + if ($categoryId < 1) { + $validationModel->errorKeys[] = 'NO_CATEGORY'; + } else { + $categoryExists = array_key_exists($categoryId, $this->categoryRetriever->getAllCategories($heskSettings, $userContext)); + if (!$categoryExists) { + $validationModel->errorKeys[] = 'CATEGORY_DOES_NOT_EXIST'; + } + } + + //-- TODO assert priority exists + + if ($heskSettings['cust_urgency'] && intval($ticketRequest->priority) === $TICKET_PRIORITY_CRITICAL) { + $validationModel->errorKeys[] = 'CRITICAL_PRIORITY_FORBIDDEN'; + } + + if ($heskSettings['require_subject'] === 1 && + ($ticketRequest->subject === NULL || $ticketRequest->subject === '')) { + $validationModel->errorKeys[] = 'SUBJECT_REQUIRED'; + } + + if ($heskSettings['require_message'] === 1 && + ($ticketRequest->message === NULL || $ticketRequest->message === '')) { + $validationModel->errorKeys[] = 'MESSAGE_REQUIRED'; + } + + foreach ($heskSettings['custom_fields'] as $key => $value) { + $customFieldNumber = intval(str_replace('custom', '', $key)); + if ($value['use'] == 1 && CustomFieldValidator::isCustomFieldInCategory($customFieldNumber, intval($ticketRequest->category), false, $heskSettings)) { + $custom_field_value = $ticketRequest->customFields[$customFieldNumber]; + if (empty($custom_field_value)) { + $validationModel->errorKeys[] = "CUSTOM_FIELD_{$customFieldNumber}_INVALID::NO_VALUE"; + continue; + } + switch($value['type']) { + case CustomField::DATE: + if (!preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $custom_field_value)) { + $validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $customFieldNumber . '_INVALID::INVALID_DATE'; + } else { + // Actually validate based on range + $date = strtotime($custom_field_value . ' t00:00:00'); + $dmin = strlen($value['value']['dmin']) ? strtotime($value['value']['dmin'] . ' t00:00:00') : false; + $dmax = strlen($value['value']['dmax']) ? strtotime($value['value']['dmax'] . ' t00:00:00') : false; + + if ($dmin && $dmin > $date) { + $validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $customFieldNumber . '_INVALID::DATE_BEFORE_MIN::MIN:' . date('Y-m-d', $dmin) . '::ENTERED:' . date('Y-m-d', $date); + } elseif ($dmax && $dmax < $date) { + $validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $customFieldNumber . '_INVALID::DATE_AFTER_MAX::MAX:' . date('Y-m-d', $dmax) . '::ENTERED:' . date('Y-m-d', $date); + } + } + break; + case CustomField::EMAIL: + if (!Validators::validateEmail($custom_field_value, $value['value']['multiple'], false)) { + $validationModel->errorKeys[] = "CUSTOM_FIELD_{$customFieldNumber}_INVALID::INVALID_EMAIL"; + } + break; + } + } + } + + if ($this->banRetriever->isEmailBanned($ticketRequest->email, $heskSettings)) { + $validationModel->errorKeys[] = 'EMAIL_BANNED'; + } + + if ($this->ticketValidators->isCustomerAtMaxTickets($ticketRequest->email, $heskSettings)) { + $validationModel->errorKeys[] = 'EMAIL_AT_MAX_OPEN_TICKETS'; + } + + return $validationModel; + } +} \ No newline at end of file diff --git a/api/BusinessLogic/Tickets/TicketCreator.php b/api/BusinessLogic/Tickets/TicketCreator.php index b7be8613..0c6b506e 100644 --- a/api/BusinessLogic/Tickets/TicketCreator.php +++ b/api/BusinessLogic/Tickets/TicketCreator.php @@ -2,33 +2,29 @@ namespace BusinessLogic\Tickets; - -use BusinessLogic\Categories\CategoryRetriever; use BusinessLogic\Exceptions\ValidationException; -use BusinessLogic\Security\BanRetriever; -use BusinessLogic\Tickets\CustomFields\CustomFieldValidator; -use BusinessLogic\ValidationModel; -use BusinessLogic\Validators; -use Core\Constants\CustomField; +use DataAccess\Tickets\TicketGateway; class TicketCreator { /** - * @var $categoryRetriever CategoryRetriever + * @var $newTicketValidator NewTicketValidator */ - private $categoryRetriever; - /** - * @var $banRetriever BanRetriever - */ - private $banRetriever; - /** - * @var $ticketValidators TicketValidators - */ - private $ticketValidators; + private $newTicketValidator; - function __construct($categoryRetriever, $banRetriever, $ticketValidators) { - $this->categoryRetriever = $categoryRetriever; - $this->banRetriever = $banRetriever; - $this->ticketValidators = $ticketValidators; + /** + * @var $trackingIdGenerator TrackingIdGenerator + */ + private $trackingIdGenerator; + + /** + * @var $ticketGateway TicketGateway + */ + private $ticketGateway; + + function __construct($newTicketValidator, $trackingIdGenerator, $ticketGateway) { + $this->newTicketValidator = $newTicketValidator; + $this->trackingIdGenerator = $trackingIdGenerator; + $this->ticketGateway = $ticketGateway; } /** @@ -37,11 +33,12 @@ class TicketCreator { * @param $ticketRequest CreateTicketByCustomerModel * @param $heskSettings array HESK settings * @param $modsForHeskSettings array Mods for HESK settings + * @return Ticket The newly created ticket * @throws ValidationException When a required field in $ticket_request is missing * */ function createTicketByCustomer($ticketRequest, $heskSettings, $modsForHeskSettings, $userContext) { - $validationModel = $this->validate($ticketRequest, false, $heskSettings, $modsForHeskSettings, $userContext); + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($ticketRequest, $heskSettings, $userContext); if (count($validationModel->errorKeys) > 0) { // Validation failed @@ -50,113 +47,19 @@ class TicketCreator { } // Create the ticket - //-- TODO Get tracking ID - - //-- TODO handle message + $ticket = new Ticket(); + $ticket->trackingId = $this->trackingIdGenerator->generateTrackingId($heskSettings); //-- TODO suggested kb articles - //-- TODO autoassign logic + //-- TODO owner/autoassign logic //-- TODO latitude/longitude //-- TODO HTML flag - //-- TODO Screen res / user agent + $this->ticketGateway->createTicket($ticket, $heskSettings); - //-- TODO Should ticket validation exist? - - //-- TODO Create the ticket - - //-- TODO return the freshly created ticket. Any extra stuff the web side does will be handled in submit_ticket.php - } - - /** - * @param $ticketRequest CreateTicketByCustomerModel - * @param $staff bool - * @param $heskSettings array HESK settings - * @param $modsForHeskSettings array Mods for HESK settings - * @return ValidationModel If errorKeys is empty, validation successful. Otherwise invalid ticket - */ - function validate($ticketRequest, $staff, $heskSettings, $modsForHeskSettings, $userContext) { - $TICKET_PRIORITY_CRITICAL = 0; - - $validationModel = new ValidationModel(); - - if ($ticketRequest->name === NULL || $ticketRequest->name == '') { - $validationModel->errorKeys[] = 'NO_NAME'; - } - - if (!Validators::validateEmail($ticketRequest->email, $heskSettings['multi_eml'], false)) { - $validationModel->errorKeys[] = 'INVALID_OR_MISSING_EMAIL'; - } - - $categoryId = intval($ticketRequest->category); - if ($categoryId < 1) { - $validationModel->errorKeys[] = 'NO_CATEGORY'; - } else { - $categoryExists = array_key_exists($categoryId, $this->categoryRetriever->getAllCategories($heskSettings, $userContext)); - if (!$categoryExists) { - $validationModel->errorKeys[] = 'CATEGORY_DOES_NOT_EXIST'; - } - } - - if ($heskSettings['cust_urgency'] && intval($ticketRequest->priority) === $TICKET_PRIORITY_CRITICAL) { - $validationModel->errorKeys[] = 'CRITICAL_PRIORITY_FORBIDDEN'; - } - - if ($heskSettings['require_subject'] === 1 && - ($ticketRequest->subject === NULL || $ticketRequest->subject === '')) { - $validationModel->errorKeys[] = 'SUBJECT_REQUIRED'; - } - - if ($heskSettings['require_message'] === 1 && - ($ticketRequest->message === NULL || $ticketRequest->message === '')) { - $validationModel->errorKeys[] = 'MESSAGE_REQUIRED'; - } - - foreach ($heskSettings['custom_fields'] as $key => $value) { - $customFieldNumber = intval(str_replace('custom', '', $key)); - if ($value['use'] == 1 && CustomFieldValidator::isCustomFieldInCategory($customFieldNumber, intval($ticketRequest->category), false, $heskSettings)) { - $custom_field_value = $ticketRequest->customFields[$customFieldNumber]; - if (empty($custom_field_value)) { - $validationModel->errorKeys[] = "CUSTOM_FIELD_{$customFieldNumber}_INVALID::NO_VALUE"; - continue; - } - switch($value['type']) { - case CustomField::DATE: - if (!preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $custom_field_value)) { - $validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $customFieldNumber . '_INVALID::INVALID_DATE'; - } else { - // Actually validate based on range - $date = strtotime($custom_field_value . ' t00:00:00'); - $dmin = strlen($value['value']['dmin']) ? strtotime($value['value']['dmin'] . ' t00:00:00') : false; - $dmax = strlen($value['value']['dmax']) ? strtotime($value['value']['dmax'] . ' t00:00:00') : false; - - if ($dmin && $dmin > $date) { - $validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $customFieldNumber . '_INVALID::DATE_BEFORE_MIN::MIN:' . date('Y-m-d', $dmin) . '::ENTERED:' . date('Y-m-d', $date); - } elseif ($dmax && $dmax < $date) { - $validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $customFieldNumber . '_INVALID::DATE_AFTER_MAX::MAX:' . date('Y-m-d', $dmax) . '::ENTERED:' . date('Y-m-d', $date); - } - } - break; - case CustomField::EMAIL: - if (!Validators::validateEmail($custom_field_value, $value['value']['multiple'], false)) { - $validationModel->errorKeys[] = "CUSTOM_FIELD_{$customFieldNumber}_INVALID::INVALID_EMAIL"; - } - break; - } - } - } - - if ($this->banRetriever->isEmailBanned($ticketRequest->email, $heskSettings)) { - $validationModel->errorKeys[] = 'EMAIL_BANNED'; - } - - if ($this->ticketValidators->isCustomerAtMaxTickets($ticketRequest->email, $heskSettings)) { - $validationModel->errorKeys[] = 'EMAIL_AT_MAX_OPEN_TICKETS'; - } - - return $validationModel; + return $ticket; } } \ No newline at end of file diff --git a/api/BusinessLogic/Tickets/TrackingIdGenerator.php b/api/BusinessLogic/Tickets/TrackingIdGenerator.php index a97811ca..25cbe010 100644 --- a/api/BusinessLogic/Tickets/TrackingIdGenerator.php +++ b/api/BusinessLogic/Tickets/TrackingIdGenerator.php @@ -19,6 +19,7 @@ class TrackingIdGenerator { /** * @param $heskSettings array * @return string + * @throws UnableToGenerateTrackingIdException */ function generateTrackingId($heskSettings) { $acceptableCharacters = 'AEUYBDGHJLMNPQRSTVWXZ123456789'; diff --git a/api/Tests/BusinessLogic/Tickets/NewTicketValidatorTest.php b/api/Tests/BusinessLogic/Tickets/NewTicketValidatorTest.php new file mode 100644 index 00000000..de978568 --- /dev/null +++ b/api/Tests/BusinessLogic/Tickets/NewTicketValidatorTest.php @@ -0,0 +1,432 @@ +banRetriever = $this->createMock(BanRetriever::class); + $this->categoryRetriever = $this->createMock(CategoryRetriever::class); + $this->ticketValidators = $this->createMock(TicketValidators::class); + $this->newTicketValidator = new NewTicketValidator($this->categoryRetriever, $this->banRetriever, $this->ticketValidators); + $this->userContext = new UserContext(); + + $this->ticketRequest = new CreateTicketByCustomerModel(); + $this->ticketRequest->name = 'Name'; + $this->ticketRequest->email = 'some@e.mail'; + $this->ticketRequest->category = 1; + $this->ticketRequest->priority = Priority::HIGH; + $this->ticketRequest->subject = 'Subject'; + $this->ticketRequest->message = 'Message'; + $this->ticketRequest->customFields = array(); + $this->heskSettings = array( + 'multi_eml' => false, + 'cust_urgency' => false, + 'require_subject' => 1, + 'require_message' => 1, + 'custom_fields' => array(), + ); + + $category = new Category(); + $category->accessible = true; + $category->id = 1; + $categories = array(); + $categories[1] = $category; + $this->categoryRetriever->method('getAllCategories') + ->willReturn($categories); + } + + function testItAddsTheProperValidationErrorWhenNameIsNull() { + //-- Arrange + $this->ticketRequest->name = null; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['NO_NAME'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenNameIsBlank() { + //-- Arrange + $this->ticketRequest->name = ''; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['NO_NAME'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenEmailIsNull() { + //-- Arrange + $this->ticketRequest->email = null; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['INVALID_OR_MISSING_EMAIL'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenEmailIsBlank() { + //-- Arrange + $this->ticketRequest->email = ''; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['INVALID_OR_MISSING_EMAIL'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenEmailIsInvalid() { + //-- Arrange + $this->ticketRequest->email = 'something@'; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['INVALID_OR_MISSING_EMAIL'], $validationModel->errorKeys); + } + + function testItSupportsMultipleEmails() { + //-- Arrange + $this->ticketRequest->email = 'something@email.com;another@valid.email'; + $this->heskSettings['multi_eml'] = true; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertThat($validationModel->valid, $this->isTrue()); + } + + function testItAddsTheProperValidationErrorWhenCategoryIsNotANumber() { + //-- Arrange + $this->ticketRequest->category = 'something'; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['NO_CATEGORY'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenCategoryIsNegative() { + //-- Arrange + $this->ticketRequest->category = -5; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['NO_CATEGORY'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCategoryDoesNotExist() { + //-- Arrange + $this->ticketRequest->category = 10; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['CATEGORY_DOES_NOT_EXIST'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithPriorityCritical() { + //-- Arrange + $this->ticketRequest->priority = Priority::CRITICAL; + $this->heskSettings['cust_urgency'] = true; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['CRITICAL_PRIORITY_FORBIDDEN'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithNullSubjectAndItIsRequired() { + //-- Arrange + $this->ticketRequest->subject = null; + $this->heskSettings['require_subject'] = 1; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['SUBJECT_REQUIRED'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithBlankSubjectAndItIsRequired() { + //-- Arrange + $this->ticketRequest->subject = ''; + $this->heskSettings['require_subject'] = 1; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['SUBJECT_REQUIRED'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithNullMessageAndItIsRequired() { + //-- Arrange + $this->ticketRequest->message = null; + $this->heskSettings['require_message'] = 1; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['MESSAGE_REQUIRED'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithBlankMessageAndItIsRequired() { + //-- Arrange + $this->ticketRequest->message = ''; + $this->heskSettings['require_message'] = 1; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['MESSAGE_REQUIRED'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithNullRequiredCustomField() { + //-- Arrange + $customField = array(); + $customField['req'] = 1; + $customField['type'] = CustomField::TEXT; + $customField['use'] = 1; + $customField['category'] = array(); + $this->heskSettings['custom_fields']['custom1'] = $customField; + $this->ticketRequest->customFields[1] = null; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::NO_VALUE'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithBlankRequiredCustomField() { + //-- Arrange + $customField = array(); + $customField['req'] = 1; + $customField['type'] = CustomField::TEXT; + $customField['use'] = 1; + $customField['category'] = array(); + $this->heskSettings['custom_fields']['custom1'] = $customField; + $this->ticketRequest->customFields[1] = ''; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::NO_VALUE'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithDateCustomFieldThatIsInvalid() { + //-- Arrange + $customField = array(); + $customField['req'] = 1; + $customField['type'] = CustomField::DATE; + $customField['use'] = 1; + $customField['category'] = array(); + $this->heskSettings['custom_fields']['custom1'] = $customField; + $this->ticketRequest->customFields[1] = '2017-30-00'; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::INVALID_DATE'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithDateThatIsBeforeMinDate() { + //-- Arrange + $customField = array(); + $customField['req'] = 1; + $customField['type'] = CustomField::DATE; + $customField['use'] = 1; + $customField['category'] = array(); + $customField['value'] = array( + 'dmin' => '2017-01-01', + 'dmax' => '' + ); + $this->heskSettings['custom_fields']['custom1'] = $customField; + $this->ticketRequest->customFields[1] = '2016-12-31'; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::DATE_BEFORE_MIN::MIN:2017-01-01::ENTERED:2016-12-31'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithDateThatIsAfterMaxDate() { + //-- Arrange + $customField = array(); + $customField['req'] = 1; + $customField['type'] = CustomField::DATE; + $customField['use'] = 1; + $customField['category'] = array(); + $customField['value'] = array( + 'dmin' => '', + 'dmax' => '2017-01-01' + ); + $this->heskSettings['custom_fields']['custom1'] = $customField; + $this->ticketRequest->customFields[1] = '2017-01-02'; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::DATE_AFTER_MAX::MAX:2017-01-01::ENTERED:2017-01-02'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithEmailThatIsInvalid() { + //-- Arrange + $customField = array(); + $customField['req'] = 1; + $customField['type'] = CustomField::EMAIL; + $customField['use'] = 1; + $customField['category'] = array(); + $customField['value'] = array( + 'multiple' => 0 + ); + $this->heskSettings['custom_fields']['custom1'] = $customField; + $this->ticketRequest->customFields[1] = 'invalid@'; + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::INVALID_EMAIL'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithABannedEmail() { + //-- Arrange + $this->ticketRequest->email = 'some@banned.email'; + $this->banRetriever->method('isEmailBanned') + ->with($this->ticketRequest->email, $this->heskSettings) + ->willReturn(true); + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['EMAIL_BANNED'], $validationModel->errorKeys); + } + + function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWhenTheyAreMaxedOut() { + //-- Arrange + $this->ticketRequest->email = 'some@maxedout.email'; + $this->ticketValidators->method('isCustomerAtMaxTickets') + ->with($this->ticketRequest->email, $this->heskSettings) + ->willReturn(true); + + //-- Act + $validationModel = $this->newTicketValidator->validateNewTicketForCustomer($this->ticketRequest, + $this->heskSettings, + $this->userContext); + + //-- Assert + $this->assertArraySubset(['EMAIL_AT_MAX_OPEN_TICKETS'], $validationModel->errorKeys); + } +} diff --git a/api/Tests/BusinessLogic/Tickets/TicketCreatorTest.php b/api/Tests/BusinessLogic/Tickets/TicketCreatorTest.php deleted file mode 100644 index 2098bee6..00000000 --- a/api/Tests/BusinessLogic/Tickets/TicketCreatorTest.php +++ /dev/null @@ -1,606 +0,0 @@ -banRetriever = $this->createMock(BanRetriever::class); - $this->categoryRetriever = $this->createMock(CategoryRetriever::class); - $this->ticketValidators = $this->createMock(TicketValidators::class); - $this->ticketCreator = new TicketCreator($this->categoryRetriever, $this->banRetriever, $this->ticketValidators); - $this->userContext = new UserContext(); - - $this->ticketRequest = new CreateTicketByCustomerModel(); - $this->ticketRequest->name = 'Name'; - $this->ticketRequest->email = 'some@e.mail'; - $this->ticketRequest->category = 1; - $this->ticketRequest->priority = Priority::HIGH; - $this->ticketRequest->subject = 'Subject'; - $this->ticketRequest->message = 'Message'; - $this->ticketRequest->customFields = array(); - $this->heskSettings = array( - 'multi_eml' => false, - 'cust_urgency' => false, - 'require_subject' => 1, - 'require_message' => 1, - 'custom_fields' => array(), - ); - - $category = new Category(); - $category->accessible = true; - $category->id = 1; - $categories = array(); - $categories[1] = $category; - $this->categoryRetriever->method('getAllCategories') - ->willReturn($categories); - } - - function testItAddsTheProperValidationErrorWhenNameIsNull() { - //-- Arrange - $this->ticketRequest->name = null; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['NO_NAME'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenNameIsBlank() { - //-- Arrange - $this->ticketRequest->name = ''; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['NO_NAME'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenEmailIsNull() { - //-- Arrange - $this->ticketRequest->email = null; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['INVALID_OR_MISSING_EMAIL'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenEmailIsBlank() { - //-- Arrange - $this->ticketRequest->email = ''; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['INVALID_OR_MISSING_EMAIL'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenEmailIsInvalid() { - //-- Arrange - $this->ticketRequest->email = 'something@'; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['INVALID_OR_MISSING_EMAIL'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItSupportsMultipleEmails() { - //-- Arrange - $this->ticketRequest->email = 'something@email.com;another@valid.email'; - $this->heskSettings['multi_eml'] = true; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - var_dump($e->validationModel->errorKeys); - $this->fail('Should not have thrown a ValidationException! Validation error keys are above.'); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(false)); - } - - function testItAddsTheProperValidationErrorWhenCategoryIsNotANumber() { - //-- Arrange - $this->ticketRequest->category = 'something'; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['NO_CATEGORY'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenCategoryIsNegative() { - //-- Arrange - $this->ticketRequest->category = -5; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['NO_CATEGORY'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCategoryDoesNotExist() { - //-- Arrange - $this->ticketRequest->category = 10; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['CATEGORY_DOES_NOT_EXIST'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithPriorityCritical() { - //-- Arrange - $this->ticketRequest->priority = Priority::CRITICAL; - $this->heskSettings['cust_urgency'] = true; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['CRITICAL_PRIORITY_FORBIDDEN'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithNullSubjectAndItIsRequired() { - //-- Arrange - $this->ticketRequest->subject = null; - $this->heskSettings['require_subject'] = 1; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['SUBJECT_REQUIRED'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithBlankSubjectAndItIsRequired() { - //-- Arrange - $this->ticketRequest->subject = ''; - $this->heskSettings['require_subject'] = 1; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['SUBJECT_REQUIRED'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithNullMessageAndItIsRequired() { - //-- Arrange - $this->ticketRequest->message = null; - $this->heskSettings['require_message'] = 1; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['MESSAGE_REQUIRED'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithBlankMessageAndItIsRequired() { - //-- Arrange - $this->ticketRequest->message = ''; - $this->heskSettings['require_message'] = 1; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['MESSAGE_REQUIRED'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithNullRequiredCustomField() { - //-- Arrange - $customField = array(); - $customField['req'] = 1; - $customField['type'] = CustomField::TEXT; - $customField['use'] = 1; - $customField['category'] = array(); - $this->heskSettings['custom_fields']['custom1'] = $customField; - $this->ticketRequest->customFields[1] = null; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::NO_VALUE'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithBlankRequiredCustomField() { - //-- Arrange - $customField = array(); - $customField['req'] = 1; - $customField['type'] = CustomField::TEXT; - $customField['use'] = 1; - $customField['category'] = array(); - $this->heskSettings['custom_fields']['custom1'] = $customField; - $this->ticketRequest->customFields[1] = ''; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::NO_VALUE'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithDateCustomFieldThatIsInvalid() { - //-- Arrange - $customField = array(); - $customField['req'] = 1; - $customField['type'] = CustomField::DATE; - $customField['use'] = 1; - $customField['category'] = array(); - $this->heskSettings['custom_fields']['custom1'] = $customField; - $this->ticketRequest->customFields[1] = '2017-30-00'; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::INVALID_DATE'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithDateThatIsBeforeMinDate() { - //-- Arrange - $customField = array(); - $customField['req'] = 1; - $customField['type'] = CustomField::DATE; - $customField['use'] = 1; - $customField['category'] = array(); - $customField['value'] = array( - 'dmin' => '2017-01-01', - 'dmax' => '' - ); - $this->heskSettings['custom_fields']['custom1'] = $customField; - $this->ticketRequest->customFields[1] = '2016-12-31'; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::DATE_BEFORE_MIN::MIN:2017-01-01::ENTERED:2016-12-31'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithDateThatIsAfterMaxDate() { - //-- Arrange - $customField = array(); - $customField['req'] = 1; - $customField['type'] = CustomField::DATE; - $customField['use'] = 1; - $customField['category'] = array(); - $customField['value'] = array( - 'dmin' => '', - 'dmax' => '2017-01-01' - ); - $this->heskSettings['custom_fields']['custom1'] = $customField; - $this->ticketRequest->customFields[1] = '2017-01-02'; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::DATE_AFTER_MAX::MAX:2017-01-01::ENTERED:2017-01-02'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithEmailThatIsInvalid() { - //-- Arrange - $customField = array(); - $customField['req'] = 1; - $customField['type'] = CustomField::EMAIL; - $customField['use'] = 1; - $customField['category'] = array(); - $customField['value'] = array( - 'multiple' => 0 - ); - $this->heskSettings['custom_fields']['custom1'] = $customField; - $this->ticketRequest->customFields[1] = 'invalid@'; - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['CUSTOM_FIELD_1_INVALID::INVALID_EMAIL'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWithABannedEmail() { - //-- Arrange - $this->ticketRequest->email = 'some@banned.email'; - $this->banRetriever->method('isEmailBanned') - ->with($this->ticketRequest->email, $this->heskSettings) - ->willReturn(true); - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['EMAIL_BANNED'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } - - function testItAddsTheProperValidationErrorWhenTheCustomerSubmitsTicketWhenTheyAreMaxedOut() { - //-- Arrange - $this->ticketRequest->email = 'some@maxedout.email'; - $this->ticketValidators->method('isCustomerAtMaxTickets') - ->with($this->ticketRequest->email, $this->heskSettings) - ->willReturn(true); - - //-- Act - $exceptionThrown = false; - try { - $this->ticketCreator->createTicketByCustomer($this->ticketRequest, - $this->heskSettings, - $this->modsForHeskSettings, - $this->userContext); - } catch (ValidationException $e) { - //-- Assert (1/2) - $exceptionThrown = true; - $this->assertArraySubset(['EMAIL_AT_MAX_OPEN_TICKETS'], $e->validationModel->errorKeys); - } - - //-- Assert (2/2) - $this->assertThat($exceptionThrown, $this->equalTo(true)); - } -} diff --git a/api/Tests/BusinessLogic/Tickets/TicketCreatorTests/CreateTicketForCustomerTest.php b/api/Tests/BusinessLogic/Tickets/TicketCreatorTests/CreateTicketForCustomerTest.php new file mode 100644 index 00000000..f46f8faf --- /dev/null +++ b/api/Tests/BusinessLogic/Tickets/TicketCreatorTests/CreateTicketForCustomerTest.php @@ -0,0 +1,108 @@ +ticketGateway = $this->createMock(TicketGateway::class); + $this->newTicketValidator = $this->createMock(NewTicketValidator::class); + $this->trackingIdGenerator = $this->createMock(TrackingIdGenerator::class); + + $this->ticketCreator = new TicketCreator($this->newTicketValidator, $this->trackingIdGenerator, $this->ticketGateway); + + $this->ticketRequest = new CreateTicketByCustomerModel(); + $this->ticketRequest->name = 'Name'; + $this->ticketRequest->email = 'some@e.mail'; + $this->ticketRequest->category = 1; + $this->ticketRequest->priority = Priority::HIGH; + $this->ticketRequest->subject = 'Subject'; + $this->ticketRequest->message = 'Message'; + $this->ticketRequest->customFields = array(); + $this->heskSettings = array( + 'multi_eml' => false, + 'cust_urgency' => false, + 'require_subject' => 1, + 'require_message' => 1, + 'custom_fields' => array(), + ); + $this->modsForHeskSettings = array(); + $this->userContext = new UserContext(); + + $this->newTicketValidator->method('validateNewTicketForCustomer')->willReturn(new ValidationModel()); + $this->trackingIdGenerator->method('generateTrackingId')->willReturn('123-456-7890'); + } + + function testItSavesTheTicketToTheDatabase() { + //-- Assert + $this->ticketGateway->expects($this->once())->method('createTicket'); + + //-- Act + $this->ticketCreator->createTicketByCustomer($this->ticketRequest, $this->heskSettings, $this->modsForHeskSettings, $this->userContext); + } + + function testItSetsTheTrackingIdOnTheTicket() { + //-- Act + $ticket = $this->ticketCreator->createTicketByCustomer($this->ticketRequest, $this->heskSettings, $this->modsForHeskSettings, $this->userContext); + + //-- Assert + self::assertThat($ticket->trackingId, self::equalTo('123-456-7890')); + } +}