def test_oauth_login_command(mocker): """ Given: - login command When: - (a) trying to call the command when using basic auth. - (b) - trying to call the command when using OAuth 2.0. - mocking the login command of ServiceNowClient. Then: - (a) validate that an error is returned, indicating that the function should be called when using OAuth only. - (b) Validate that the login was successful. """ mocker.patch('ServiceNowv2.ServiceNowClient.login') client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') try: login_command(client, args={'username': '******', 'password': '******'}) except Exception as e: assert '!servicenow-oauth-login command can be used only when using OAuth 2.0 authorization' in e.args[0] client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description', oauth_params=OAUTH_PARAMS) mocker.patch.object(client, 'send_request', return_value=RESPONSE_FETCH) result = login_command(client, args={'username': '******', 'password': '******'}) assert '### Logged in successfully.' in result[0]
def test_oauth_test_module(mocker): """ Given: - oauth_test_module command When: - (a) trying to call the command when using basic auth. - (b) - trying to call the command when using OAuth 2.0 - mock the parse_date_range. - mock the Client's send_request. Then: - (a) validate that an error is returned, indicating that the function should be called when using OAuth only. - (b) Validate that the instance was configured successfully. """ mocker.patch('ServiceNowv2.parse_date_range', return_value=("2019-02-23 08:14:21", 'never mind')) client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') try: oauth_test_module(client) except Exception as e: assert 'command should be used only when using OAuth 2.0 authorization.' in e.args[0] client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description', oauth_params=OAUTH_PARAMS) mocker.patch.object(client, 'send_request', return_value=RESPONSE_FETCH) result = oauth_test_module(client) assert '### Instance Configured Successfully.' in result[0]
def test_test_module(mocker): """Unit test Given - test module command - command args - command raw response When (a) - mock the parse_date_range. - mock the Client's send_request. (b) - calling the test module when using OAuth 2.0 authorization. Then (a) - run the test module command using the Client Validate the content of the HumanReadable. (b) Validate that an error is returned, indicating that the `Test` button can't be used when using OAuth 2.0. """ mocker.patch('ServiceNowv2.parse_date_range', return_value=("2019-02-23 08:14:21", 'never mind')) client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') mocker.patch.object(client, 'send_request', return_value=RESPONSE_FETCH) result = module(client) assert result[0] == 'ok' client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description', oauth_params=OAUTH_PARAMS) try: module(client) except Exception as e: assert 'Test button cannot be used when using OAuth 2.0' in e.args[0]
def test_not_authenticated_retry_negative(requests_mock, mocker): """ Given - ServiceNow client When - Sending HTTP request and getting 401 status code (not authenticated) 3 times Then - Verify debug messages - Ensure the send_request function fails and raises expected error message """ mocker.patch.object(demisto, 'debug') client = Client('http://server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', 'sysparm_limit', 'timestamp_field', 'ticket_type', 'get_attachments', 'incident_name') requests_mock.get('http://server_url', [{ 'status_code': 401, 'json': { 'error': { 'message': 'User Not Authenticated', 'detail': 'Required to provide Auth information' }, 'status': 'failure' } }, { 'status_code': 401, 'json': { 'error': { 'message': 'User Not Authenticated', 'detail': 'Required to provide Auth information' }, 'status': 'failure' } }, { 'status_code': 401, 'json': { 'error': { 'message': 'User Not Authenticated', 'detail': 'Required to provide Auth information' }, 'status': 'failure' } }]) with pytest.raises(Exception) as ex: client.send_request('') assert str(ex.value) == "Got status code 401 with url http://server_url with body b'{\"error\": {\"message\": " \ "\"User Not Authenticated\", \"detail\": \"Required to provide Auth information\"}, " \ "\"status\": \"failure\"}' with headers {}" assert demisto.debug.call_count == 3 debug = demisto.debug.call_args_list expected_debug_msg = "Got status code 401 - {'error': {'message': 'User Not Authenticated', " \ "'detail': 'Required to provide Auth information'}, 'status': 'failure'}. Retrying ..." assert debug[0][0][0] == expected_debug_msg assert debug[1][0][0] == expected_debug_msg assert debug[2][0][0] == expected_debug_msg
def test_get_remote_data_no_entries(mocker): """ Given: - ServiceNow client - arguments: id and LastUpdate(set to lower then the modification time). - ServiceNow ticket - File and comment entries sent from XSOAR. When - running get_remote_data_command. Then - The checked entries was not returned. """ client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url', username='******', password='******', verify=False, fetch_time='fetch_time', sysparm_query='sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') args = {'id': 'sys_id', 'lastUpdate': 0} params = {} mocker.patch.object(client, 'get', return_value=[RESPONSE_TICKET_MIRROR, RESPONSE_ASSIGNMENT_GROUP]) mocker.patch.object(client, 'get_ticket_attachment_entries', return_value=RESPONSE_MIRROR_FILE_ENTRY_FROM_XSOAR) mocker.patch.object(client, 'query', return_value=MIRROR_COMMENTS_RESPONSE_FROM_XSOAR) res = get_remote_data_command(client, args, params) assert 'This is a comment\n\n Mirrored from Cortex XSOAR' not in res assert 'test_mirrored_from_xsoar.txt' not in res
def test_get_remote_data_closing_incident(mocker): """ Given: - ServiceNow client - arguments: id and LastUpdate(set to lower then the modification time). - ServiceNow ticket When - running get_remote_data_command. Then - The closed_at field exists in the ticket data. - dbotIncidentClose exists. - Closed notes exists. """ client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url', username='******', password='******', verify=False, fetch_time='fetch_time', sysparm_query='sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='sc_task', get_attachments=False, incident_name='description') args = {'id': 'sys_id', 'lastUpdate': 0} params = {'close_incident': True} mocker.patch.object(client, 'get', return_value=RESPONSE_CLOSING_TICKET_MIRROR) mocker.patch.object(client, 'get_ticket_attachment_entries', return_value=[]) mocker.patch.object(client, 'query', return_value=MIRROR_COMMENTS_RESPONSE) res = get_remote_data_command(client, args, params) assert 'closed_at' in res[0] assert CLOSING_RESPONSE == res[2]['Contents']
def test_test_module(mocker): """Unit test Given - test module command - command args - 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. """ mocker.patch('ServiceNowv2.parse_date_range', return_value=("2019-02-23 08:14:21", 'never mind')) client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') mocker.patch.object(client, 'send_request', return_value=RESPONSE_FETCH) result = module(client) assert result[0] == 'ok'
def test_update_remote_data_sc_task(mocker): """ Given: - ServiceNow client - ServiceNow ticket of type sc_task When - running update_remote_system_command. Then - The state is changed to 3 (closed) after update. """ client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url', username='******', password='******', verify=False, fetch_time='fetch_time', sysparm_query='sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='sc_task', get_attachments=False, incident_name='description') params = {'ticket_type': 'sc_task', 'close_ticket': True} args = { 'remoteId': '1234', 'data': TICKET_FIELDS, 'entries': [], 'incidentChanged': True, 'delta': {}, 'status': 2 } mocker.patch('ServiceNowv2.get_ticket_fields', side_effect=ticket_fields) mocker.patch.object(client, 'update', side_effect=update_ticket) update_remote_system_command(client, args, params)
def test_get_remote_data(mocker): """ Given: - ServiceNow client - arguments: id and LastUpdate(set to lower then the modification time). - ServiceNow ticket When - running get_remote_data_command. Then - The ticket was updated with the entries. """ client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url', username='******', password='******', verify=False, fetch_time='fetch_time', sysparm_query='sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') args = {'id': 'sys_id', 'lastUpdate': 0} params = {} mocker.patch.object(client, 'get', return_value=RESPONSE_TICKET_MIRROR) mocker.patch.object(client, 'get_ticket_attachments', return_value=RESPONSE_GET_ATTACHMENT) mocker.patch.object(client, 'get_ticket_attachment_entries', return_value=RESPONSE_MIRROR_FILE_ENTRY) mocker.patch.object(client, 'query', return_value=MIRROR_COMMENTS_RESPONSE) mocker.patch.object(client, 'get', return_value=RESPONSE_ASSIGNMENT_GROUP) res = get_remote_data_command(client, args, params) assert res[1]['File'] == 'test.txt' assert res[2]['Contents'] == 'This is a comment'
def test_fetch_incidents_with_attachments(mocker): """Unit test Given - fetch incidents command - command args - command raw response When - mock the parse_date_range. - mock the Client's send_request. - mock the Client's get_ticket_attachment_entries. Then - run the fetch incidents command using the Client Validate The length of the results and the attachment content. """ mocker.patch('ServiceNowv2.parse_date_range', return_value=("2016-10-10 15:19:57", 'never mind')) client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=True, incident_name='number') mocker.patch.object(client, 'send_request', return_value=RESPONSE_FETCH_ATTACHMENTS_TICKET) mocker.patch.object(client, 'get_ticket_attachment_entries', return_value=RESPONSE_FETCH_ATTACHMENTS_FILE) incidents = fetch_incidents(client) assert len(incidents) == 1 assert incidents[0].get('attachment')[0]['name'] == 'wireframe' assert incidents[0].get('attachment')[0]['path'] == 'file_id'
def test_upload_entries_update_remote_system_command(mocker): """ Given: - ServiceNow client - File and comment entries sent from XSOAR. When - running update_remote_system_command. Then - The checked entries was sent as expected with suffix. """ client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url', username='******', password='******', verify=False, fetch_time='fetch_time', sysparm_query='sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') params = {} args = { 'remoteId': '1234', 'data': {}, 'entries': MIRROR_ENTRIES, 'incidentChanged': False, 'delta': {} } mocker.patch.object(client, 'upload_file', side_effect=upload_file_request) mocker.patch.object(client, 'add_comment', side_effect=add_comment_request) update_remote_system_command(client, args, params)
def test_fetch_incidents_with_incident_name(mocker): """Unit test Given - fetch incidents command - command args - command raw response When - mock the parse_date_range. - mock the Client's send_request. Then - run the fetch incidents command using the Client Validate The length of the results. """ mocker.patch('ServiceNowv2.parse_date_range', return_value=("2019-02-23 08:14:21", 'never mind')) client = Client('server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') mocker.patch.object(client, 'send_request', return_value=RESPONSE_FETCH) incidents = fetch_incidents(client) assert incidents[0].get( 'name' ) == 'ServiceNow Incident Unable to access Oregon mail server. Is it down?'
def test_sysparm_input_display_value(mocker, requests_mock): """Unit test Given - create_record_command function - command args, including input_display_value - command raw response When - mock the requests url destination. Then - run the create command using the Client Validate that the sysparm_input_display_value parameter has the correct value """ client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url', username='******', password='******', verify=False, fetch_time='fetch_time', sysparm_query='sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') mocker.patch.object(demisto, 'args', return_value={ 'input_display_value': 'true', 'table_name': "alm_asset", 'fields': "asset_tag=P4325434;display_name=my_test_record" }) requests_mock.post( 'https://server_url.com/table/alm_asset?sysparm_input_display_value=True', json={}) # will raise a requests_mock.exceptions.NoMockAddress if the url address will not be as given in the requests_mock create_record_command(client, demisto.args()) assert requests_mock.request_history[0].method == 'POST' mocker.patch.object(demisto, 'args', return_value={ 'input_display_value': 'false', 'table_name': "alm_asset", 'fields': "asset_tag=P4325434;display_name=my_test_record" }) requests_mock.post( 'https://server_url.com/table/alm_asset?sysparm_input_display_value=False', json={}) # will raise a requests_mock.exceptions.NoMockAddress if the url address will not be as given in the requests_mock create_record_command(client, demisto.args()) assert requests_mock.request_history[1].method == 'POST'
def test_not_authenticated_retry_positive(requests_mock, mocker): """ Given - ServiceNow client When - Sending HTTP request and getting 401 status code (not authenticated) twice, followed by 200 status code (success) Then - Verify debug messages - Ensure the send_request function runs successfully without exceptions """ mocker.patch.object(demisto, 'debug') client = Client('http://server_url', 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', 'sysparm_limit', 'timestamp_field', 'ticket_type', 'get_attachments', 'incident_name') requests_mock.get('http://server_url', [{ 'status_code': 401, 'json': { 'error': { 'message': 'User Not Authenticated', 'detail': 'Required to provide Auth information' }, 'status': 'failure' } }, { 'status_code': 401, 'json': { 'error': { 'message': 'User Not Authenticated', 'detail': 'Required to provide Auth information' }, 'status': 'failure' } }, { 'status_code': 200, 'json': {} }]) assert client.send_request('') == {} assert demisto.debug.call_count == 2 debug = demisto.debug.call_args_list expected_debug_msg = "Got status code 401 - {'error': {'message': 'User Not Authenticated', " \ "'detail': 'Required to provide Auth information'}, 'status': 'failure'}. Retrying ..." assert debug[0][0][0] == expected_debug_msg assert debug[1][0][0] == expected_debug_msg
def test_get_ticket_attachments(mocker, sys_created_on, expected): """ Given: - Cases A+B: sys_created_on argument was not provided - Case C: sys_created_on argument was provided When: - Getting a ticket attachments. Then: - Case A+B: Ensure that the query parameters do not include ^sys_created_on> - Case C: Ensure that the query parameters include ^sys_created_on> """ client = Client("url", 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', 'sysparm_limit', 'timestamp_field', 'ticket_type', 'get_attachments', 'incident_name') mocker.patch.object(client, 'send_request', return_value=[]) client.get_ticket_attachments('id', sys_created_on) client.send_request.assert_called_with( 'attachment', 'GET', params={'sysparm_query': f'{expected}'})
def test_get_mapping_fields(): """ Given: - ServiceNow client - ServiceNow mapping fields When - running get_mapping_fields_command Then - the result fits the expected mapping. """ client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url', username='******', password='******', verify=False, fetch_time='fetch_time', sysparm_query='sysparm_query', sysparm_limit=10, timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='description') res = get_mapping_fields_command(client) assert EXPECTED_MAPPING == res.extract_mapping()
def test_commands(command, args, response, expected_result, expected_auto_extract, mocker): """Unit test Given - command main func - command args - command raw response When - mock the ServiceNow response Then - convert the result to human readable table - create the context validate the entry context """ client = Client('server_url', 'username', 'password', 'verify', 'proxy', 'fetch_time', 'sysparm_query', 'sysparm_limit', 'timestamp_field', 'ticket_type', 'get_attachments') mocker.patch.object(client, 'send_request', return_value=response) result = command(client, args) assert expected_result == result[1] # entry context is found in the 2nd place in the result of the command assert expected_auto_extract == result[3] # ignore_auto_extract is in the 4th place in the result of the command
def test_multiple_query_params(requests_mock, command, args): """ Given: - Query with multiple arguments When: - Using servicenow-query-tickets command with multiple sysparm_query arguments. - Using servicenow-query-table command with multiple sysparm_query arguments. Then: - Verify the right request is called with '&' distinguishing different arguments. """ url = 'https://test.service-now.com/api/now/v2/' client = Client(url, 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', 'sysparm_limit', 'timestamp_field', 'ticket_type', 'get_attachments', 'incident_name') requests_mock.request('GET', f'{url}table/sc_task?sysparm_limit=50&sysparm_offset=0&' 'sysparm_query=assigned_to%3D123&sysparm_query=active%3Dtrue', json=RESPONSE_TICKET_ASSIGNED) human_readable, entry_context, result, bol = command(client, args) assert result == RESPONSE_TICKET_ASSIGNED
def test_get_modified_remote_data(requests_mock, mocker, api_response): """ Given: - Case A: No updated records - Case B: 2 updated records When: - Running get-modified-remote-data Then: - Case A: Ensure no record IDs returned - Case B: Ensure the 2 records IDs returned """ mocker.patch.object(demisto, 'debug') url = 'https://test.service-now.com/api/now/v2/' client = Client(url, 'sc_server_url', 'username', 'password', 'verify', 'fetch_time', 'sysparm_query', 'sysparm_limit', 'timestamp_field', 'ticket_type', 'get_attachments', 'incident_name') last_update = '2020-11-18T13:16:52.005381+02:00' params = { 'sysparm_limit': '100', 'sysparm_offset': '0', 'sysparm_query': 'sys_updated_on>2020-11-18 11:16:52', 'sysparm_fields': 'sys_id', } requests_mock.request('GET', f'{url}table/ticket_type?{urlencode(params)}', json=api_response) result = get_modified_remote_data_command(client, {'lastUpdate': last_update}) assert result.modified_incident_ids == [ record.get('sys_id') for record in api_response.get('result') if 'sys_id' in record ]