text: import pytest
  import json
  import io
  import ServiceNowv2
  from CommonServerPython import DemistoException
  from ServiceNowv2 import get_server_url, get_ticket_context, get_ticket_human_readable, \
      generate_body, split_fields, Client, update_ticket_command, create_ticket_command, delete_ticket_command, \
      query_tickets_command, add_link_command, add_comment_command, upload_file_command, get_ticket_notes_command, \
      get_record_command, update_record_command, create_record_command, delete_record_command, query_table_command, \
      list_table_fields_command, query_computers_command, get_table_name_command, add_tag_command, query_items_command, \
      get_item_details_command, create_order_item_command, document_route_to_table, fetch_incidents, main, \
      get_mapping_fields_command, get_remote_data_command, update_remote_system_command, build_query_for_request_params, \
      ServiceNowClient, oauth_test_module, login_command, get_modified_remote_data_command, parse_build_query, \
      get_ticket_fields, check_assigned_to_field, generic_api_call_command
  from ServiceNowv2 import test_module as module
  from test_data.response_constants import RESPONSE_TICKET, RESPONSE_MULTIPLE_TICKET, RESPONSE_UPDATE_TICKET, \
      RESPONSE_UPDATE_TICKET_SC_REQ, RESPONSE_CREATE_TICKET, RESPONSE_CREATE_TICKET_WITH_OUT_JSON, RESPONSE_QUERY_TICKETS, \
      RESPONSE_ADD_LINK, RESPONSE_ADD_COMMENT, RESPONSE_UPLOAD_FILE, RESPONSE_GET_TICKET_NOTES, RESPONSE_GET_RECORD, \
      RESPONSE_UPDATE_RECORD, RESPONSE_CREATE_RECORD, RESPONSE_QUERY_TABLE, RESPONSE_LIST_TABLE_FIELDS, \
      RESPONSE_QUERY_COMPUTERS, RESPONSE_GET_TABLE_NAME, RESPONSE_UPDATE_TICKET_ADDITIONAL, \
      RESPONSE_QUERY_TABLE_SYS_PARAMS, RESPONSE_ADD_TAG, RESPONSE_QUERY_ITEMS, RESPONSE_ITEM_DETAILS, \
      RESPONSE_CREATE_ITEM_ORDER, RESPONSE_DOCUMENT_ROUTE, RESPONSE_FETCH, RESPONSE_FETCH_ATTACHMENTS_FILE, \
      RESPONSE_FETCH_ATTACHMENTS_TICKET, RESPONSE_TICKET_MIRROR, MIRROR_COMMENTS_RESPONSE, RESPONSE_MIRROR_FILE_ENTRY, \
      RESPONSE_ASSIGNMENT_GROUP, RESPONSE_MIRROR_FILE_ENTRY_FROM_XSOAR, MIRROR_COMMENTS_RESPONSE_FROM_XSOAR, \
      MIRROR_ENTRIES, RESPONSE_CLOSING_TICKET_MIRROR, RESPONSE_TICKET_ASSIGNED, OAUTH_PARAMS, \
      RESPONSE_QUERY_TICKETS_EXCLUDE_REFERENCE_LINK, MIRROR_ENTRIES_WITH_EMPTY_USERNAME, USER_RESPONSE, RESPONSE_GENERIC_TICKET
  from test_data.result_constants import EXPECTED_TICKET_CONTEXT, EXPECTED_MULTIPLE_TICKET_CONTEXT, \
      EXPECTED_TICKET_HR, EXPECTED_MULTIPLE_TICKET_HR, EXPECTED_UPDATE_TICKET, EXPECTED_UPDATE_TICKET_SC_REQ, \
      EXPECTED_CREATE_TICKET, EXPECTED_CREATE_TICKET_WITH_OUT_JSON, EXPECTED_QUERY_TICKETS, EXPECTED_ADD_LINK_HR, \
      EXPECTED_ADD_COMMENT_HR, EXPECTED_UPLOAD_FILE, EXPECTED_GET_TICKET_NOTES, EXPECTED_GET_RECORD, \
      EXPECTED_UPDATE_RECORD, EXPECTED_CREATE_RECORD, EXPECTED_QUERY_TABLE, EXPECTED_LIST_TABLE_FIELDS, \
      EXPECTED_QUERY_COMPUTERS, EXPECTED_GET_TABLE_NAME, EXPECTED_UPDATE_TICKET_ADDITIONAL, \
      EXPECTED_QUERY_TABLE_SYS_PARAMS, EXPECTED_ADD_TAG, EXPECTED_QUERY_ITEMS, EXPECTED_ITEM_DETAILS, \
      EXPECTED_CREATE_ITEM_ORDER, EXPECTED_DOCUMENT_ROUTE, EXPECTED_MAPPING, \
      EXPECTED_TICKET_CONTEXT_WITH_ADDITIONAL_FIELDS, EXPECTED_QUERY_TICKETS_EXCLUDE_REFERENCE_LINK, \
      EXPECTED_TICKET_CONTEXT_WITH_NESTED_ADDITIONAL_FIELDS
  from test_data.created_ticket_context import CREATED_TICKET_CONTEXT_CREATE_CO_FROM_TEMPLATE_COMMAND, \
      CREATED_TICKET_CONTEXT_GET_TASKS_FOR_CO_COMMAND
  
  import demistomock as demisto
  from urllib.parse import urlencode
  
  
  def util_load_json(path):
      with io.open(path, mode='r', encoding='utf-8') as f:
          return json.loads(f.read())
  
  
  def test_get_server_url():
      assert "http://www.demisto.com/" == get_server_url("http://www.demisto.com//")
  
  
  def test_get_ticket_context():
      assert EXPECTED_TICKET_CONTEXT == get_ticket_context(RESPONSE_TICKET)
  
      assert EXPECTED_MULTIPLE_TICKET_CONTEXT[0] in get_ticket_context(RESPONSE_MULTIPLE_TICKET)
      assert EXPECTED_MULTIPLE_TICKET_CONTEXT[1] in get_ticket_context(RESPONSE_MULTIPLE_TICKET)
  
  
  def test_get_ticket_context_additional_fields():
      """Unit test
      Given
          - additional keys of a ticket alongside regular keys.
      When
          - getting a ticket context
      Then
          - validate that all the details of the ticket were updated, and all the updated keys are shown in
          the context with do duplicates.
      """
      assert EXPECTED_TICKET_CONTEXT_WITH_ADDITIONAL_FIELDS == get_ticket_context(RESPONSE_TICKET,
                                                                                  ['Summary', 'sys_created_by'])
  
  
  def test_get_ticket_context_nested_additional_fields():
      """Unit test
      Given
          - nested additional keys of a ticket (in the form of a.b), alongside regular keys.
      When
          - getting a ticket context
      Then
          - validate that all the details of the ticket were updated, and all the updated keys are shown in
          the context with do duplicates.
      """
      assert EXPECTED_TICKET_CONTEXT_WITH_NESTED_ADDITIONAL_FIELDS == get_ticket_context(RESPONSE_TICKET,
                                                                                         ['Summary', 'opened_by.link'])
  
  
  def test_get_ticket_human_readable():
      assert EXPECTED_TICKET_HR == get_ticket_human_readable(RESPONSE_TICKET, 'incident')
  
      assert EXPECTED_MULTIPLE_TICKET_HR[0] in get_ticket_human_readable(RESPONSE_MULTIPLE_TICKET, 'incident')
      assert EXPECTED_MULTIPLE_TICKET_HR[1] in get_ticket_human_readable(RESPONSE_MULTIPLE_TICKET, 'incident')
  
  
  def test_generate_body():
      fields = {'a_field': 'test'}
      custom_fields = {'a_custom_field': 'test'}
      expected_body = {'a_field': 'test', 'u_a_custom_field': 'test'}
      assert expected_body == generate_body(fields, custom_fields)
  
  
  def test_split_fields():
      expected_dict_fields = {'a': 'b', 'c': 'd', 'e': ''}
      assert expected_dict_fields == split_fields('a=b;c=d;e=')
  
      expected_custom_field = {'u_customfield': "<a href=\'https://google.com\'>Link text</a>"}
      assert expected_custom_field == split_fields("u_customfield=<a href=\'https://google.com\'>Link text</a>")
  
      expected_custom_sys_params = {
          "sysparm_display_value": 'all',
          "sysparm_exclude_reference_link": 'True',
          "sysparm_query": 'number=TASK0000001'
      }
  
      assert expected_custom_sys_params == split_fields(
          "sysparm_display_value=all;sysparm_exclude_reference_link=True;sysparm_query=number=TASK0000001")
  
      try:
          split_fields('a')
      except Exception as err:
          assert "must contain a '=' to specify the keys and values" in str(err)
          return
      assert False
  
  
  def test_split_fields_with_special_delimiter():
      """Unit test
      Given
      - split_fields method
      - the default delimiter is ;
      When
      - splitting values with a different delimiter - ','
      Then
      -  Validate the fields were created correctly
      """
      expected_dict_fields = {'a': 'b', 'c': 'd'}
      assert expected_dict_fields == split_fields('a=b,c=d', ',')
  
      expected_custom_field = {'u_customfield': "<a href=\'https://google.com\'>Link text<;/a>"}
      assert expected_custom_field == split_fields("u_customfield=<a href=\'https://google.com\'>Link text<;/a>", ',')
  
      try:
          split_fields('a')
      except Exception as err:
          assert "must contain a '=' to specify the keys and values" in str(err)
          return
      assert False
  
  
  @pytest.mark.parametrize('query, parsed, result', [
      ('&', False, '&'),
      ('&', True, []),
      ('noampersand', False, 'noampersand'),
      ('noampersand', True, 'noampersand')
  ])
  def test_parse_build_query(query, parsed, result):
      """Unit test
      Given
      - an ampersand
      When
      - no parsing the ampersand
      - when parsing the ampersand
      Then
      -  Validate the query field is parsed correctly.
      """
      assert parse_build_query(query, parse_amp=parsed) == result
  
  
  @pytest.mark.parametrize('command, args, response, expected_result, expected_auto_extract', [
      (update_ticket_command, {'id': '1234', 'impact': '2'}, RESPONSE_UPDATE_TICKET, EXPECTED_UPDATE_TICKET, True),
      (update_ticket_command, {'id': '1234', 'ticket_type': 'sc_req_item', 'approval': 'requested'},
       RESPONSE_UPDATE_TICKET_SC_REQ, EXPECTED_UPDATE_TICKET_SC_REQ, True),
      (update_ticket_command, {'id': '1234', 'severity': '3', 'additional_fields': "approval=rejected"},
       RESPONSE_UPDATE_TICKET_ADDITIONAL, EXPECTED_UPDATE_TICKET_ADDITIONAL, True),
      (create_ticket_command, {'active': 'true', 'severity': "3", 'description': "creating a test ticket",
                               'sla_due': "2020-10-10 10:10:11"}, RESPONSE_CREATE_TICKET, EXPECTED_CREATE_TICKET, True),
      (create_ticket_command, {'active': 'true', 'severity': "3", 'description': "creating a test ticket",
                               'sla_due': "2020-10-10 10:10:11"}, RESPONSE_CREATE_TICKET_WITH_OUT_JSON,
       EXPECTED_CREATE_TICKET_WITH_OUT_JSON, True),
      (query_tickets_command, {'limit': "3", 'query': "impact<2^short_descriptionISNOTEMPTY", 'ticket_type': "incident"},
       RESPONSE_QUERY_TICKETS, EXPECTED_QUERY_TICKETS, True),
      (query_tickets_command,
       {"ticket_type": "incident", "query": "number=INC0000001", "system_params": "sysparm_exclude_reference_link=true"},
       RESPONSE_QUERY_TICKETS_EXCLUDE_REFERENCE_LINK, EXPECTED_QUERY_TICKETS_EXCLUDE_REFERENCE_LINK, True),
      (upload_file_command, {'id': "sys_id", 'file_id': "entry_id", 'file_name': 'test_file'}, RESPONSE_UPLOAD_FILE,
       EXPECTED_UPLOAD_FILE, True),
      (get_ticket_notes_command, {'id': "sys_id"}, RESPONSE_GET_TICKET_NOTES, EXPECTED_GET_TICKET_NOTES, True),
      (get_record_command, {'table_name': "alm_asset", 'id': "sys_id", 'fields': "asset_tag,display_name"},
       RESPONSE_GET_RECORD, EXPECTED_GET_RECORD, True),
      (update_record_command, {'name': "alm_asset", 'id': "1234", 'custom_fields': "display_name=test4"},
       RESPONSE_UPDATE_RECORD, EXPECTED_UPDATE_RECORD, True),
      (create_record_command, {'table_name': "alm_asset", 'fields': "asset_tag=P4325434;display_name=my_test_record"},
       RESPONSE_CREATE_RECORD, EXPECTED_CREATE_RECORD, True),
      (query_table_command, {'table_name': "alm_asset", 'fields': "asset_tag,sys_updated_by,display_name",
                             'query': "display_nameCONTAINSMacBook", 'limit': 3}, RESPONSE_QUERY_TABLE,
       EXPECTED_QUERY_TABLE, False),
      (query_table_command, {
          'table_name': "sc_task", 'system_params':
              'sysparm_display_value=all;sysparm_exclude_reference_link=True;sysparm_query=number=TASK0000001',
          'fields': "approval,state,escalation,number,description"
      }, RESPONSE_QUERY_TABLE_SYS_PARAMS, EXPECTED_QUERY_TABLE_SYS_PARAMS, False),
      (list_table_fields_command, {'table_name': "alm_asset"}, RESPONSE_LIST_TABLE_FIELDS, EXPECTED_LIST_TABLE_FIELDS,
       False),
      (query_computers_command, {'computer_id': '1234'}, RESPONSE_QUERY_COMPUTERS, EXPECTED_QUERY_COMPUTERS, False),
      (get_table_name_command, {'label': "ACE"}, RESPONSE_GET_TABLE_NAME, EXPECTED_GET_TABLE_NAME, False),
      (add_tag_command, {'id': "123", 'tag_id': '1234', 'title': 'title'}, RESPONSE_ADD_TAG, EXPECTED_ADD_TAG, True),
      (query_items_command, {'name': "ipad", 'limit': '2'}, RESPONSE_QUERY_ITEMS, EXPECTED_QUERY_ITEMS, True),
      (get_item_details_command, {'id': "1234"}, RESPONSE_ITEM_DETAILS, EXPECTED_ITEM_DETAILS, True),
      (create_order_item_command, {'id': "1234", 'quantity': "3",
                                   'variables': "Additional_software_requirements=best_pc"},
       RESPONSE_CREATE_ITEM_ORDER, EXPECTED_CREATE_ITEM_ORDER, True),
      (document_route_to_table, {'queue_id': 'queue_id', 'document_id': 'document_id'}, RESPONSE_DOCUMENT_ROUTE,
       EXPECTED_DOCUMENT_ROUTE, True),
  ])  # noqa: E124
  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', 'sc_server_url', 'cr_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=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
  
  
  @pytest.mark.parametrize('command, args, response, expected_hr, expected_auto_extract', [
      (delete_ticket_command, {'id': '1234'}, {}, 'Ticket with ID 1234 was successfully deleted.', True),
      (add_link_command, {'id': '1234', 'link': "http://www.demisto.com", 'text': 'demsito_link'}, RESPONSE_ADD_LINK,
       EXPECTED_ADD_LINK_HR, True),
      (add_comment_command, {'id': "1234", 'comment': "Nice work!"}, RESPONSE_ADD_COMMENT, EXPECTED_ADD_COMMENT_HR, True),
      (delete_record_command, {'table_name': "alm_asset", 'id': '1234'}, {},
       'ServiceNow record with ID 1234 was successfully deleted.', True),
  ])  # noqa: E124
  def test_no_ec_commands(command, args, response, expected_hr, 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 human readable
      """
      client = Client('server_url', 'sc_server_url', 'cr_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=response)
      result = command(client, args)
      assert expected_hr in result[0]  # HR is found in the 1st 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_fetch_incidents(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', 'cr_server_url', 'username', 'password',
                      'verify', 'fetch_time', 'sysparm_query', sysparm_limit=10,
                      timestamp_field='opened_at', ticket_type='incident', get_attachments=False, incident_name='number')
      mocker.patch.object(client, 'send_request', return_value=RESPONSE_FETCH)
      incidents = fetch_incidents(client)
      assert len(incidents) == 2
      assert incidents[0].get('name') == 'ServiceNow Incident INC0000040'
  
  
  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', 'cr_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_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', 'cr_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_incident_name_is_initialized(mocker, requests_mock):
      """
      Given:
       - Integration instance initialized with fetch enabled and without changing incident name
  
      When:
       - Clicking on Test button (running test-module)
  
      Then:
       - Verify expected exception is raised as default incident name value is not in response
      """
      url = 'https://test.service-now.com'
      mocker.patch.object(
          demisto,
          'params',
          return_value={
              'isFetch': True,
              'url': url,
              'credentials': {
                  'identifier': 'identifier',
                  'password': 'password',
              },
              'incident_name': None
          }
      )
      mocker.patch.object(demisto, 'command', return_value='test-module')
  
      def return_error_mock(message, error):
          raise
  
      mocker.patch('ServiceNowv2.return_error', side_effect=return_error_mock)
      requests_mock.get(
          f'{url}/api/now/table/incident?sysparm_limit=1',
          json={
              'result': [{
                  'opened_at': 'sometime'
              }]
          }
      )
      with pytest.raises(ValueError) as e:
          main()
      assert str(e.value) == 'The field [number] does not exist in the ticket.'
  
  
  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', 'cr_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_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', 'cr_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_oauth_authentication(mocker, requests_mock):
      """
      Given:
       - Integration instance, initialized with the `Use OAuth Login` checkbox selected.
  
      When:
       - Clicking on running the !servicenow-oauth-test command.
  
      Then:
       - Verify that oauth authorization flow is used by checking that the get_access_token is called.
      """
      from unittest.mock import MagicMock
      url = 'https://test.service-now.com'
      mocker.patch.object(demisto, 'command', return_value='servicenow-oauth-test')
      mocker.patch.object(ServiceNowClient, 'get_access_token')
      requests_mock.get(
          f'{url}/api/now/table/incident?sysparm_limit=1',
          json={
              'result': [{
                  'opened_at': 'sometime'
              }]
          }
      )
  
      # Assert that get_access_token is called when `Use OAuth Login` checkbox is selected:
      mocker.patch.object(
          demisto,
          'params',
          return_value={
              'url': url,
              'credentials': {
                  'identifier': 'client_id',
                  'password': 'client_secret'
              },
              'use_oauth': True
          }
      )
      ServiceNowClient.get_access_token = MagicMock()
      main()
      assert ServiceNowClient.get_access_token.called
  
  
  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', 'cr_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', 'cr_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_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', 'cr_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', 'cr_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_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', 'cr_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': 'username', 'password': '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', 'cr_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': 'username', 'password': 'password'})
      assert '### Logged in successfully.' in result[0]
  
  
  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', cr_server_url='cr_server_url',
                      username='username', password='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_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', cr_server_url='cr_server_url',
                      username='username', password='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_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',
                      cr_server_url='cr_server_url', username='username',
                      password='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_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_assigned_to_field_no_user():
      """
      Given:
          -  Client class
          -  Assigned_to field for user that doesn't exist in SNOW
      When
          - run check_assigned_to_field command
      Then
          - Check that assign_to value is empty
      """
      class Client:
          def get(self, table, value):
              return {'results': {}}
  
      assigned_to = {'link': 'https://test.service-now.com/api/now/table/sys_user/oscar@example.com',
                     'value': 'oscar@example.com'}
      res = check_assigned_to_field(Client(), assigned_to)
      assert res == ''
  
  
  def test_assigned_to_field_user_exists():
      """
      Given:
          -  Client class
          -  Assigned_to field for user that does exist in SNOW
      When
          - run check_assigned_to_field command
      Then
          - Check that assign_to value is filled with the right email
      """
      class Client:
          def get(self, table, value):
              return USER_RESPONSE
  
      assigned_to = {'link': 'https://test.service-now.com/api/now/table/sys_user/oscar@example.com',
                     'value': 'oscar@example.com'}
      res = check_assigned_to_field(Client(), assigned_to)
      assert res == 'oscar@example.com'
  
  
  CLOSING_RESPONSE = {'dbotIncidentClose': True, 'closeReason': 'From ServiceNow: Test'}
  
  
  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',
                      cr_server_url="cr_server_url", username='username',
                      password='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_get_remote_data_no_attachment(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 no attachment.
      """
  
      client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url',
                      cr_server_url="cr_server_url", username='username',
                      password='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=[])
      mocker.patch.object(client, 'get_ticket_attachment_entries', return_value=[])
      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]['Contents'] == 'This is a comment'
      assert len(res) == 2
  
  
  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',
                      cr_server_url='cr_server_url', username='username',
                      password='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 upload_file_request(*args):
      assert 'test_mirrored_from_xsoar.txt' == args[2]
      return {'id': "sys_id", 'file_id': "entry_id", 'file_name': 'test.txt'}
  
  
  def add_comment_request(*args):
      assert '(dbot): This is a comment\n\n Mirrored from Cortex XSOAR' == args[3]
      return {'id': "1234", 'comment': "This is a comment"}
  
  
  @pytest.mark.parametrize('mirror_entries', [MIRROR_ENTRIES, MIRROR_ENTRIES_WITH_EMPTY_USERNAME])
  def test_upload_entries_update_remote_system_command(mocker, mirror_entries):
      """
      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',
                      cr_server_url='cr_server_url', username='username',
                      password='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)
  
  
  TICKET_FIELDS = {'close_notes': 'This is closed', 'closed_at': '2020-10-29T13:19:07.345995+02:00', 'impact': '3',
                   'priority': '4', 'resolved_at': '2020-10-29T13:19:07.345995+02:00', 'severity': '1 - Low',
                   'short_description': 'Post parcel', 'sla_due': '0001-01-01T00:00:00Z', 'urgency': '3', 'state': '1',
                   'work_start': '0001-01-01T00:00:00Z'}
  
  
  def ticket_fields(*args, **kwargs):
      state = '7' if kwargs.get('ticket_type') == 'incident' else '3'
      assert {'close_notes': 'This is closed', 'closed_at': '2020-10-29T13:19:07.345995+02:00', 'impact': '3',
              'priority': '4', 'resolved_at': '2020-10-29T13:19:07.345995+02:00', 'severity': '1 - Low',
              'short_description': 'Post parcel', 'sla_due': '0001-01-01T00:00:00Z', 'urgency': '3', 'state': state,
              'work_start': '0001-01-01T00:00:00Z'} == args[0]
  
      return {'close_notes': 'This is closed', 'closed_at': '2020-10-29T13:19:07.345995+02:00', 'impact': '3',
              'priority': '4', 'resolved_at': '2020-10-29T13:19:07.345995+02:00', 'severity': '1 - Low',
              'short_description': 'Post parcel', 'sla_due': '0001-01-01T00:00:00Z', 'urgency': '3', 'state': '1',
              'work_start': '0001-01-01T00:00:00Z'}
  
  
  def update_ticket(*args):
      state = '7' if 'incident' in args else '3'
      return {'short_description': 'Post parcel', 'close_notes': 'This is closed',
              'closed_at': '2020-10-29T13:19:07.345995+02:00', 'impact': '3', 'priority': '4',
              'resolved_at': '2020-10-29T13:19:07.345995+02:00', 'severity': '1 - High - Low',
              'sla_due': '0001-01-01T00:00:00Z', 'state': state, 'urgency': '3', 'work_start': '0001-01-01T00:00:00Z'}
  
  
  @pytest.mark.parametrize('ticket_type', ['sc_task', 'sc_req_item', 'incident'])
  def test_update_remote_data_sc_task_sc_req_item(mocker, ticket_type):
      """
      Given:
      -  ServiceNow client
      -  ServiceNow ticket of type sc_task
      -  ServiceNow ticket of type sc_req_item
      -  ServiceNow ticket of type incident
  
      When
          - running update_remote_system_command.
      Then
          - The state is changed to 3 (closed) after update for sc_task and sc_req_item.
          - The state is changed to 7 (closed) after update for incident.
      """
      client = Client(server_url='https://server_url.com/', sc_server_url='sc_server_url',
                      cr_server_url='cr_server_url', username='username',
                      password='password', verify=False, fetch_time='fetch_time',
                      sysparm_query='sysparm_query', sysparm_limit=10, timestamp_field='opened_at',
                      ticket_type=ticket_type, get_attachments=False, incident_name='description')
      params = {'ticket_type': ticket_type, '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)
  
  
  @pytest.mark.parametrize('query, expected', [
      ("id=5&status=pi", ["id=5", "status=pi"]),
      ("id=5&status=pi&name=bobby", ["id=5", "status=pi", "name=bobby"]),
      ("&status=pi", ["status=pi"]),
      ("status=pi&", ["status=pi"]),
  ])
  def test_build_query_for_request_params(query, expected):
      """
      Given:
       - Query with multiple arguments
  
      When:
       - Running Cilent.query function
  
      Then:
       - Verify the query was split to a list of sub queries according to the &.
      """
      sub_queries = build_query_for_request_params(query)
      assert sub_queries == expected
  
  
  @pytest.mark.parametrize('command, args', [
      (query_tickets_command, {'limit': "50", 'query': "assigned_to=123&active=true", 'ticket_type': "sc_task"}),
      (query_table_command, {'limit': "50", 'query': "assigned_to=123&active=true", 'table_name': "sc_task"})
  ])
  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', 'cr_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
  
  
  @pytest.mark.parametrize('api_response', [
      ({'result': []}),
      ({'result': [{'sys_id': 'sys_id1'}, {'sys_id': 'sys_id2'}]}),
  ])
  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', 'cr_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
      ]
  
  
  @pytest.mark.parametrize('sys_created_on, expected', [
      (None, 'table_sys_id=id'),
      ('', 'table_sys_id=id'),
      ('2020-11-18 11:16:52', 'table_sys_id=id^sys_created_on>2020-11-18 11:16:52')
  ])
  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', 'cr_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}'})
  
  
  @pytest.mark.parametrize('args,expected_ticket_fields', [
      ({'clear_fields': 'assigned_to,severity'}, {'assigned_to': '', 'severity': ''}),
      ({'clear_fields': 'assigned_to,severity', 'assigned_to': 'assigned@to.com'}, {'assigned_to': '', 'severity': ''}),
      ({}, {}),
  ])
  def test_clear_fields_in_get_ticket_fields(args, expected_ticket_fields):
      if 'assigned_to' in args:
          with pytest.raises(DemistoException) as e:
              res = get_ticket_fields(args)
          assert str(e.value) == "Could not set a value for the argument 'assigned_to' and add it to the clear_fields. \
                  You can either set or clear the field value."
      else:
          res = get_ticket_fields(args)
          assert res == expected_ticket_fields
  
  
  def test_query_table_with_fields(mocker):
      """
      Given:
          - Fields for query table
  
      When:
          - Run query table command
  
      Then:
          - Validate the fields was sent as params in the request and sys_id appear in fields
      """
  
      # prepare
      client = Client('server_url', 'sc_server_url', 'cr_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={
          "result": [
              {
                  "sys_id": "test_id",
                  "sys_updated_by": "test_updated_name",
                  "opened_by.name": "test_opened_name"
              }
          ]})
      fields = "sys_updated_by,opened_by.name"
      fields_with_sys_id = f'{fields},sys_id'
      args = {'table_name': "alm_asset", 'fields': fields,
              'query': "display_nameCONTAINSMacBook", 'limit': 3}
  
      # run
      result = query_table_command(client, args)
  
      # validate
      assert client.send_request.call_args[1]['params']['sysparm_fields'] == fields_with_sys_id
      # validate that the '.' in the key was replaced to '_'
      assert result[1]['ServiceNow.Record(val.ID===obj.ID)'][0]['opened_by_name'] == 'test_opened_name'
  
  
  def test_create_co_from_template_command(mocker):
      """
      Given:
          - template to create change request from it.
  
      When:
          - Using servicenow-create-co-from-template command.
  
      Then:
          - Validate the output is correct.
      """
      client = Client('server_url', 'sc_server_url', 'cr_server_url', 'username', 'password', 'verify', 'fetch_time',
                      'sysparm_query', 'sysparm_limit', 'timestamp_field', 'ticket_type', 'get_attachments',
                      'incident_name')
  
      args = {"template": "Add network switch to datacenter cabinet"}
      mocker.patch.object(client,
                          'send_request',
                          return_value=util_load_json('test_data/create_co_from_template_result.json'))
      result = ServiceNowv2.create_co_from_template_command(client, args)
      assert result.outputs_prefix == "ServiceNow.Ticket"
      assert result.outputs == {
          'Ticket(val.ID===obj.ID)': CREATED_TICKET_CONTEXT_CREATE_CO_FROM_TEMPLATE_COMMAND,
          'ServiceNow.Ticket(val.ID===obj.ID)': CREATED_TICKET_CONTEXT_CREATE_CO_FROM_TEMPLATE_COMMAND
      }
      assert result.raw_response == util_load_json('test_data/create_co_from_template_result.json')
  
  
  def test_get_tasks_for_co_command(mocker):
      """
      Given:
          - id to get tasks from it.
  
      When:
          - Using servicenow-get-tasks-for-co command.
  
      Then:
          - Validate the output is correct.
      """
      client = Client('server_url', 'sc_server_url', 'cr_server_url', 'username', 'password', 'verify', 'fetch_time',
                      'sysparm_query', 'sysparm_limit', 'timestamp_field', 'problem', 'get_attachments', 'incident_name')
  
      args = {"id": "a9e9c33dc61122760072455df62663d2"}
      mocker.patch.object(client,
                          'send_request',
                          return_value=util_load_json('test_data/get_tasks_for_co_command.json'))
      result = ServiceNowv2.get_tasks_for_co_command(client, args)
      assert result.outputs_prefix == "ServiceNow.Tasks"
      assert result.outputs == {
          'ServiceNow.Tasks(val.ID===obj.ID)': CREATED_TICKET_CONTEXT_GET_TASKS_FOR_CO_COMMAND
      }
      assert result.raw_response == util_load_json('test_data/get_tasks_for_co_command.json')
  
  
  def test_get_ticket_attachment_entries_with_oauth_token(mocker):
      """
      The purpose of this test is to verify that it is possible to get a file attachment of a ServiceNow ticket by using
      an OAuth 2.0 client.
  
      Given:
          - A client with 'oauth_params' - i.e a client that is configured with an OAuth 2.0 Authorization.
          - Mock responses for 'get_ticket_attachments', 'get_access_token' and 'requests.get' functions.
  
      When:
          - Running the 'client.get_ticket_attachment_entries' function.
  
      Then:
          - Verify that the 'requests.get' function's arguments are arguments of a call with OAuth 2.0 Authorization.
      """
      # Preparations and mocking:
      client = Client("url", 'sc_server_url', 'cr_server_url', 'username', 'password', 'verify', 'fetch_time',
                      'sysparm_query', 'sysparm_limit', 'timestamp_field', 'ticket_type', 'get_attachments',
                      'incident_name', oauth_params={'oauth_params': ''})
  
      mock_res_for_get_ticket_attachments = \
          {'result': [
              {
                  'file_name': 'attachment for test.txt',
                  'download_link': 'https://ven03941.service-now.com/api/now/attachment/12b7ea411b15cd10042611b4bd4/file'
              }]}
  
      mock_res_for_get_access_token = 'access_token'
  
      mocker.patch.object(client, 'get_ticket_attachments', return_value=mock_res_for_get_ticket_attachments)
      mocker.patch.object(client.snow_client, 'get_access_token', return_value=mock_res_for_get_access_token)
      requests_get_mocker = mocker.patch('requests.get', return_value=None)
  
      # Running get_ticket_attachment_entries function:
      client.get_ticket_attachment_entries(ticket_id='id')
  
      # Validate Results are as expected:
      assert requests_get_mocker.call_args.kwargs.get('auth') is None,\
          "When An OAuth 2.0 client is configured the 'auth' argument shouldn't be passed to 'requests.get' function"
      assert requests_get_mocker.call_args.kwargs.get('headers').get('Authorization') == \
             f"Bearer {mock_res_for_get_access_token}", "When An OAuth 2.0 client is configured the 'Authorization'" \
                                                        " Header argument should be passed to 'requests.get' function"
  
  
  @pytest.mark.parametrize(
      'command, args, response',
      [
          (generic_api_call_command,
           {"method": "GET",
            "path": "table/sn_si_incident?sysparam_limit=1&sysparam_query=active=true^ORDERBYDESCnumber",
            "body": {},
            "headers": {},
            },
           RESPONSE_GENERIC_TICKET)
      ])
  def test_generic_api_call_command(command, args, response, mocker):
      """test case for `generic_api_call_command`"""
  
      client = Client('server_url', 'sc_server_url', 'cr_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=response)
      result = command(client, args)
      assert result.outputs == response
  