import demistomock as demisto import pytest from ServiceDeskPlus import ( Client, OAUTH_URL, add_resolution_command, args_to_query, assign_request_command, close_request_command, create_fetch_list_info, create_human_readable, create_modify_linked_input_data, create_output, create_request_command, create_requests_list_info, create_udf_field, delete_request_command, fetch_incidents, generate_refresh_token, get_resolutions_list_command, linked_request_command, list_requests_command, modify_linked_request_command, pickup_request_command, resolution_human_readable, update_request_command, ) from test_data.response_constants import ( RESPONSE_CREATE_REQUEST, RESPONSE_FETCH_INCIDENTS, RESPONSE_GENERATE_REFRESH_TOKEN, RESPONSE_LINK_REQUEST, RESPONSE_LINKED_REQUEST_LIST, RESPONSE_LIST_MULTIPLE_REQUESTS, RESPONSE_LIST_SINGLE_REQUEST, RESPONSE_NO_RESOLUTION_LIST, RESPONSE_RESOLUTION_LIST, RESPONSE_UNLINK_REQUEST, RESPONSE_UPDATE_REQUEST, RESPONSE_GET_NOTES_LIST, RESPONSE_GET_NOTE, RESPONSE_ADD_NOTE, RESPONSE_DELETE_NOTE, RESPONSE_UPDATE_NOTE, ) from test_data.result_constants import ( EXPECTED_CREATE_REQUEST, EXPECTED_LINKED_REQUEST_LIST, EXPECTED_LIST_MULTIPLE_REQUESTS, EXPECTED_LIST_SINGLE_REQUEST, EXPECTED_NO_RESOLUTION_LIST, EXPECTED_RESOLUTION_LIST, EXPECTED_UPDATE_REQUEST, EXPECTED_GET_NOTES_LIST, EXPECTED_GET_NOTE, EXPECTED_ADD_NOTE, EXPECTED_DELETE_NOTE, EXPECTED_UPDATE_NOTE, ) COMMANDS_LIST_WITH_CONTEXT = [ # Given the create command, different fields that should be used to create the request, the response of the command # and the expected result, validate that the output of the command and the expected result are identical ( create_request_command, { "subject": "Create request test", "mode": "E-Mail", "requester": "First Last", "level": "Tier 1", "impact": "Affects Group", "priority": "High", "status": "On Hold", "request_type": "Incident", "description": "The description of the request", "urgency": "Normal", "group": "Network", }, RESPONSE_CREATE_REQUEST, EXPECTED_CREATE_REQUEST, ), # Given the update command, different fields that should be used to create the request, the response of the command # and the expected result, validate that the output of the command and the expected result are identical ( update_request_command, {"request_id": "123640000000240013", "description": "Update the description", "impact": "Affects Business"}, RESPONSE_UPDATE_REQUEST, EXPECTED_UPDATE_REQUEST, ), # Given list requests command, the id of the single request that should be returned, validate that the output # context of the command is identical to the expected output (list_requests_command, {"request_id": "123640000000240013"}, RESPONSE_LIST_SINGLE_REQUEST, EXPECTED_LIST_SINGLE_REQUEST), # Given list requests command, page size equal 3 and the response for 3 requests, validate that the output # context of the command is identical to the expected output (list_requests_command, {"page_size": "3"}, RESPONSE_LIST_MULTIPLE_REQUESTS, EXPECTED_LIST_MULTIPLE_REQUESTS), # Given the linked request command, the id of the request that it's links should be checked and the response for the # command, validate that the context output of the command is identical to the expected output. (linked_request_command, {"request_id": "123640000000246001"}, RESPONSE_LINKED_REQUEST_LIST, EXPECTED_LINKED_REQUEST_LIST), # Given the get resolutions list command, the id of the request for which the resolution should be returned and the # response in case there IS a resolution for the request, validate the context output of the command (get_resolutions_list_command, {"request_id": "123640000000241001"}, RESPONSE_RESOLUTION_LIST, EXPECTED_RESOLUTION_LIST), # Given the get resolutions list command, the id of the request for which the resolution should be returned and the # response in case there is NO a resolution for the request, validate the context output of the command ( get_resolutions_list_command, {"request_id": "123640000000241001"}, RESPONSE_NO_RESOLUTION_LIST, EXPECTED_NO_RESOLUTION_LIST, ), ] COMMANDS_LIST_WITHOUT_CONTEXT = [ # Given the delete command and the id of the request that should be deleted, validate the human readable output (delete_request_command, {"request_id": "1234"}, {}, "### Successfully deleted request(s) ['1234']"), # Given the delete command and multiple ids of requests that should be deleted, validate the human readable output (delete_request_command, {"request_id": "1234,5678"}, {}, "### Successfully deleted request(s) ['1234', '5678']"), # Given the close command and the id of the request that should be closed, validate the human readable output (close_request_command, {"request_id": "1234"}, {}, "### Successfully closed request 1234"), # Given the assign command and the id of the request that should be assigned, validate the human readable output (assign_request_command, {"request_id": "1234"}, {}, "### Service Desk Plus request 1234 was successfully assigned"), # Given the pickup command and the id of the request that should be picked up, validate the human readable output (pickup_request_command, {"request_id": "1234"}, {}, "### Service Desk Plus request 1234 was successfully picked up"), # Given the modify linked command with the 'Link' action and the ids of the requests that should be linked, verify # that the human readable indicates that the requests were successfully linked ( modify_linked_request_command, {"action": "Link", "request_id": "1234", "linked_requests_id": "5678"}, RESPONSE_LINK_REQUEST, "## Request successfully linked", ), # Given the modify linked command with the 'Unlink' action and the ids of the requests that should be linked, verify # that the human readable indicates that the requests were successfully unlinked ( modify_linked_request_command, {"action": "Unlink", "request_id": "1234", "linked_requests_id": "5678"}, RESPONSE_UNLINK_REQUEST, "## The request[s] link are removed successfully.", ), # Given the add resolution command, the id of the request the resolution should be added to, the resolution content # and the add_to_linked_requests flag set to true, validate the human readable output ( add_resolution_command, {"request_id": "1234", "resolution_content": "resolution message", "add_to_linked_requests": "true"}, RESPONSE_UNLINK_REQUEST, "### Resolution was successfully added to 1234 and the linked requests", ), # Given the add resolution command, the id of the request the resolution should be added to, the resolution content # and the add_to_linked_requests flag set to true, validate the human readable output ( add_resolution_command, {"request_id": "1234", "resolution_content": "resolution message", "add_to_linked_requests": "false"}, RESPONSE_UNLINK_REQUEST, "### Resolution was successfully added to 1234", ), ] REFRESH_TOKEN_COMMAND_CLOUD = [ # Given the generate refresh token command, a valid code that should be used and the response for this command, # validate the human readable output ( generate_refresh_token, {"code": "147852369"}, RESPONSE_GENERATE_REFRESH_TOKEN, "### Refresh Token: 987654321\n " "Please paste the Refresh Token in" " the instance configuration and " "save it for future use.", ), # Given the generate refresh token command, a code and an error message as the response, validate that the human # readable is indicating an error. (generate_refresh_token, {"code": "147852369"}, {"error": "invalid_code"}, "### Error: invalid_code"), ] # test commands with context: @pytest.mark.parametrize("command, args, response, expected_result", COMMANDS_LIST_WITH_CONTEXT) def test_commands_cloud(command, args, response, expected_result, mocker): mocker.patch("ServiceDeskPlus.Client.get_access_token") client = Client( "server_url", "https://accounts.zoho.com/oauth/v2/token", "use_ssl", "use_proxy", "client_id", "client_secret", "refresh_token", ) mocker.patch.object(client, "http_request", return_value=response) result = command(client, args) assert expected_result == result[1] # test commands with context: @pytest.mark.parametrize("command, args, response, expected_result", COMMANDS_LIST_WITH_CONTEXT) def test_commands_on_premise(command, args, response, expected_result, mocker): client = Client( "server_url", "https://accounts.zoho.com/oauth/v2/token", "use_ssl", "use_proxy", technician_key="technician_key", on_premise=True, ) mocker.patch.object(client, "http_request", return_value=response) result = command(client, args) assert expected_result == result[1] # test commands without context: @pytest.mark.parametrize("command, args, response, expected_result", COMMANDS_LIST_WITHOUT_CONTEXT) def test_command_hr_cloud(command, args, response, expected_result, mocker): mocker.patch("ServiceDeskPlus.Client.get_access_token") client = Client( "server_url", "https://accounts.zoho.com/oauth/v2/token", "use_ssl", "use_proxy", "client_id", "client_secret", "refresh_token", ) mocker.patch.object(client, "http_request", return_value=response) result = command(client, args) assert expected_result == result[0] # test commands without context: @pytest.mark.parametrize("command, args, response, expected_result", COMMANDS_LIST_WITHOUT_CONTEXT) def test_command_hr_on_premise(command, args, response, expected_result, mocker): client = Client( "server_url", "https://accounts.zoho.com/oauth/v2/token", "use_ssl", "use_proxy", technician_key="technician_key", on_premise=True, ) mocker.patch.object(client, "http_request", return_value=response) result = command(client, args) assert expected_result == result[0] @pytest.mark.parametrize("command, args, response, expected_result", REFRESH_TOKEN_COMMAND_CLOUD) def test_refresh_token_command_cloud(command, args, response, expected_result, mocker): mocker.patch("ServiceDeskPlus.Client.get_access_token") client = Client( "server_url", "https://accounts.zoho.com/oauth/v2/token", "use_ssl", "use_proxy", "client_id", "client_secret", "refresh_token", ) mocker.patch.object(client, "http_request", return_value=response) result = command(client, args) assert expected_result == result[0] def test_refresh_token_command_on_premise(mocker): """ Given: - on-premise client When: - run refresh-token command Then: - Returns an error that this command cannot be executed for on-premise. """ mocker.patch("ServiceDeskPlus.Client.get_access_token") client = Client("server_url", "dummy_oauth_url", "use_ssl", "use_proxy", technician_key="technician_key", on_premise=True) mocker.patch.object(demisto, "results") with pytest.raises(SystemExit) as err: generate_refresh_token(client, "args") assert err.type is SystemExit assert demisto.results.call_count == 1 # call_args is tuple (args list, kwargs). we only need the first one results = demisto.results.call_args[0] assert len(results) == 1 assert "The command 'service-desk-plus-generate-refresh-token' can not be executed on on-premise." in results[0]["Contents"] # test helper functions: def test_create_output(): input = RESPONSE_CREATE_REQUEST.get("request") expected_output = EXPECTED_CREATE_REQUEST.get("ServiceDeskPlus(val.ID===obj.ID)").get("Request") assert create_output(input) == expected_output def test_args_to_query(): assign_input = {"group": "group1", "technician": "tech name"} expected_assign_output = {"request": {"group": {"name": "group1"}, "technician": {"name": "tech name"}}} assert args_to_query(assign_input) == expected_assign_output create_input = {"subject": "request subject", "group": "group1", "impact": "Affects Business", "requester": "name"} expected_create_output = { "request": { "subject": "request subject", "group": {"name": "group1"}, "impact": {"name": "Affects Business"}, "requester": {"name": "name"}, } } assert args_to_query(create_input) == expected_create_output def test_create_modify_linked_input_data(): linked_request_id = ["1234"] comment = "testing one request" expected_output = {"link_requests": [{"linked_request": {"id": "1234"}, "comments": "testing one request"}]} assert create_modify_linked_input_data(linked_request_id, comment) == expected_output linked_request_id = ["1234", "5678"] comment = "testing two request" expected_output = { "link_requests": [ {"linked_request": {"id": "1234"}, "comments": "testing two request"}, {"linked_request": {"id": "5678"}, "comments": "testing two request"}, ] } assert create_modify_linked_input_data(linked_request_id, comment) == expected_output linked_request_id = ["1234", "5678", "0912"] expected_output = { "link_requests": [ {"linked_request": {"id": "1234"}}, {"linked_request": {"id": "5678"}}, {"linked_request": {"id": "0912"}}, ] } assert create_modify_linked_input_data(linked_request_id, "") == expected_output def test_create_human_readable(): input = { "CreatedTime": "creation_time", "Id": "1234", "Requester": { "name": "First Last", "mobile": None, "id": "123640000000244019", "photo_url": "url", "is_vip_user": False, "department": None, }, "Technician": {"email_id": "i@id", "cost_per_hour": "0", "phone": None, "name": "tech1"}, "Status": "Open", "Subject": "test human readable", } expected_output = { "CreatedTime": "creation_time", "Id": "1234", "Requester": "First Last", "Technician": "tech1", "Status": "Open", "Subject": "test human readable", } assert create_human_readable(input) == expected_output def test_resolution_human_readable(): input = { "Content": "res contents", "SubmittedOn": "submittion_date", "SubmittedBy": {"email_id": "i@id", "phone": None, "name": "submitter"}, } expected_output = {"Content": "res contents", "SubmittedOn": "submittion_date", "SubmittedBy": "submitter"} assert resolution_human_readable(input) == expected_output def test_create_requests_list_info(): start_index, row_count, search_fields, filter_by = "0", "15", "a, b, c", "filter" expected_output = { "list_info": { "start_index": "0", "row_count": "15", "search_fields": "a, b, c", "filter_by": "filter", "sort_field": "created_time", "sort_order": "asc", } } assert create_requests_list_info(start_index, row_count, search_fields, filter_by) == expected_output def test_create_fetch_list_info(): # Check empty status list: time_from, time_to, status, fetch_filter, fetch_limit = "from", "to", [], "", 10 expected_output = { "list_info": { "search_criteria": [{"field": "created_time", "values": ["from", "to"], "condition": "between"}], "sort_field": "created_time", "sort_order": "asc", "row_count": 10, } } assert create_fetch_list_info(time_from, time_to, status, fetch_filter, fetch_limit) == expected_output # Check one status: time_from, time_to, status, fetch_filter, fetch_limit = "from", "to", ["status"], "", 10 expected_output = { "list_info": { "search_criteria": [ {"field": "created_time", "values": ["from", "to"], "condition": "between"}, {"field": "status.name", "values": ["status"], "condition": "is", "logical_operator": "AND"}, ], "sort_field": "created_time", "sort_order": "asc", "row_count": 10, } } assert create_fetch_list_info(time_from, time_to, status, fetch_filter, fetch_limit) == expected_output # Check multiple status: time_from, time_to, status, fetch_filter, fetch_limit = "from", "to", ["status1", "status2"], "", 10 expected_output = { "list_info": { "search_criteria": [ {"field": "created_time", "values": ["from", "to"], "condition": "between"}, {"field": "status.name", "values": ["status1", "status2"], "condition": "is", "logical_operator": "AND"}, ], "sort_field": "created_time", "sort_order": "asc", "row_count": 10, } } assert create_fetch_list_info(time_from, time_to, status, fetch_filter, fetch_limit) == expected_output time_from, time_to, status, fetch_limit = "from", "to", ["status"], 15 fetch_filter = "{'field': 'technician.name', 'values': 'tech1,tech2', 'condition': 'is', 'logical_operator':'AND'}" expected_output = { "list_info": { "search_criteria": [ {"field": "created_time", "values": ["from", "to"], "condition": "between"}, {"field": "technician.name", "condition": "is", "values": ["tech1", "tech2"], "logical_operator": "AND"}, ], "sort_field": "created_time", "sort_order": "asc", "row_count": 15, } } assert create_fetch_list_info(time_from, time_to, status, fetch_filter, fetch_limit) == expected_output time_from, time_to, status, fetch_limit = "from", "to", ["status"], 20 fetch_filter = ( "{'field':'technician.name','values':'tech1,tech2','condition':'is','logical_operator':'AND'}," "{'field':'group.name','values':'group1','condition':'is','logical_operator':'AND'}" ) expected_output = { "list_info": { "search_criteria": [ {"field": "created_time", "values": ["from", "to"], "condition": "between"}, {"field": "technician.name", "condition": "is", "values": ["tech1", "tech2"], "logical_operator": "AND"}, {"field": "group.name", "condition": "is", "values": ["group1"], "logical_operator": "AND"}, ], "sort_field": "created_time", "sort_order": "asc", "row_count": 20, } } assert create_fetch_list_info(time_from, time_to, status, fetch_filter, fetch_limit) == expected_output def test_create_udf_field(): udf_input = "key1:val1" expected_output = {"key1": "val1"} assert create_udf_field(udf_input) == expected_output udf_input = "{'key1':'val1'}" expected_output = {"key1": "val1"} assert create_udf_field(udf_input) == expected_output udf_input = "key1:val1,key2:val2" expected_output = {"key1": "val1", "key2": "val2"} assert create_udf_field(udf_input) == expected_output invalid_udf_inputs = ["key1:val1,key2", "key1,val1", "key1", ":val1"] for udf_input in invalid_udf_inputs: try: create_udf_field(udf_input) except Exception as e: assert "Illegal udf fields format" in e.args[0] def test_fetch_incidents_cloud(mocker): """ Unit test Given - fetch incidents command - command args - command raw response When - mock the parse_date_range. - mock the date_to_timestamp. - mock the create_fetch_list_info. - mock the Client's get_requests command. Then - run the fetch incidents command using the Client. Validate the length of the results and the different fields of the fetched incidents. """ mocker.patch("ServiceDeskPlus.Client.get_access_token") mocker.patch("ServiceDeskPlus.parse_date_range", return_value=("2020-06-23 04:18:00", "never mind")) mocker.patch("ServiceDeskPlus.date_to_timestamp", return_value="1592918317168") mocker.patch("ServiceDeskPlus.create_fetch_list_info", return_value={}) client = Client( "server_url", "use_ssl", "use_proxy", "client_id", "client_secret", "refresh_token", fetch_time="1 hour", fetch_limit=3, fetch_status=["Open"], ) mocker.patch.object(client, "get_requests", return_value=RESPONSE_FETCH_INCIDENTS) incidents = fetch_incidents(client) assert len(incidents) == 3 client = Client( "server_url", "use_ssl", "use_proxy", "client_id", "client_secret", "refresh_token", fetch_time="1 hour", fetch_limit=2, fetch_status=["Open"], ) mocker.patch.object(client, "get_requests", return_value=RESPONSE_FETCH_INCIDENTS) incidents = fetch_incidents(client) assert len(incidents) == 2 client = Client( "server_url", "use_ssl", "use_proxy", "client_id", "client_secret", "refresh_token", fetch_time="1 hour", fetch_limit=1, fetch_status=["Open"], ) mocker.patch.object(client, "get_requests", return_value=RESPONSE_FETCH_INCIDENTS) incidents = fetch_incidents(client) assert len(incidents) == 1 assert incidents[0].get("name") == "Test fetch incidents - 1234" client = Client( "server_url", "use_ssl", "use_proxy", "client_id", "client_secret", "refresh_token", fetch_time="1 hour", fetch_limit=0, fetch_status=["Open"], ) mocker.patch.object(client, "get_requests", return_value=RESPONSE_FETCH_INCIDENTS) incidents = fetch_incidents(client) assert len(incidents) == 0 def test_fetch_incidents_on_premise(mocker): """ Unit test Given - fetch incidents command - command args - command raw response When - mock the parse_date_range. - mock the date_to_timestamp. - mock the create_fetch_list_info. - mock the Client's get_requests command. Then - run the fetch incidents command using the Client. Validate the length of the results and the different fields of the fetched incidents. """ mocker.patch("ServiceDeskPlus.parse_date_range", return_value=("2020-06-23 04:18:00", "never mind")) mocker.patch("ServiceDeskPlus.date_to_timestamp", return_value="1592918317168") mocker.patch("ServiceDeskPlus.create_fetch_list_info", return_value={}) client = Client( "server_url", "dummy_oauth_url", "use_ssl", "use_proxy", technician_key="technician_key", on_premise=True, fetch_time="1 hour", fetch_limit=3, fetch_status=["Open"], ) mocker.patch.object(client, "get_requests", return_value=RESPONSE_FETCH_INCIDENTS) incidents = fetch_incidents(client) assert len(incidents) == 3 client = Client( "server_url", "dummy_oauth_url", "use_ssl", "use_proxy", technician_key="technician_key", on_premise=True, fetch_time="1 hour", fetch_limit=2, fetch_status=["Open"], ) mocker.patch.object(client, "get_requests", return_value=RESPONSE_FETCH_INCIDENTS) incidents = fetch_incidents(client) assert len(incidents) == 2 client = Client( "server_url", "dummy_oauth_url", "use_ssl", "use_proxy", technician_key="technician_key", on_premise=True, fetch_time="1 hour", fetch_limit=1, fetch_status=["Open"], ) mocker.patch.object(client, "get_requests", return_value=RESPONSE_FETCH_INCIDENTS) incidents = fetch_incidents(client) assert len(incidents) == 1 assert incidents[0].get("name") == "Test fetch incidents - 1234" client = Client( "server_url", "dummy_oauth_url", "use_ssl", "use_proxy", technician_key="technician_key", on_premise=True, fetch_time="1 hour", fetch_limit=0, fetch_status=["Open"], ) mocker.patch.object(client, "get_requests", return_value=RESPONSE_FETCH_INCIDENTS) incidents = fetch_incidents(client) assert len(incidents) == 0 def test_test_module_cloud(mocker): """ Unit test Given - test module command - command raw response When - mock the parse_date_range. - mock the Client's send_request. Then - run the test module command using the Client Validate the content of the HumanReadable. """ from ServiceDeskPlus import test_module as module mocker.patch("ServiceDeskPlus.Client.get_access_token") client = Client("server_url", "use_ssl", "use_proxy", "client_id", "client_secret", refresh_token="refresh_token") mocker.patch("ServiceDeskPlus.parse_date_range", return_value=("2020-06-23 04:18:00", "never mind")) mocker.patch.object(client, "http_request", return_value=RESPONSE_FETCH_INCIDENTS) result = module(client) assert result == "ok" def test_test_module_on_premise(mocker): """ Unit test Given - test module command on premise - command raw response When - mock the parse_date_range. - mock the Client's send_request. Then - run the test module command using the Client Validate the content of the HumanReadable. """ from ServiceDeskPlus import test_module as module client = Client("server_url", "dummy_oauth_url", "use_ssl", "use_proxy", technician_key="technician_key", on_premise=True) mocker.patch("ServiceDeskPlus.parse_date_range", return_value=("2020-06-23 04:18:00", "never mind")) mocker.patch.object(client, "http_request", return_value=RESPONSE_FETCH_INCIDENTS) result = module(client) assert result == "ok" @pytest.mark.parametrize( "region,expected_oauth_url", [ ("United States", "https://accounts.zoho.com/oauth/v2/token"), ("Europe", "https://accounts.zoho.eu/oauth/v2/token"), ("India", "https://accounts.zoho.in/oauth/v2/token"), ("China", "https://accounts.zoho.cn/oauth/v2/token"), ("Australia", "https://accounts.zoho.au/oauth/v2/token"), ], ) def test_get_access_token_with_regional_oauth_url(mocker, region, expected_oauth_url): """ Given - Client with regional OAuth URL When - calling get_access_token method Then - validate that the correct regional OAuth URL is used for token request """ oauth_url = OAUTH_URL[region] mocker.patch("ServiceDeskPlus.demisto.getIntegrationContext", return_value={}) mocker.patch("ServiceDeskPlus.demisto.setIntegrationContext") mocker.patch("ServiceDeskPlus.date_to_timestamp", return_value=1234567890) mock_response = {"access_token": "test_access_token", "expires_in": 3600} mock_http_request = mocker.patch("ServiceDeskPlus.Client.http_request", return_value=mock_response) Client( url="https://test.com/api/v3/", outh_url=oauth_url, use_ssl=True, use_proxy=False, client_id="test_client_id", client_secret="test_client_secret", refresh_token="test_refresh_token", ) mock_http_request.assert_called_once() call_args = mock_http_request.call_args assert call_args[1]["full_url"] == expected_oauth_url assert call_args[0][0] == "POST" assert call_args[1]["url_suffix"] == "" @pytest.mark.parametrize( "region,expected_oauth_url", [ ("United States", "https://accounts.zoho.com/oauth/v2/token"), ("Europe", "https://accounts.zoho.eu/oauth/v2/token"), ("India", "https://accounts.zoho.in/oauth/v2/token"), ("China", "https://accounts.zoho.cn/oauth/v2/token"), ("Australia", "https://accounts.zoho.au/oauth/v2/token"), ], ) def test_generate_refresh_token_with_regional_oauth_url(mocker, region, expected_oauth_url): """ Given - generate_refresh_token command with regional OAuth URL When - calling generate_refresh_token with different regional clients Then - validate that the correct regional OAuth URL is used """ oauth_url = OAUTH_URL[region] client = Client( url="https://test.com/api/v3/", outh_url=oauth_url, use_ssl=True, use_proxy=False, client_id="test_client_id", client_secret="test_client_secret", ) mock_response = {"refresh_token": "new_refresh_token"} mock_http_request = mocker.patch.object(client, "http_request", return_value=mock_response) args = {"code": "test_authorization_code"} result = generate_refresh_token(client, args) mock_http_request.assert_called_once() call_args = mock_http_request.call_args assert call_args[1]["full_url"] == expected_oauth_url assert call_args[0][0] == "POST" assert call_args[1]["url_suffix"] == "" assert "new_refresh_token" in result[0] def test_get_request_notes_list_command(mocker): from ServiceDeskPlus import get_request_notes_list_command client = Client("server_url", "test_oauth_url", True, False, technician_key="technician_key", on_premise=True) mocker.patch.object(client, "http_request", return_value=RESPONSE_GET_NOTES_LIST) args = {"request_id": "123"} result = get_request_notes_list_command(client, args) assert result.outputs == EXPECTED_GET_NOTES_LIST def test_get_request_note_command(mocker): from ServiceDeskPlus import get_request_notes_list_command client = Client("server_url", "test_oauth_url", True, False, technician_key="technician_key", on_premise=True) mocker.patch.object(client, "http_request", return_value=RESPONSE_GET_NOTE) args = {"request_id": "123", "request_note_id": "1"} result = get_request_notes_list_command(client, args) assert result.outputs == EXPECTED_GET_NOTE def test_add_request_note_command(mocker): from ServiceDeskPlus import add_request_note_command client = Client("server_url", "test_oauth_url", True, False, technician_key="technician_key", on_premise=True) mocker.patch.object(client, "http_request", return_value=RESPONSE_ADD_NOTE) args = { "request_id": "123", "description": "New Note", "mark_first_response": "false", "add_to_linked_requests": "false", "notify_technician": "false", "show_to_requester": "false", } result = add_request_note_command(client, args) assert result.outputs == EXPECTED_ADD_NOTE def test_delete_request_note_command(mocker): from ServiceDeskPlus import delete_request_note_command client = Client("server_url", "test_oauth_url", True, False, technician_key="technician_key", on_premise=True) mocker.patch.object(client, "http_request", return_value=RESPONSE_DELETE_NOTE) args = {"request_id": "123", "request_note_id": "1"} result = delete_request_note_command(client, args) assert result.outputs == EXPECTED_DELETE_NOTE def test_update_request_note_command(mocker): from ServiceDeskPlus import update_request_note_command client = Client("server_url", "test_oauth_url", True, False, technician_key="technician_key", on_premise=True) mocker.patch.object(client, "http_request", return_value=RESPONSE_UPDATE_NOTE) args = { "request_id": "123", "request_note_id": "1", "description": "Updated Note 1", "mark_first_response": "false", "add_to_linked_requests": "false", "notify_technician": "false", "show_to_requester": "false", } result = update_request_note_command(client, args) assert result.outputs == EXPECTED_UPDATE_NOTE