diff --git a/README.md b/README.md index 0b82b81..bfa9f87 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,8 @@ $uploadResponse = $connector->send( $token = $uploadResponse->dto()->token; +// And to pass to your ticket request + $ticketResponse = $connector->send( new CreateSingleTicketRequest( SingleTicketDTO::fromArray([ diff --git a/src/ZendeskConnector.php b/src/ZendeskConnector.php index 4face32..04e5da1 100644 --- a/src/ZendeskConnector.php +++ b/src/ZendeskConnector.php @@ -26,6 +26,12 @@ protected function defaultHeaders(): array } protected function defaultAuth(): ?Authenticator + { + $authenticationString = $this->setAuth(); + return new TokenAuthenticator(base64_encode($authenticationString), 'Basic'); + } + + public function setAuth(): string { if (! config('zendesk.auth.method')) { throw new \Exception('No authentication method provided.', 500); @@ -47,12 +53,10 @@ protected function defaultAuth(): ?Authenticator throw new \Exception('No API token provided for token authentication.', 500); } - $authenticationString = match (config('zendesk.auth.method')) { - 'basic' => $authenticationString = config('zendesk.auth.email_address').':'.config('zendesk.auth.password'), - 'token' => $authenticationString = config('zendesk.auth.email_address').'/token:'.config('zendesk.auth.api_token'), + return match (config('zendesk.auth.method')) { + 'basic' => config('zendesk.auth.email_address').':'.config('zendesk.auth.password'), + 'token' => config('zendesk.auth.email_address').'/token:'.config('zendesk.auth.api_token'), default => throw new \Exception('Invalid authentication method provided.', 500), }; - - return new TokenAuthenticator(base64_encode($authenticationString), 'Basic'); } } diff --git a/tests/Connectors/ZendeskConnectorTest.php b/tests/Connectors/ZendeskConnectorTest.php new file mode 100644 index 0000000..0d5b5f6 --- /dev/null +++ b/tests/Connectors/ZendeskConnectorTest.php @@ -0,0 +1,169 @@ +resolveBaseUrl(); + +})->throws('No subdomain provided.', 500); + +it('will not throw an exception if a subdomain is set', closure: function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag' + ]); + + $connector = new ZendeskConnector; + $connector->resolveBaseUrl(); + +})->expectNotToPerformAssertions(); + +it('will return the base path', closure: function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag' + ]); + + $connector = new ZendeskConnector; + $path = $connector->resolveBaseUrl(); + + expect($path)->toBe('https://codebarsolutionsag.zendesk.com/api/v2'); + +}); + + +it('will throw an exception if an auth method is not set', closure: function () { + config([ + 'zendesk.auth.method' => null, + ]); + + $connector = new ZendeskConnector; + $connector->setAuth(); + +})->throws('No authentication method provided.', 500); + +it('will throw an exception if an auth method invalid', closure: function () { + config([ + 'zendesk.auth.method' => 'not-a-valid-method', + ]); + + $connector = new ZendeskConnector; + $connector->setAuth(); + +})->throws('Invalid authentication method provided.', 500); + +it('will not throw an exception if an auth method valid', closure: function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag', + 'zendesk.auth.email_address' => 'test@example.com', + 'zendesk.auth.api_token' => 'test-token', + 'zendesk.auth.password' => 'test-password', + ]); + + + config([ + 'zendesk.auth.method' => 'token', + ]); + + $connector = new ZendeskConnector; + $connector->setAuth(); + + config([ + 'zendesk.auth.method' => 'basic', + ]); + + $connector = new ZendeskConnector; + $connector->setAuth(); + +})->expectNotToPerformAssertions(); + +it('will throw an exception if a token is not provided when using the token method', closure: function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag', + 'zendesk.auth.method' => 'token', + 'zendesk.auth.email_address' => 'test@example.com', + 'zendesk.auth.api_token' => null, + 'zendesk.auth.password' => null, + ]); + + $connector = new ZendeskConnector; + $connector->setAuth(); + +})->throws('No API token provided for token authentication.', 500); + +it('will not throw an exception if a token is provided when using the token method', closure: function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag', + 'zendesk.auth.method' => 'token', + 'zendesk.auth.email_address' => 'test@example.com', + 'zendesk.auth.api_token' => 'test-token', + 'zendesk.auth.password' => null, + ]); + + $connector = new ZendeskConnector; + $connector->setAuth(); + +})->expectNotToPerformAssertions(); + +it('will throw an exception if a password is not provided when using the basic method', closure: function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag', + 'zendesk.auth.method' => 'basic', + 'zendesk.auth.email_address' => 'test@example.com', + 'zendesk.auth.api_token' => null, + 'zendesk.auth.password' => null, + ]); + + $connector = new ZendeskConnector; + $connector->setAuth(); + +})->throws('No password provided for basic authentication.', 500); + +it('will not throw an exception if a password is provided when using the password method', closure: function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag', + 'zendesk.auth.method' => 'basic', + 'zendesk.auth.email_address' => 'test@example.com', + 'zendesk.auth.api_token' => null, + 'zendesk.auth.password' => 'test-password', + ]); + + $connector = new ZendeskConnector; + $connector->setAuth(); + +})->expectNotToPerformAssertions(); + +it('will compile the correct authentication string for token method', function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag', + 'zendesk.auth.method' => 'token', + 'zendesk.auth.email_address' => 'test@example.com', + 'zendesk.auth.api_token' => 'test-token', + 'zendesk.auth.password' => null, + ]); + + $connector = new ZendeskConnector; + + $token = $connector->setAuth(); + + expect($token)->toBe('test@example.com/token:test-token'); +}); + +it('will compile the correct authentication string for basic method', function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag', + 'zendesk.auth.method' => 'basic', + 'zendesk.auth.email_address' => 'test@example.com', + 'zendesk.auth.api_token' => null, + 'zendesk.auth.password' => 'test-password', + ]); + + $connector = new ZendeskConnector; + + $token = $connector->setAuth(); + + expect($token)->toBe('test@example.com:test-password'); +}); diff --git a/tests/Fixtures/Files/test.png b/tests/Fixtures/Files/test.png new file mode 100644 index 0000000..372c2a2 Binary files /dev/null and b/tests/Fixtures/Files/test.png differ diff --git a/tests/Fixtures/Saloon/all-tickets-request.json b/tests/Fixtures/Saloon/all-tickets-request.json new file mode 100644 index 0000000..9b1059f --- /dev/null +++ b/tests/Fixtures/Saloon/all-tickets-request.json @@ -0,0 +1,38 @@ +{ + "statusCode": 200, + "headers": { + "Date": "Mon, 03 Jul 2023 11:31:03 GMT", + "Content-Type": "application\/json; charset=utf-8", + "Transfer-Encoding": "chunked", + "Connection": "keep-alive", + "x-zendesk-api-version": "v2", + "x-zendesk-application-version": "v17438", + "x-frame-options": "SAMEORIGIN", + "zendesk-rate-limit-tickets-index": "total=100; remaining=99; resets=57", + "x-rate-limit": "400", + "rate-limit": "400", + "x-rate-limit-remaining": "399", + "rate-limit-remaining": "399", + "rate-limit-reset": "57", + "strict-transport-security": "max-age=31536000;", + "etag": "W\/\"8cdd07d5c75ffd1b225da69dee7e9985\"", + "cache-control": "max-age=0, private, must-revalidate", + "x-zendesk-origin-server": "classic-app-server-6fc8db697c-cgrcj", + "set-cookie": [ + "_zendesk_cookie=BAhJIhl7ImRldmljZV90b2tlbnMiOnt9fQY6BkVU--0bf2100788cb010d0183feca16aaf88ccaf719ca; path=\/; expires=Wed, 03 Jul 2024 04:36:17 GMT; secure; HttpOnly; SameSite=None", + "__cfruid=96c8e6e12fd2ae1a1fb6295fcc3d95a8a1bb0890-1688383863; path=\/; domain=.codebarsolutionsag.zendesk.com; HttpOnly; Secure; SameSite=None" + ], + "x-request-id": [ + "7e0eccc609fa7692-LHR", + "7e0eccc609fa7692-LHR" + ], + "x-runtime": "0.124075", + "X-Zendesk-Zorg": "yes", + "CF-Cache-Status": "DYNAMIC", + "Report-To": "{\"endpoints\":[{\"url\":\"https:\\\/\\\/a.nel.cloudflare.com\\\/report\\\/v3?s=FrrIioe8zsDqyeop5JgV0cpPiCkfW62wcV7EiVd%2F0fYtWuHvzB5RW1ln%2FfyR4Zbuk7fIcfkLKjUQ8qj%2Fpi5htVqKXZJKY%2FMxVXu4YyHBaDW3pp6%2BIDFYAOAwYHwKH2cz1D0car5EemABOXu9BrdQog%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}", + "NEL": "{\"success_fraction\":0.01,\"report_to\":\"cf-nel\",\"max_age\":604800}", + "Server": "cloudflare", + "CF-RAY": "7e0eccc609fa7692-LHR" + }, + "data": "{\"tickets\":[{\"url\":\"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/tickets\/79.json\",\"id\":79,\"external_id\":null,\"via\":{\"channel\":\"api\",\"source\":{\"from\":{},\"to\":{},\"rel\":null}},\"created_at\":\"2023-07-01T12:50:02Z\",\"updated_at\":\"2023-07-01T13:05:54Z\",\"type\":null,\"subject\":\"Eine neue Anfrage der B\u00e4rtschi ist eingetroffen: Projekt #1.\",\"raw_subject\":\"Eine neue Anfrage der B\u00e4rtschi ist eingetroffen: Projekt #1.\",\"description\":\"Eine neue Anfrage der B\u00e4rtschi ist eingetroffen.\\n\\nAnfrage\\nIdentifikation 1\\nBemerkung asdasd\\nURL https:\/\/app.pv.test\/nova\/resources\/inquiries\/1\\nErstellt am 01.07.2023 14:21 Uhr\\n**Kunde**\\nKunden B\u00e4rtschi\\nKunden ID 437046\\nBenutzer ID 437046_ralph\\nBenutzername Ralph Senn\\n**Konfiguration**\\nName Projekt #1\\nDachform Sattel-\/Pultdach\\nMontage Aufdach\\nHerkunft Asiatisch\\nWechselrichter Typ String\\n**Adresse**\\nStrasse M\u00fchlematten 12\\nPLZ 4455\\nOrt Zunzgen\\nLand CH\",\"priority\":\"urgent\",\"status\":\"open\",\"recipient\":null,\"requester_id\":17145664265741,\"submitter_id\":17145664265741,\"assignee_id\":17145664265741,\"organization_id\":17145651654157,\"group_id\":17145664762125,\"collaborator_ids\":[],\"follower_ids\":[],\"email_cc_ids\":[],\"forum_topic_id\":null,\"problem_id\":null,\"has_incidents\":false,\"is_public\":true,\"due_at\":null,\"tags\":[],\"custom_fields\":[{\"id\":17146061349901,\"value\":null},{\"id\":17195718961677,\"value\":null},{\"id\":17195752153741,\"value\":null}],\"satisfaction_rating\":null,\"sharing_agreement_ids\":[],\"custom_status_id\":17145678334989,\"fields\":[{\"id\":17146061349901,\"value\":null},{\"id\":17195718961677,\"value\":null},{\"id\":17195752153741,\"value\":null}],\"followup_ids\":[],\"ticket_form_id\":17145664563725,\"brand_id\":17145651602957,\"allow_channelback\":false,\"allow_attachments\":true,\"from_messaging_channel\":false},{\"url\":\"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/tickets\/81.json\",\"id\":81,\"external_id\":null,\"via\":{\"channel\":\"api\",\"source\":{\"from\":{},\"to\":{},\"rel\":null}},\"created_at\":\"2023-07-03T11:16:03Z\",\"updated_at\":\"2023-07-03T11:16:05Z\",\"type\":null,\"subject\":\"My printer is on fire!\",\"raw_subject\":\"My printer is on fire!\",\"description\":\"The smoke is very colorful.\",\"priority\":\"urgent\",\"status\":\"open\",\"recipient\":null,\"requester_id\":17145664265741,\"submitter_id\":17145664265741,\"assignee_id\":17145664265741,\"organization_id\":17145651654157,\"group_id\":17145664762125,\"collaborator_ids\":[],\"follower_ids\":[],\"email_cc_ids\":[],\"forum_topic_id\":null,\"problem_id\":null,\"has_incidents\":false,\"is_public\":true,\"due_at\":null,\"tags\":[],\"custom_fields\":[{\"id\":17146061349901,\"value\":null},{\"id\":17195718961677,\"value\":\"Check field works\"},{\"id\":17195752153741,\"value\":\"Check field works number 2\"}],\"satisfaction_rating\":null,\"sharing_agreement_ids\":[],\"custom_status_id\":17145678334989,\"fields\":[{\"id\":17146061349901,\"value\":null},{\"id\":17195718961677,\"value\":\"Check field works\"},{\"id\":17195752153741,\"value\":\"Check field works number 2\"}],\"followup_ids\":[],\"ticket_form_id\":17145664563725,\"brand_id\":17145651602957,\"allow_channelback\":false,\"allow_attachments\":true,\"from_messaging_channel\":false}],\"next_page\":null,\"previous_page\":null,\"count\":2}" +} diff --git a/tests/Fixtures/Saloon/count-tickets-request.json b/tests/Fixtures/Saloon/count-tickets-request.json new file mode 100644 index 0000000..ec31ab3 --- /dev/null +++ b/tests/Fixtures/Saloon/count-tickets-request.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Date":"Mon, 03 Jul 2023 13:19:53 GMT","Content-Type":"application\/json; charset=utf-8","Transfer-Encoding":"chunked","Connection":"keep-alive","x-zendesk-api-version":"v2","x-zendesk-application-version":"v17438","x-frame-options":"SAMEORIGIN","x-rate-limit":"400","rate-limit":"400","x-rate-limit-remaining":"399","rate-limit-remaining":"399","rate-limit-reset":"7","strict-transport-security":"max-age=31536000;","etag":"W\/\"dd5b53a4c6c7cd54d9e75cb4d51c3a8a\"","cache-control":"max-age=0, private, must-revalidate","x-zendesk-origin-server":"classic-app-server-6fc8db697c-msbrs","set-cookie":["_zendesk_cookie=BAhJIhl7ImRldmljZV90b2tlbnMiOnt9fQY6BkVU--0bf2100788cb010d0183feca16aaf88ccaf719ca; path=\/; expires=Wed, 03 Jul 2024 04:36:28 GMT; secure; HttpOnly; SameSite=None","__cfruid=0e155e55bd96d1d52b7c0b19c4c735ae1b2e0d93-1688390393; path=\/; domain=.codebarsolutionsag.zendesk.com; HttpOnly; Secure; SameSite=None"],"x-request-id":["7e0f6c36fb797735-LHR","7e0f6c36fb797735-LHR"],"x-runtime":"0.073519","X-Zendesk-Zorg":"yes","CF-Cache-Status":"DYNAMIC","Report-To":"{\"endpoints\":[{\"url\":\"https:\\\/\\\/a.nel.cloudflare.com\\\/report\\\/v3?s=bl0dv422vOkNLREKNLdaQy5qTMuOaeDMK0kHOBFaaHa6bdBul%2FWMn6KIhIC1GeWb8Z5cXJMcbSVQhZgHH4KjUiJYs%2FFPWcZQD7vYwvy7SWODBlcd6FSqwVYFnq8ghN8Vq6a45PZLHAy2EtL2BEFDqg%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}","NEL":"{\"success_fraction\":0.01,\"report_to\":\"cf-nel\",\"max_age\":604800}","Server":"cloudflare","CF-RAY":"7e0f6c36fb797735-LHR"},"data":"{\"count\":{\"value\":4,\"refreshed_at\":\"2023-07-03T13:19:53+00:00\"}}"} \ No newline at end of file diff --git a/tests/Fixtures/Saloon/create-attachment-request.json b/tests/Fixtures/Saloon/create-attachment-request.json new file mode 100644 index 0000000..ad47a59 --- /dev/null +++ b/tests/Fixtures/Saloon/create-attachment-request.json @@ -0,0 +1,40 @@ +{ + "statusCode": 201, + "headers": { + "Date": "Mon, 03 Jul 2023 13:33:16 GMT", + "Content-Type": "application\/json; charset=utf-8", + "Content-Length": "2293", + "Connection": "keep-alive", + "x-zendesk-api-version": "v2", + "x-zendesk-application-version": "v17438", + "x-frame-options": "SAMEORIGIN", + "location": "https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/attachments\/17278923683597.json", + "access-control-allow-origin": "*", + "access-control-expose-headers": "X-Zendesk-API-Warn,X-Zendesk-User-Id,X-Zendesk-User-Session-Expires-At", + "x-rate-limit": "400", + "rate-limit": "400", + "x-rate-limit-remaining": "399", + "rate-limit-remaining": "399", + "rate-limit-reset": "44", + "strict-transport-security": "max-age=31536000;", + "etag": "W\/\"387b535ca927c3e885bc4ebf45675c64\"", + "cache-control": "max-age=0, private, must-revalidate", + "x-zendesk-origin-server": "classic-app-server-6fc8db697c-lbxfk", + "set-cookie": [ + "_zendesk_cookie=BAhJIhl7ImRldmljZV90b2tlbnMiOnt9fQY6BkVU--0bf2100788cb010d0183feca16aaf88ccaf719ca; path=\/; expires=Wed, 03 Jul 2024 07:05:39 GMT; secure; HttpOnly; SameSite=None", + "__cfruid=9a71e3de0932ad74b42e7fcf2ed091e67ad18b84-1688391196; path=\/; domain=.codebarsolutionsag.zendesk.com; HttpOnly; Secure; SameSite=None" + ], + "x-request-id": [ + "7e0f7fcbdbec7545-LHR", + "7e0f7fcbdbec7545-LHR" + ], + "x-runtime": "0.374089", + "X-Zendesk-Zorg": "yes", + "CF-Cache-Status": "DYNAMIC", + "Report-To": "{\"endpoints\":[{\"url\":\"https:\\\/\\\/a.nel.cloudflare.com\\\/report\\\/v3?s=TL6Q7BjsnUmgl8FO0vyKlypUJhEHM8ywbUzWFRH46niQLknkM8iDggX2mC7pWJJ8V8iBHBrGs0U8%2FGwAQEyClKMQMHTIDmcs%2Bl%2BlOH339vU0XQ%2FSAlPzIG1WkX6vs5k%2FCZCmES8PcDYJ0I44ZqeZIg%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}", + "NEL": "{\"success_fraction\":0.01,\"report_to\":\"cf-nel\",\"max_age\":604800}", + "Server": "cloudflare", + "CF-RAY": "7e0f7fcbdbec7545-LHR" + }, + "data": "{\"upload\":{\"token\":\"OPvgMbfg5Der4DYn66hTC31in\",\"expires_at\":\"2023-07-06T13:33:15Z\",\"attachments\":[{\"url\":\"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/attachments\/17278923683597.json\",\"id\":17278923683597,\"file_name\":\"test.png\",\"content_url\":\"https:\/\/codebarsolutionsag.zendesk.com\/attachments\/token\/52HCaRgRZM38MvaUuUQsYzhUA\/?name=test.png\",\"mapped_content_url\":\"https:\/\/codebarsolutionsag.zendesk.com\/attachments\/token\/52HCaRgRZM38MvaUuUQsYzhUA\/?name=test.png\",\"content_type\":\"image\/png\",\"size\":26271,\"width\":640,\"height\":360,\"inline\":false,\"deleted\":false,\"malware_access_override\":false,\"malware_scan_result\":\"not_scanned\",\"thumbnails\":[{\"url\":\"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/attachments\/17278921757709.json\",\"id\":17278921757709,\"file_name\":\"test_thumb.png\",\"content_url\":\"https:\/\/codebarsolutionsag.zendesk.com\/attachments\/token\/gvLU5FyT7CoKakThdKaxHwVNg\/?name=test_thumb.png\",\"mapped_content_url\":\"https:\/\/codebarsolutionsag.zendesk.com\/attachments\/token\/gvLU5FyT7CoKakThdKaxHwVNg\/?name=test_thumb.png\",\"content_type\":\"image\/png\",\"size\":1823,\"width\":80,\"height\":45,\"inline\":false,\"deleted\":false,\"malware_access_override\":false,\"malware_scan_result\":\"not_scanned\"}]}],\"attachment\":{\"url\":\"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/attachments\/17278923683597.json\",\"id\":17278923683597,\"file_name\":\"test.png\",\"content_url\":\"https:\/\/codebarsolutionsag.zendesk.com\/attachments\/token\/52HCaRgRZM38MvaUuUQsYzhUA\/?name=test.png\",\"mapped_content_url\":\"https:\/\/codebarsolutionsag.zendesk.com\/attachments\/token\/52HCaRgRZM38MvaUuUQsYzhUA\/?name=test.png\",\"content_type\":\"image\/png\",\"size\":26271,\"width\":640,\"height\":360,\"inline\":false,\"deleted\":false,\"malware_access_override\":false,\"malware_scan_result\":\"not_scanned\",\"thumbnails\":[{\"url\":\"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/attachments\/17278921757709.json\",\"id\":17278921757709,\"file_name\":\"test_thumb.png\",\"content_url\":\"https:\/\/codebarsolutionsag.zendesk.com\/attachments\/token\/gvLU5FyT7CoKakThdKaxHwVNg\/?name=test_thumb.png\",\"mapped_content_url\":\"https:\/\/codebarsolutionsag.zendesk.com\/attachments\/token\/gvLU5FyT7CoKakThdKaxHwVNg\/?name=test_thumb.png\",\"content_type\":\"image\/png\",\"size\":1823,\"width\":80,\"height\":45,\"inline\":false,\"deleted\":false,\"malware_access_override\":false,\"malware_scan_result\":\"not_scanned\"}]}}}" +} diff --git a/tests/Fixtures/Saloon/create-single-ticket-request.json b/tests/Fixtures/Saloon/create-single-ticket-request.json new file mode 100644 index 0000000..237fda8 --- /dev/null +++ b/tests/Fixtures/Saloon/create-single-ticket-request.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Date":"Mon, 03 Jul 2023 13:16:35 GMT","Content-Type":"application\/json; charset=utf-8","Content-Length":"3197","Connection":"keep-alive","x-zendesk-api-version":"v2","x-zendesk-application-version":"v17438","x-zendesk-api-warn":"{:allowed_parameters=>{:controller=>\"tickets\", :action=>\"create\", :unpermitted_keys=>[\"ticket.allow_attachments\", \"ticket.allow_channelback\", \"ticket.comment.attachments\", \"ticket.comment.audit_id\", \"ticket.comment.created_at\", \"ticket.comment.id\", \"ticket.comment.metadata\", \"ticket.comment.plain_body\", \"ticket.comment.type\", \"ticket.comment.via\", \"ticket.created_at\", \"ticket.email_cc_ids\", \"ticket.follower_ids\", \"ticket.followup_ids\", \"ticket.from_messaging_channel\", \"ticket.has_incidents\", \"ticket.id\", \"ticket.is_public\", \"ticket.self_update\", \"ticket.satisfaction_rating\", \"ticket.updated_at\"], :invalid_values=>[]}}","x-frame-options":"SAMEORIGIN","zendesk-ep":"-22","location":"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/tickets\/83.json","x-rate-limit":"400","rate-limit":"400","x-rate-limit-remaining":"399","rate-limit-remaining":"399","rate-limit-reset":"25","strict-transport-security":"max-age=31536000;","etag":"W\/\"3f19ce42212521a313aba3506dabd849\"","cache-control":"max-age=0, private, must-revalidate","x-zendesk-origin-server":"classic-app-server-6fc8db697c-vp95d","set-cookie":["_zendesk_cookie=BAhJIhl7ImRldmljZV90b2tlbnMiOnt9fQY6BkVU--0bf2100788cb010d0183feca16aaf88ccaf719ca; path=\/; expires=Wed, 03 Jul 2024 07:05:25 GMT; secure; HttpOnly; SameSite=None","__cfruid=212285535bde6012c576e4f7e5897005b752ea29-1688390195; path=\/; domain=.codebarsolutionsag.zendesk.com; HttpOnly; Secure; SameSite=None"],"x-request-id":["7e0f675b4829d168-LHR","7e0f675b4829d168-LHR"],"x-runtime":"0.490684","X-Zendesk-Zorg":"yes","CF-Cache-Status":"DYNAMIC","Report-To":"{\"endpoints\":[{\"url\":\"https:\\\/\\\/a.nel.cloudflare.com\\\/report\\\/v3?s=WhPNGryN2lnTT63PGIv4jkoAL%2BCJfcUd9U1L%2B%2F6RBPPdiAz7EXz0y4Oj84xA9dyzvnJHh4SVHLzJ9asKpj7DJczwb9mXhXY5Q8BverBn44Bu9RmF8gitXsMkSpAbWkL9gBwsgUTzlEcW4sPwEYwwSw%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}","NEL":"{\"success_fraction\":0.01,\"report_to\":\"cf-nel\",\"max_age\":604800}","Server":"cloudflare","CF-RAY":"7e0f675b4829d168-LHR"},"data":"{\"ticket\":{\"url\":\"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/tickets\/83.json\",\"id\":83,\"external_id\":null,\"via\":{\"channel\":\"api\",\"source\":{\"from\":{},\"to\":{},\"rel\":null}},\"created_at\":\"2023-07-03T13:16:35Z\",\"updated_at\":\"2023-07-03T13:16:35Z\",\"type\":null,\"subject\":\"My printer is on fire!\",\"raw_subject\":\"My printer is on fire!\",\"description\":\"The smoke is very colorful.\",\"priority\":\"urgent\",\"status\":\"open\",\"recipient\":null,\"requester_id\":17145664265741,\"submitter_id\":17145664265741,\"assignee_id\":17145664265741,\"organization_id\":17145651654157,\"group_id\":17145664762125,\"collaborator_ids\":[],\"follower_ids\":[],\"email_cc_ids\":[],\"forum_topic_id\":null,\"problem_id\":null,\"has_incidents\":false,\"is_public\":true,\"due_at\":null,\"tags\":[],\"custom_fields\":[{\"id\":17146061349901,\"value\":null},{\"id\":17195718961677,\"value\":\"Check field works\"},{\"id\":17195752153741,\"value\":\"Check field works number 2\"}],\"satisfaction_rating\":null,\"sharing_agreement_ids\":[],\"custom_status_id\":17145678334989,\"fields\":[{\"id\":17146061349901,\"value\":null},{\"id\":17195718961677,\"value\":\"Check field works\"},{\"id\":17195752153741,\"value\":\"Check field works number 2\"}],\"followup_ids\":[],\"ticket_form_id\":17145664563725,\"brand_id\":17145651602957,\"allow_channelback\":false,\"allow_attachments\":true,\"from_messaging_channel\":false},\"audit\":{\"id\":17278400133517,\"ticket_id\":83,\"created_at\":\"2023-07-03T13:16:35Z\",\"author_id\":17145664265741,\"metadata\":{\"system\":{\"client\":\"GuzzleHttp\/7\",\"ip_address\":\"94.101.151.181\",\"location\":\"Herne Bay, ENG, United Kingdom\",\"latitude\":51.3724,\"longitude\":1.1561},\"custom\":{}},\"events\":[{\"id\":17278400133645,\"type\":\"Comment\",\"author_id\":17145664265741,\"body\":\"The smoke is very colorful.\",\"html_body\":\"
The smoke is very colorful.<\/p><\/div>\",\"plain_body\":\"The smoke is very colorful.\",\"public\":true,\"attachments\":[],\"audit_id\":17278400133517},{\"id\":17278400133773,\"type\":\"Create\",\"value\":\"urgent\",\"field_name\":\"priority\"},{\"id\":17278400133901,\"type\":\"Create\",\"value\":\"My printer is on fire!\",\"field_name\":\"subject\"},{\"id\":17278400134029,\"type\":\"Create\",\"value\":\"17145664265741\",\"field_name\":\"requester_id\"},{\"id\":17278400134157,\"type\":\"Create\",\"value\":\"Check field works\",\"field_name\":\"17195718961677\"},{\"id\":17278400134285,\"type\":\"Create\",\"value\":\"Check field works number 2\",\"field_name\":\"17195752153741\"},{\"id\":17278400134413,\"type\":\"Create\",\"value\":null,\"field_name\":\"type\"},{\"id\":17278400134541,\"type\":\"Create\",\"value\":\"open\",\"field_name\":\"status\"},{\"id\":17278400134669,\"type\":\"Create\",\"value\":\"17145664265741\",\"field_name\":\"assignee_id\"},{\"id\":17278400134797,\"type\":\"Create\",\"value\":\"17145664762125\",\"field_name\":\"group_id\"},{\"id\":17278400134925,\"type\":\"Create\",\"value\":\"17145651654157\",\"field_name\":\"organization_id\"},{\"id\":17278400135053,\"type\":\"Create\",\"value\":\"17145651602957\",\"field_name\":\"brand_id\"},{\"id\":17278400135181,\"type\":\"Create\",\"value\":\"17145664563725\",\"field_name\":\"ticket_form_id\"},{\"id\":17278400135309,\"type\":\"Create\",\"value\":\"17145678334989\",\"field_name\":\"custom_status_id\"},{\"id\":17278414083597,\"type\":\"AssociateAttValsEvent\",\"attribute_values\":[]}],\"via\":{\"channel\":\"api\",\"source\":{\"from\":{},\"to\":{},\"rel\":null}}}}"} \ No newline at end of file diff --git a/tests/Fixtures/Saloon/single-ticket-request.json b/tests/Fixtures/Saloon/single-ticket-request.json new file mode 100644 index 0000000..7ec8913 --- /dev/null +++ b/tests/Fixtures/Saloon/single-ticket-request.json @@ -0,0 +1,37 @@ +{ + "statusCode": 200, + "headers": { + "Date": "Mon, 03 Jul 2023 11:31:04 GMT", + "Content-Type": "application\/json; charset=utf-8", + "Transfer-Encoding": "chunked", + "Connection": "keep-alive", + "x-zendesk-api-version": "v2", + "x-zendesk-application-version": "v17438", + "x-frame-options": "SAMEORIGIN", + "x-rate-limit": "400", + "rate-limit": "400", + "x-rate-limit-remaining": "398", + "rate-limit-remaining": "398", + "rate-limit-reset": "56", + "strict-transport-security": "max-age=31536000;", + "etag": "W\/\"f6a375c66420a3a7c52a087aa0f3bb47\"", + "cache-control": "max-age=0, private, must-revalidate", + "x-zendesk-origin-server": "classic-app-server-6fc8db697c-js56h", + "set-cookie": [ + "_zendesk_cookie=BAhJIhl7ImRldmljZV90b2tlbnMiOnt9fQY6BkVU--0bf2100788cb010d0183feca16aaf88ccaf719ca; path=\/; expires=Wed, 03 Jul 2024 07:05:41 GMT; secure; HttpOnly; SameSite=None", + "__cfruid=b15e262f7b806ba2db1221699a831cc39e74cd44-1688383864; path=\/; domain=.codebarsolutionsag.zendesk.com; HttpOnly; Secure; SameSite=None" + ], + "x-request-id": [ + "7e0ecccb0ef7414d-LHR", + "7e0ecccb0ef7414d-LHR" + ], + "x-runtime": "0.086786", + "X-Zendesk-Zorg": "yes", + "CF-Cache-Status": "DYNAMIC", + "Report-To": "{\"endpoints\":[{\"url\":\"https:\\\/\\\/a.nel.cloudflare.com\\\/report\\\/v3?s=7lMEsubYh03mZhbyhOB7legoUvkomiPxbsQOg0HD6GL0OxkjWkOR0%2BYeSVdaW9J2uI%2FTZdGSdesx8628LQHv%2BSSghfw776Er2QMrCaswrMMD6WyL4RTiVF5m%2F20KZSDfwoR4VeTsATquzrBuUeD0Gg%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}", + "NEL": "{\"success_fraction\":0.01,\"report_to\":\"cf-nel\",\"max_age\":604800}", + "Server": "cloudflare", + "CF-RAY": "7e0ecccb0ef7414d-LHR" + }, + "data": "{\"ticket\":{\"url\":\"https:\/\/codebarsolutionsag.zendesk.com\/api\/v2\/tickets\/81.json\",\"id\":81,\"external_id\":null,\"via\":{\"channel\":\"api\",\"source\":{\"from\":{},\"to\":{},\"rel\":null}},\"created_at\":\"2023-07-03T11:16:03Z\",\"updated_at\":\"2023-07-03T11:16:05Z\",\"type\":null,\"subject\":\"My printer is on fire!\",\"raw_subject\":\"My printer is on fire!\",\"description\":\"The smoke is very colorful.\",\"priority\":\"urgent\",\"status\":\"open\",\"recipient\":null,\"requester_id\":17145664265741,\"submitter_id\":17145664265741,\"assignee_id\":17145664265741,\"organization_id\":17145651654157,\"group_id\":17145664762125,\"collaborator_ids\":[],\"follower_ids\":[],\"email_cc_ids\":[],\"forum_topic_id\":null,\"problem_id\":null,\"has_incidents\":false,\"is_public\":true,\"due_at\":null,\"tags\":[],\"custom_fields\":[{\"id\":17146061349901,\"value\":null},{\"id\":17195718961677,\"value\":\"Check field works\"},{\"id\":17195752153741,\"value\":\"Check field works number 2\"}],\"satisfaction_rating\":null,\"sharing_agreement_ids\":[],\"custom_status_id\":17145678334989,\"fields\":[{\"id\":17146061349901,\"value\":null},{\"id\":17195718961677,\"value\":\"Check field works\"},{\"id\":17195752153741,\"value\":\"Check field works number 2\"}],\"followup_ids\":[],\"ticket_form_id\":17145664563725,\"brand_id\":17145651602957,\"allow_channelback\":false,\"allow_attachments\":true,\"from_messaging_channel\":false}}" +} diff --git a/tests/Pest.php b/tests/Pest.php index cc8b9d4..1cb836f 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -8,3 +8,12 @@ uses()->beforeEach(function () { Event::fake(); })->in(__DIR__); + +uses()->beforeEach(function () { + config([ + 'zendesk.subdomain' => 'codebarsolutionsag', + 'zendesk.auth.method' => 'token', + 'zendesk.auth.email_address' => 'invoice@codebar.ch', + 'zendesk.auth.api_token' => 'TqxDOhfFVseETyvdQ0ISV6JKaXuXtmoFRX67gKnZ', + ]); +})->in(__DIR__.'/Requests'); diff --git a/tests/Requests/AllTicketsRequestTest.php b/tests/Requests/AllTicketsRequestTest.php new file mode 100644 index 0000000..c64683f --- /dev/null +++ b/tests/Requests/AllTicketsRequestTest.php @@ -0,0 +1,42 @@ + MockResponse::fixture('all-tickets-request'), + ]); + + $connector = new ZendeskConnector; + $connector->withMockClient($mockClient); + + $response = $connector->send(new AllTicketsRequest()); + + $mockClient->assertSent(AllTicketsRequest::class); + + expect($response->dto()->count)->toBe(2) + ->and($response->dto()->tickets[1]['id'])->toBe(81) + ->and($response->dto()->tickets[1]['subject'])->toBe('My printer is on fire!') + ->and($response->dto()->tickets[1]['raw_subject'])->toBe('My printer is on fire!') + ->and($response->dto()->tickets[1]['description'])->toBe('The smoke is very colorful.') + ->and($response->dto()->tickets[1]['priority'])->toBe(TicketPriority::URGENT) + ->and($response->dto()->tickets[1]['custom_fields'][1]['id'])->toBe(17195718961677) + ->and($response->dto()->tickets[1]['custom_fields'][1]['value'])->toBe('Check field works') + ->and($response->dto()->tickets[1]['custom_fields'][2]['id'])->toBe(17195752153741) + ->and($response->dto()->tickets[1]['custom_fields'][2]['value'])->toBe('Check field works number 2') + ->and($response->dto()->tickets[0]['id'])->toBe(79) + ->and($response->dto()->tickets[0]['subject'])->toBe('Eine neue Anfrage der Bärtschi ist eingetroffen: Projekt #1.') + ->and($response->dto()->tickets[0]['raw_subject'])->toBe('Eine neue Anfrage der Bärtschi ist eingetroffen: Projekt #1.') + ->and($response->dto()->tickets[0]['description']) + ->toBe("Eine neue Anfrage der Bärtschi ist eingetroffen.\n\nAnfrage\nIdentifikation 1\nBemerkung asdasd\nURL https://app.pv.test/nova/resources/inquiries/1\nErstellt am 01.07.2023 14:21 Uhr\n**Kunde**\nKunden Bärtschi\nKunden ID 437046\nBenutzer ID 437046_ralph\nBenutzername Ralph Senn\n**Konfiguration**\nName Projekt #1\nDachform Sattel-/Pultdach\nMontage Aufdach\nHerkunft Asiatisch\nWechselrichter Typ String\n**Adresse**\nStrasse Mühlematten 12\nPLZ 4455\nOrt Zunzgen\nLand CH") + ->and($response->dto()->tickets[0]['priority'])->toBe(TicketPriority::URGENT) + ->and($response->dto()->tickets[0]['custom_fields'][1]['id'])->toBe(17195718961677) + ->and($response->dto()->tickets[0]['custom_fields'][1]['value'])->toBe(null) + ->and($response->dto()->tickets[0]['custom_fields'][2]['id'])->toBe(17195752153741) + ->and($response->dto()->tickets[0]['custom_fields'][2]['value'])->toBe(null); + +}); diff --git a/tests/Requests/CountTicketsRequestTest.php b/tests/Requests/CountTicketsRequestTest.php new file mode 100644 index 0000000..86feb66 --- /dev/null +++ b/tests/Requests/CountTicketsRequestTest.php @@ -0,0 +1,22 @@ + MockResponse::fixture('count-tickets-request'), + ]); + + $connector = new ZendeskConnector; + $connector->withMockClient($mockClient); + + $response = $connector->send(new CountTicketsRequest()); + + $mockClient->assertSent(CountTicketsRequest::class); + + expect($response->dto()->value)->toBe(4) + ->and($response->dto()->refreshed_at->toDateTimeString())->toBe('2023-07-03 13:19:53'); +}); diff --git a/tests/Requests/CreateAttachmentRequestTest.php b/tests/Requests/CreateAttachmentRequestTest.php new file mode 100644 index 0000000..0c7a590 --- /dev/null +++ b/tests/Requests/CreateAttachmentRequestTest.php @@ -0,0 +1,33 @@ + MockResponse::fixture('create-attachment-request'), + ]); + + $connector = new ZendeskConnector; + $connector->withMockClient($mockClient); + + $response = $connector->send( + new CreateAttachmentRequest( + fileName: 'test.png', + mimeType: 'image/png', + stream: fopen(__DIR__.'/../Fixtures/Files/test.png', 'r') + ) + ); + + $mockClient->assertSent(CreateAttachmentRequest::class); + + expect($response->dto()->token)->toBe('OPvgMbfg5Der4DYn66hTC31in') + ->and($response->dto()->attachment->content_type)->toBe('image/png') + ->and($response->dto()->attachment->size)->toBe(26271) + ->and($response->dto()->attachment->file_name)->toBe('test.png') + ->and($response->dto()->attachment->width)->toBe('640') + ->and($response->dto()->attachment->height)->toBe('360') + ->and($response->dto()->attachment->content_url)->toBe('https://codebarsolutionsag.zendesk.com/attachments/token/52HCaRgRZM38MvaUuUQsYzhUA/?name=test.png'); +}); diff --git a/tests/Requests/CreateSingleTicketRequestTest.php b/tests/Requests/CreateSingleTicketRequestTest.php new file mode 100644 index 0000000..22e8c43 --- /dev/null +++ b/tests/Requests/CreateSingleTicketRequestTest.php @@ -0,0 +1,46 @@ + MockResponse::fixture('create-single-ticket-request'), + ]); + + $connector = new ZendeskConnector; + $connector->withMockClient($mockClient); + + $response = $connector->send(new CreateSingleTicketRequest([ + 'comment' => CommentDTO::fromArray([ + 'body' => 'The smoke is very colorful.', + ]), + 'priority' => TicketPriority::URGENT, + 'subject' => 'My printer is on fire!', + 'custom_fields' => [ + [ + 'id' => 17195718961677, + 'value' => 'Check field works', + ], + [ + 'id' => 17195752153741, + 'value' => 'Check field works number 2', + ], + ], + ])); + + $mockClient->assertSent(CreateSingleTicketRequest::class); + + expect($response->dto()->subject)->toBe('My printer is on fire!') + ->and($response->dto()->raw_subject)->toBe('My printer is on fire!') + ->and($response->dto()->description)->toBe('The smoke is very colorful.') + ->and($response->dto()->priority)->toBe(TicketPriority::URGENT) + ->and($response->dto()->custom_fields[1]['id'])->toBe(17195718961677) + ->and($response->dto()->custom_fields[1]['value'])->toBe('Check field works') + ->and($response->dto()->custom_fields[2]['id'])->toBe(17195752153741) + ->and($response->dto()->custom_fields[2]['value'])->toBe('Check field works number 2'); +}); diff --git a/tests/Requests/SingleTicketRequestTest.php b/tests/Requests/SingleTicketRequestTest.php new file mode 100644 index 0000000..23c32f7 --- /dev/null +++ b/tests/Requests/SingleTicketRequestTest.php @@ -0,0 +1,30 @@ + MockResponse::fixture('single-ticket-request'), + ]); + + $connector = new ZendeskConnector; + $connector->withMockClient($mockClient); + + $response = $connector->send(new SingleTicketRequest(81)); + + $mockClient->assertSent(SingleTicketRequest::class); + + expect($response->dto()->id)->toBe(81) + ->and($response->dto()->subject)->toBe('My printer is on fire!') + ->and($response->dto()->raw_subject)->toBe('My printer is on fire!') + ->and($response->dto()->description)->toBe('The smoke is very colorful.') + ->and($response->dto()->priority)->toBe(TicketPriority::URGENT) + ->and($response->dto()->custom_fields[1]['id'])->toBe(17195718961677) + ->and($response->dto()->custom_fields[1]['value'])->toBe('Check field works') + ->and($response->dto()->custom_fields[2]['id'])->toBe(17195752153741) + ->and($response->dto()->custom_fields[2]['value'])->toBe('Check field works number 2'); +}); diff --git a/tests/TestCase.php b/tests/TestCase.php index 6b100a4..a4319ac 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -5,6 +5,7 @@ use CodebarAg\Zendesk\ZendeskServiceProvider; use Illuminate\Database\Eloquent\Factories\Factory; use Orchestra\Testbench\TestCase as Orchestra; +use Spatie\LaravelData\Support\DataConfig; class TestCase extends Orchestra { @@ -15,6 +16,11 @@ protected function setUp(): void Factory::guessFactoryNamesUsing( fn (string $modelName) => 'CodebarAg\\Zendesk\\Database\\Factories\\'.class_basename($modelName).'Factory' ); + + // Provide a config array to DataConfig + $this->app->when(DataConfig::class) + ->needs('$config') + ->give([]); } protected function getPackageProviders($app): array