BMCHelixRemedyforce

BMC Helix Remedyforce integration enables customers to create/update service requests and incidents, update statuses, and resolve service requests and incidents with customer notes. This integration exposes standard ticketing capabilities that can be utilized as part of automation & orchestration.

Utilities · Bmc Helix Remedyforce

Details

IDBMCHelixRemedyforce
ProviderBMC Software
CategoryUtilities
From Version5.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

BMC Helix Remedyforce integration allows customers to create/update service requests and incidents. It also allows to update status, resolve service requests and incidents with customer notes. This integration exposes standard ticketing capabilities that can be utilized as part of automation & orchestration.
This integration was integrated and tested with version 202002.79 of BMC Helix Remedyforce.

Configure BMC Helix Remedyforce in Cortex

Parameter Description Required
url BMC Remedyforce URL (e.g. https://example.com) True
username Username True
password Password True
type Type False
category Category False
impact Impact False
urgency Urgency False
status Status False
queue Queue False
max_incidents Max Incidents False
fetch_note Fetch Note(s) False
query Query (If provided other filtering parameters will be ignored) e.g. select Name, LastModifiedDate from BMCServiceDesk__Incident__c where BMCServiceDesk__Impact_Id__c = ‘High’ False
incidentType Incident type False
insecure Trust any certificate (not secure) False
proxy Use system proxy settings False
request_timeout HTTP(S) Request Timeout (in seconds) True
isFetch Fetch incidents False
firstFetchTimestamp First Fetch Timestamp (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year) False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

bmc-remedy-service-request-definition-get


This command gets details of service request definitions with the help of service request definition name.

Base Command

bmc-remedy-service-request-definition-get

Input

Argument Name Description Required
service_request_definition_name service_request_definition_name is the name of the service request definition whose details the user wants to get. If any value is not specified, it gets details of all service request definitions. Optional

Context Output

Path Type Description
BmcRemedyforce.ServiceRequestDefinition.Id String Service Request Definition Id.
BmcRemedyforce.ServiceRequestDefinition.CategoryId String Category Id of the Service Request Definition.
BmcRemedyforce.ServiceRequestDefinition.IsProblem Boolean Indicates if it is a problem or not.
BmcRemedyforce.ServiceRequestDefinition.LastModifiedDate Date Last modified date.
BmcRemedyforce.ServiceRequestDefinition.CreatedDate Date Created Date.
BmcRemedyforce.ServiceRequestDefinition.Questions.Id String Id of question attached with Service Request Definition.
BmcRemedyforce.ServiceRequestDefinition.Questions.IsRequired Boolean Indicates if a question is required or not.
BmcRemedyforce.ServiceRequestDefinition.Questions.Type String Type of the question.
BmcRemedyforce.ServiceRequestDefinition.Questions.Text String Name of the question.
BmcRemedyforce.ServiceRequestDefinition.Conditions.SRDId String Service Request Definition Id of condition.
BmcRemedyforce.ServiceRequestDefinition.Conditions.Value String Value of the condition.
BmcRemedyforce.ServiceRequestDefinition.Conditions.Operator String Operator of the condition.
BmcRemedyforce.ServiceRequestDefinition.Conditions.DependentQuestionId String Question Id of dependent question which is associated with the condition.
BmcRemedyforce.ServiceRequestDefinition.Conditions.Id String Id of the condition.
BmcRemedyforce.ServiceRequestDefinition.Conditions.QuestionId String Associate question Id for the condition.
BmcRemedyforce.ServiceRequestDefinition.requestFor String Request for field value.
BmcRemedyforce.ServiceRequestDefinition.requestedBy String Requested by field value.
BmcRemedyforce.ServiceRequestDefinition.title String Title field value for Service Request Definition.
BmcRemedyforce.ServiceRequestDefinition.description String Description field value for Service Request Definition.
BmcRemedyforce.ServiceRequestDefinition.approvalRequired Boolean Indicates if approval is required or not.

Command Example

!bmc-remedy-service-request-definition-get service_request_definition_name="Ask Benefits/HR Question"

Context Example

{
    "BmcRemedyforce": {
        "ServiceRequestDefinition": {
            "CategoryId": "a212w000000UFftAAG",
            "CreatedDate": "2020-07-14 06:02:49",
            "Id": "a3H2w000000H5UhEAK",
            "IsProblem": false,
            "LastModifiedDate": "2020-07-14 06:02:49",
            "Questions": [
                {
                    "Id": "a3D2w000000TmAKEA0",
                    "IsRequired": false,
                    "Text": "Benefits/HR Question Details",
                    "Type": "header section"
                },
                {
                    "Id": "a3D2w000000TmALEA0",
                    "IsRequired": true,
                    "Text": "Please provide details on the information you are requesting",
                    "Type": "textarea"
                }
            ],
            "approvalRequired": false,
            "description": "Service Request for information pertaining to Benefits/HR",
            "email": "testuser@mail.com",
            "requestFor": "Test user",
            "requestedBy": "Test user",
            "title": "Ask Benefits/HR Question"
        }
    }
}

Human Readable Output

Total retrieved service request definition(s): 1

Service Request Definition Id Service Request Definition Name Questions
a3H2w000000H5UhEAK Ask Benefits/HR Question Id: a3D2w000000TmAKEA0
Question: Benefits/HR Question Details
Is Required: No

Id: a3D2w000000TmALEA0
Question: Please provide details on the information you are requesting
Is Required: Yes

bmc-remedy-note-create


This command creates notes for incidents and service requests.

Base Command

bmc-remedy-note-create

Input

Argument Name Description Required
request_number The unique incident or service request number that needs to be updated with a note. Required
summary Description of incident or service request while creating the note.
Default value of summary is ‘Client Note’.
Optional
note Detailed note for incident or service request. Optional

Context Output

Path Type Description
BmcRemedyforce.Note.Id String Id of the created note.
BmcRemedyforce.Note.WorkInfoType String Work Information of note.
BmcRemedyforce.Note.ViewAccess String View Access Information of note.
BmcRemedyforce.Note.Summary String The description of the note.
BmcRemedyforce.Note.Submitter String User who added note.
BmcRemedyforce.Note.srId String Id of the Service Request/Incident on which we have added note.
BmcRemedyforce.Note.Notes String Note for Service Request/Incident.
BmcRemedyforce.Note.ModifiedDate Date Last modified date for note.
BmcRemedyforce.Note.CreatedDate Date Created date of note.

Command Example

!bmc-remedy-note-create request_number=SR00000054 summary="demo note" note="demo note"

Context Example

{
    "BmcRemedyforce": {
        "Note": {
            "CreatedDate": "2020-07-30 09:25:42",
            "Id": "a2N2w000000Y39FEAS",
            "ModifiedDate": "2020-07-30 09:25:42",
            "Notes": "demo note\r\ntestuser@bmcremedyforce.com 7/30/2020 2:25 AM",
            "Submitter": "Test user",
            "Summary": "Test user's summary",
            "srId": "a2U2w000000YGQREA4"
        }
    }
}

Human Readable Output

The service request/incident SR00000054 is successfully updated with the note.

bmc-remedy-service-request-update


This command updates the details of a service request for a given service request number.

Base Command

bmc-remedy-service-request-update

Input

Argument Name Description Required
service_request_number The unique number of the service request for which details needs to be updated. Required
category_id category_id is the unique Id of the category. Categories allow users to classify the incident or service request using standard classifications to track the reporting purposes.
Users can get the category Id from the category name using ‘bmc-remedy-category-details-get’ command.
Optional
queue_id queue_id is the unique Id of the owner.
Users can get the queue Id from the owner name using ‘bmc-remedy-queue-details-get’ command.
Optional
staff_id staff_id is the unique Id of the staff to whom the user wants to assign the record.
Users can get the staff Id from the staff details using ‘bmc-remedy-user-details-get’ command.
Optional
status_id status_id is the unique Id of the status that is used to display the progress of the service request through its stages of opening to closure.
Users can get the status Id from the status name using ‘bmc-remedy-status-details-get’ command.
Optional
urgency_id urgency_id is the unique Id of the urgency which is used to determine the priority of the service request.
Users can get the urgency Id from the urgency name using ‘bmc-remedy-urgency-details-get’ command.
Optional
client_id client_id is the unique Id of the client. It helps to select a client for a particular service request.
Users can get the client Id from the email using ‘bmc-remedy-user-details-get’ command.
Optional
additional_fields The fields which are not present in the current argument list can be added here in the format “fieldname1=value;fieldname2=value”.
Possible fields: impact_id, account_id or any other custom field.
Optional

Context Output

Path Type Description
BmcRemedyforce.ServiceRequest.Number String Service request number.
BmcRemedyforce.ServiceRequest.Id String Service request Id.
BmcRemedyforce.ServiceRequest.LastUpdatedDate String Last updated date & time of a service request.

Command Example

!bmc-remedy-service-request-update service_request_number=SR00000054 status_id=a3w2w000000TfGlAAK category_id=a212w000000UFfyAAG aditional_fields="impact_id=HIGH;asset_id=a0K2w000000wi2uEAA"

Context Example

{
    "BmcRemedyforce": {
        "ServiceRequest": {
            "Id": "a2U2w000000YGQREA4",
            "LastUpdatedDate": "2020-08-01T12:05:48Z",
            "Number": "00000054"
        }
    }
}

Human Readable Output

The service request 00000054 is successfully updated.

bmc-remedy-service-request-create


This command allows the user to create a new service request. A service request is the request record that is generated from the service request definition to manage and track the execution.

Base Command

bmc-remedy-service-request-create

Input

Argument Name Description Required
service_request_definition_id The unique Id of the service request definition.
Users can get the service request definition Id from service request definition name using ‘bmc-remedy-service-request-definition-get’ command.
Required
service_request_definition_params Each service request definition expects specific parameters to be supplied. Specify the parameters as a delimiter (;) separated string.
Example: “param1=value1; param2=value2”.
Optional
client_id client_id is the unique Id of the client. It helps to select a client for a particular service request.
Users can get the client Id from the email using ‘bmc-remedy-user-details-get’ command.
Optional
category_id category_id is the unique Id of the category. Categories allow users to classify the incident or service request using standard classifications to track the reporting purposes.
Users can get the category Id from the category name using ‘bmc-remedy-category-details-get’ command.
Optional
queue_id queue_id is the unique Id of the owner.
Users can get the queue Id from the owner name using ‘bmc-remedy-queue-details-get’ command.
Optional
staff_id staff_id is the unique Id of the staff to whom the user wants to assign the record.
Users can get the staff Id from the staff details using ‘bmc-remedy-user-details-get’ command.
Optional
urgency_id urgency_id is the unique Id of the urgency which is used to determine the priority of the service request.
Users can get the urgency Id from the urgency name using ‘bmc-remedy-urgency-details-get’ command.
Optional
status_id status_id is the unique Id of the status that is used to display the progress of the service request through its stages of opening to closure.
Users can get the status Id from the status name using ‘bmc-remedy-status-details-get’ command.
Optional
additional_fields The fields which are not present in the current argument list can be added here in the format “fieldname1=value;fieldname2=value”.
Possible fields: impact_id, account_id or any other custom field.
Optional

Context Output

Path Type Description
BmcRemedyforce.ServiceRequest.Number String Service request number.
BmcRemedyforce.ServiceRequest.Id String Service request Id.
BmcRemedyforce.ServiceRequest.CreatedDate String Creation date & time of service request.

Command Example

!bmc-remedy-service-request-create service_request_definition_id=a3H2w000000H5UVEA0 category_id=a212w000000UFfyAAG status_id=a3w2w000000TfGBAA0

Context Example

{
    "BmcRemedyforce": {
        "ServiceRequest": {
            "CreatedDate": "2020-08-01T12:05:13Z",
            "Id": "a2U2w000000YTEhEAO",
            "Number": "00012192"
        }
    }
}

Human Readable Output

The service request 00012192 is successfully created.

bmc-remedy-template-details-get


This command helps to get template details for Incidents. Templates enable users to prepopulate commonly used fields in a form.

Base Command

bmc-remedy-template-details-get

Input

Argument Name Description Required
template_name template_name is the name of the template whose details the user wants to get. If any value is not specified, it gets details of all the available templates. Optional

Context Output

Path Type Description
BmcRemedyforce.Template.Id String Template Id.
BmcRemedyforce.Template.Name String Template name.
BmcRemedyforce.Template.Description String Template description.
BmcRemedyforce.Template.Recurring Boolean Recurrence of template.

Command Example

!bmc-remedy-template-details-get template_name="General Support - SR"

Context Example

{
    "BmcRemedyforce": {
        "Template": {
            "Description": "Used for the General Support Service Request to capture any issues or requests that may not yet be covered by published SRs.",
            "Id": "a3k2w000000LSl9AAG",
            "Name": "General Support - SR",
            "Recurring": false
        }
    }
}

Human Readable Output

Total retrieved template(s): 1

Id Name Description Recurring
a3k2w000000LSl9AAG General Support - SR Used for the General Support Service Request to capture any issues or requests that may not yet be covered by published SRs. false

bmc-remedy-impact-details-get


This command helps to get impact details for incidents and service requests. Impact helps to calculate priority of the incident or service request.

Base Command

bmc-remedy-impact-details-get

Input

Argument Name Description Required
impact_name impact_name is the name of the impact whose details the user wants to get. If any value is not specified, it gets details of all the available impacts. Optional

Context Output

Path Type Description
BmcRemedyforce.Impact.Id String Impact Id.
BmcRemedyforce.Impact.Name String Impact Name.

Command Example

!bmc-remedy-impact-details-get impact_name=HIGH

Context Example

{
    "BmcRemedyforce": {
        "Impact": {
            "Id": "a2M2w000000UApmEAG",
            "Name": "HIGH"
        }
    }
}

Human Readable Output

Total retrieved impact(s): 1

Id Name
a2M2w000000UApmEAG HIGH

bmc-remedy-service-offering-details-get


This command helps to get service offering details for incidents. Users can link a service offering of the associated service.

Base Command

bmc-remedy-service-offering-details-get

Input

Argument Name Description Required
service_offering_name service_offering_name is the name of service offering whose details the user wants to get. If any value is not specified, it gets details of all the available service offerings. Optional

Context Output

Path Type Description
BmcRemedyforce.ServiceOffering.Id String Service offering Id.
BmcRemedyforce.ServiceOffering.Name String Service offering name.

Command Example

!bmc-remedy-service-offering-details-get service_offering_name="Building Access"

Context Example

{
    "BmcRemedyforce": {
        "ServiceOffering": {
            "Id": "a0K2w000000wi3FEAQ",
            "Name": "Building Access"
        }
    }
}

Human Readable Output

Total retrieved service offering(s): 1

Id Name
a0K2w000000wi3FEAQ Building Access

bmc-remedy-incident-create


This command allows the user to create a new incident.

Base Command

bmc-remedy-incident-create

Input

Argument Name Description Required
client_id client_id is the unique Id of the client. It helps to select a client for a particular Incident.
Users can get the client Id from the email using ‘bmc-remedy-user-details-get’ command.
Required
description This field represents the description of the incident that the user wants to create. Optional
opened_date opened_date is the date and time at which the incident was created. Use the yyyy-MM-ddTHH:mm:ss.SSS+/-HHmm or yyyy-MM-ddTHH:mm:ss.SSSZ formats to specify dateTime fields. Optional
due_date due_date is the date and time at which the incident should be completed. Use the yyyy-MM-ddTHH:mm:ss.SSS+/-HHmm or yyyy-MM-ddTHH:mm:ss.SSSZ formats to specify dateTime fields. Optional
queue_id queue_id is the unique Id of the owner.
Users can get the queue Id from the owner name using ‘bmc-remedy-queue-details-get’ command.
Optional
template_id template_id is the unique Id of the template. Templates enable users to pre-populate commonly used fields in a form.
Users can get the template Id from the template name using ‘bmc-remedy-template-details-get’ command.
Optional
category_id category_id is the unique Id of the category. Categories allow users to classify the incident or service request using standard classifications to track the reporting purposes.
Users can get the category Id from the category name using ‘bmc-remedy-category-details-get’ command.
Optional
urgency_id urgency_id is the unique Id of the urgency which is used to determine the priority of the incident.
Users can get the urgency Id from the urgency name using ‘bmc-remedy-urgency-details-get’ command.
Optional
status_id status_id is the unique Id of the status that is used to display the progress of the incident through its stages of opening to closure. Users can get the status Id from the status name using ‘bmc-remedy-status-details-get’ command. Optional
staff_id staff_id is the unique Id of the staff to whom the user wants to assign the record.
Users can get the staff Id from the staff details using ‘bmc-remedy-user-details-get’ command.
Optional
additional_fields The fields which are not present in the current argument list can be added here in the format “fieldname1=value;fieldname2=value”.
Possible fields: broadcast_id, service_id,impact_id, service_offering_id, asset_id, outage_start, outage_end, account_id or any other custom field.
Optional

Context Output

Path Type Description
BmcRemedyforce.Incident.Id String Incident Id.
BmcRemedyforce.Incident.Number String Incident number.
BmcRemedyforce.Incident.CreatedDate String Creation date & time of Incident.

Command Example

!bmc-remedy-incident-create client_id=0052w000004Z9vJAAS status_id=a3w2w000000TfGlAAK category_id=a212w000000UFfyAAG

Context Example

{
    "BmcRemedyforce": {
        "Incident": {
            "CreatedDate": "2020-08-01 12:06:08",
            "Id": "a2U2w000000YTEmEAO",
            "Number": "00012193"
        }
    }
}

Human Readable Output

The incident 00012193 is successfully created.

bmc-remedy-incident-update


This command updates the details of an incident for a given incident number.

Base Command

bmc-remedy-incident-update

Input

Argument Name Description Required
incident_number The unique number of the incident whose details need to be updated. Required
category_id category_id is the unique Id of the category. Categories allow users to classify the incident or service request using standard classifications to track the reporting purposes.
Users can get the category Id from the category name using ‘bmc-remedy-category-details-get’ command.
Optional
queue_id queue_id is the unique Id of the owner.
Users can get the queue Id from the owner name using ‘bmc-remedy-queue-details-get’ command.
Optional
staff_id staff_id is the unique Id of the staff to whom the user wants to assign the record.
Users can get the staff Id from the staff details using ‘bmc-remedy-user-details-get’ command.
Optional
status_id status_id is the unique Id of the status that is used to display the progress of the incident through its stages of opening to closure.
Users can get the status Id from the status name using ‘bmc-remedy-status-details-get’ command.
Optional
urgency_id urgency_id is the unique Id of the urgency which is used to determine the priority of the incident.
Users can get the urgency Id from the urgency name using ‘bmc-remedy-urgency-details-get’ command.
Optional
due_date due_date is the date and time until which the incident should be completed. Use the yyyy-MM-ddTHH:mm:ss.SSS+/-HHmm or yyyy-MM-ddTHH:mm:ss.SSSZ formats to specify dateTime fields. Optional
client_id client_id is the unique Id of the client. It helps to select the client for a particular incident.
Users can get the client Id from the email using ‘bmc-remedy-user-details-get’ command.
Optional
additional_fields The fields which are not present in the current argument list can be added here in the format “fieldname1=value;fieldname2=value”.
Possible fields: broadcast_id, service_id,impact_id, service_offering_id, asset_id, outage_start, outage_end, account_id or any other custom field.
Optional

Context Output

Path Type Description
BmcRemedyforce.Incident.Id String Incident Id.
BmcRemedyforce.Incident.Number String Incident number.
BmcRemedyforce.Incident.LastUpdatedDate String Last updated date & time of Incident.

Command Example

!bmc-remedy-incident-update incident_number=IN00000182 status_id=a3w2w000000TfGlAAK category_id=a212w000000UFfyAAG aditional_fields="impact_id=HIGH;asset_id=a0K2w000000wi2uEAA" using=BMCHelixRemedyforce_instance_1

Context Example

{
    "BmcRemedyforce": {
        "Incident": {
            "Id": "a2U2w000000YGaHEAW",
            "LastUpdatedDate": "2020-08-01T12:05:37Z",
            "Number": "00000182"
        }
    }
}

Human Readable Output

The incident 00000182 is successfully updated.

bmc-remedy-asset-details-get


This command helps to get asset or configuration item details for incidents.

Base Command

bmc-remedy-asset-details-get

Input

Argument Name Description Required
asset_name asset_name is the name of the asset for which the command will find the metadata. Optional
instance_type Assets belonging to the selected instance_type will be populated. Optional

Context Output

Path Type Description
BmcRemedyforce.Asset.Id String Asset Id.
BmcRemedyforce.Asset.Name String Asset name.
BmcRemedyforce.Asset.Description String Asset description.
BmcRemedyforce.Asset.Class_Name String Asset under BMC class type.
BmcRemedyforce.Asset.Asset_Number String Asset number.
BmcRemedyforce.Asset.Instance_Type String Assets belonging to selected class.

Command Example

!bmc-remedy-asset-details-get asset_name=BlackBerry-Houston01

Context Example

{
    "BmcRemedyforce": {
        "Asset": {
            "Asset_Number": "1102942",
            "Class_Name": "BMC_ComputerSystem",
            "Description": "Houston BlackBerry Server",
            "Id": "a0K2w000000wi1bEAA",
            "Instance_Type": "CI / Asset",
            "Name": "BlackBerry-Houston01"
        }
    }
}

Human Readable Output

Total retrieved asset(s): 1

Id Name Description Asset # Class Name Instance Type
a0K2w000000wi1bEAA BlackBerry-Houston01 Houston BlackBerry Server 1102942 BMC_ComputerSystem CI / Asset

bmc-remedy-account-details-get


This command helps to get account details for incidents and service requests.

Base Command

bmc-remedy-account-details-get

Input

Argument Name Description Required
account_name account_name is the account name of the account whose details the user wants to get. If any value is not specified, it gets details of all the available accounts. Optional

Context Output

Path Type Description
BmcRemedyforce.Account.Id String Account Id.
BmcRemedyforce.Account.Name String Account name.

Command Example

!bmc-remedy-account-details-get account_name="test_account"

Context Example

{
    "BmcRemedyforce": {
        "Account": {
            "Id": "0012w00000GMthNAAT",
            "Name": "test_account"
        }
    }
}

Human Readable Output

Total retrieved account(s): 1

Id Name
0012w00000GMthNAAT test_account

bmc-remedy-status-details-get


This command helps to get status details for incidents and service requests. Status is used to display the progress of the service request or incident through its stages of opening to closure.

Base Command

bmc-remedy-status-details-get

Input

Argument Name Description Required
status_name status_name is the status name whose details the user wants to get. Optional

Context Output

Path Type Description
BmcRemedyforce.Status.Id String Status Id.
BmcRemedyforce.Status.Name String Status name.

Command Example

!bmc-remedy-status-details-get status_name="OPENED"

Context Example

{
    "BmcRemedyforce": {
        "Status": {
            "Id": "a3w2w000000TfGBAA0",
            "Name": "OPENED"
        }
    }
}

Human Readable Output

Total retrieved status: 1

Id Name
a3w2w000000TfGBAA0 OPENED

bmc-remedy-urgency-details-get


This command helps to get urgency details for incidents and service requests. Urgency is used to determine the priority of the incident or service request.

Base Command

bmc-remedy-urgency-details-get

Input

Argument Name Description Required
urgency_name urgency_name is the name of the urgency whose details the user wants to get. Optional

Context Output

Path Type Description
BmcRemedyforce.Urgency.Id String Urgency Id.
BmcRemedyforce.Urgency.Name String Urgency name.

Command Example

!bmc-remedy-urgency-details-get urgency_name="LOW"

Context Example

{
    "BmcRemedyforce": {
        "Urgency": {
            "Id": "a472w000000Tyk6AAC",
            "Name": "LOW"
        }
    }
}

Human Readable Output

Total retrieved urgencies: 1

Id Name
a472w000000Tyk6AAC LOW

bmc-remedy-category-details-get


This command helps to get category details for incidents and service requests. Categories allow users to classify the incident or service request using standard classifications to track the reporting purposes.

Base Command

bmc-remedy-category-details-get

Input

Argument Name Description Required
type type is the category type whose details the user wants to get. Optional
category_name category_name is the category name whose details the user wants to get. Optional

Context Output

Path Type Description
BmcRemedyforce.Category.Id String Category Id.
BmcRemedyforce.Category.Name String Category name.
BmcRemedyforce.Category.ChildrenCount String Number of children of the category.

Command Example

!bmc-remedy-category-details-get category_name="Email"

Context Example

{
    "BmcRemedyforce": {
        "Category": {
            "ChildrenCount": 0,
            "Id": "a212w000000UFfyAAG",
            "Name": "Email"
        }
    }
}

Human Readable Output

Total retrieved categories: 1

Id Name Children Count
a212w000000UFfyAAG Email 0.0

bmc-remedy-queue-details-get


This command helps to get queue details for incidents and service requests. It accepts queue name and type as arguments.

Base Command

bmc-remedy-queue-details-get

Input

Argument Name Description Required
queue_name queue_name is the name of the queue as the owner whose details the user wants to get. Optional
type type will allow the user to filter with its possible values as incident or service request and get details accordingly. Optional

Context Output

Path Type Description
BmcRemedyforce.Queue.Id String Queue Id.
BmcRemedyforce.Queue.Name String Queue name.
BmcRemedyforce.Queue.Email String Queue email.

Command Example

!bmc-remedy-queue-details-get queue_name="Application Development"

Context Example

{
    "BmcRemedyforce": {
        "Queue": {
            "Email": "testuser@bmcremedyforce.com",
            "Id": "00G2w0000027SeUEAU",
            "Name": "Application Development"
        }
    }
}

Human Readable Output

Total retrieved queue(s): 1

Id Name Email
00G2w0000027SeUEAU Application Development testuser@bmcremedyforce.com

bmc-remedy-user-details-get


This command helps to get user details for incidents and service requests. It accepts username, account name, email, queue name, and is_staff as arguments.

Base Command

bmc-remedy-user-details-get

Input

Argument Name Description Required
username username is the name of the user whose details the user wants to get. Optional
account_name account_name is the account name of the user whose details the user wants to get. Optional
email email is the email address of the user whose details the user wants to get. Optional
queue_name queue_name is the group/queue name for which user wants to get user details. Optional
is_staff is_staff will allow the user to filter with its possible values true or false and get details of users accordingly. Optional

Context Output

Path Type Description
BmcRemedyforce.User.Id String User Id which uniquely identifies the user.
BmcRemedyforce.User.Name String Full name of the user.
BmcRemedyforce.User.FirstName String First name of the user.
BmcRemedyforce.User.LastName String Last name of the user.
BmcRemedyforce.User.Username String Username of the user.
BmcRemedyforce.User.Email String Email of the user.
BmcRemedyforce.User.Phone String Phone number of the user.
BmcRemedyforce.User.Account String Account name of the user.
BmcRemedyforce.User.CompanyName String Company name of the user.
BmcRemedyforce.User.Division String Division of the user.
BmcRemedyforce.User.Department String Department name of the user.
BmcRemedyforce.User.Title String Title of the user.
BmcRemedyforce.User.IsStaff Boolean Shows whether the user belongs to the staff or not.

Command Example

!bmc-remedy-user-details-get queue_name="BMC Client Management"

Context Example

{
    "BmcRemedyforce": {
        "User": [
            {
                "CompanyName": "Company",
                "Email": "bmcremedyforce@example.com",
                "FirstName": "user1",
                "Id": "0052w000004nsLdAAI",
                "IsStaff": true,
                "LastName": "test",
                "Name": "user1 test",
                "Username": "testuser1@bmcremedyforce.com"
            },
            {
                "CompanyName": "Company",
                "Email": "bmcremedyforce@example.com",
                "FirstName": "user2",
                "Id": "0052w000004nsLaAAI",
                "IsStaff": true,
                "LastName": "test",
                "Name": "user2 test",
                "Username": "testuser2@bmcremedyforce.com"
            }
        ]
    }
}

Human Readable Output

Total retrieved user(s): 2

Id Username First Name Last Name Email Company Name Is Staff
0052w000004nsLdAAI testuser1@bmcremedyforce.com user1 test bmcremedy@example.com Company true
0052w000004nsLaAAI testuser2@bmcremedyforce.com user2 test bmcremedy@example.com Company true

bmc-remedy-broadcast-details-get


This command helps to get broadcast details for incidents. Broadcast enables users to send messages to the entire organization, selected groups within the organization and to external customers.

Base Command

bmc-remedy-broadcast-details-get

Input

Argument Name Description Required
broadcast_name broadcast_name is the name of the broadcast whose details the user wants to get. Optional
category_name category_name is the name of the category whose details the user wants to get. Optional

Context Output

Path Type Description
BmcRemedyforce.Broadcast.Id String Broadcast Id.
BmcRemedyforce.Broadcast.Name String Broadcast name.
BmcRemedyforce.Broadcast.Description String Broadcast description.
BmcRemedyforce.Broadcast.Category String Broadcast category.
BmcRemedyforce.Broadcast.Status String Broadcast status.
BmcRemedyforce.Broadcast.Priority String Broadcast priority.
BmcRemedyforce.Broadcast.Urgency String Broadcast urgency.
BmcRemedyforce.Broadcast.Impact String Broadcast impact.

Command Example

!bmc-remedy-broadcast-details-get broadcast_name="BES Server is down completely"

Context Example

{
    "BmcRemedyforce": {
        "Broadcast": {
            "Category": "Telecommunication",
            "Id": "a1v2w000000IaP7AAK",
            "Impact": "HIGH",
            "Name": "BES Server is down completely",
            "Priority": "1",
            "Status": "OPENED",
            "Urgency": "HIGH"
        }
    }
}

Human Readable Output

Total retrieved broadcast(s): 1

Id Name Priority Urgency Impact Category Status
a1v2w000000IaP7AAK BES Server is down completely 1 HIGH HIGH Telecommunication OPENED

bmc-remedy-incident-get


This command helps to get details of incidents.

Base Command

bmc-remedy-incident-get

Input

Argument Name Description Required
last_fetch_time The time range to consider for getting the incident. Use the format “<number> <time unit>”. Example: 12 hours, 7 days, 3 months, 1 year. Optional
incident_number The unique number of the incident whose details user wants to get. Optional
maximum_incident The maximum number of the incidents user wants to get. Optional

Context Output

Path Type Description
BmcRemedyforce.Incident.Id String Incident Id.
BmcRemedyforce.Incident.Number String Incident number.
BmcRemedyforce.Incident.Priority String Incident priority.
BmcRemedyforce.Incident.Description String Incident description.
BmcRemedyforce.Incident.ClientID String Incident client Id.
BmcRemedyforce.Incident.Status String Incident status.
BmcRemedyforce.Incident.dueDateTime String Incident due datetime.
BmcRemedyforce.Incident.Staff String Incident staff.
BmcRemedyforce.Incident.Queue String Incident queue.
BmcRemedyforce.Incident.Category String Incident category.
BmcRemedyforce.Incident.Urgency String Incident urgency.
BmcRemedyforce.Incident.ClientAccount String Incident client account.
BmcRemedyforce.Incident.Broadcast String Incident broadcast.
BmcRemedyforce.Incident.closeDateTime String Incident close datetime.
BmcRemedyforce.Incident.CreatedDate String Incident created date.
BmcRemedyforce.Incident.LastModifiedDate String Incident last modified date.
BmcRemedyforce.Incident.openDateTime String Incident open datetime.
BmcRemedyforce.Incident.outageTo String Incident outage end.
BmcRemedyforce.Incident.outageFrom String Incident outage start.
BmcRemedyforce.Incident.Resolution String Incident resolution.
BmcRemedyforce.Incident.respondedDateTime String Incident responded datetime.
BmcRemedyforce.Incident.Service String Incident service.
BmcRemedyforce.Incident.ServiceOffering String Incident service offering.
BmcRemedyforce.Incident.Template String Incident template.
BmcRemedyforce.Incident.Type String Incident type.
BmcRemedyforce.Incident.Impact String Incident impact.
BmcRemedyforce.Incident.Asset String Incident asset.

Command Example

!bmc-remedy-incident-get last_fetch_time="1 hours" maximum_incident=2

Context Example

{
    "BmcRemedyforce": {
        "Incident": {
            "Category": "Human Resources",
            "ClientID": "Clinet ID",
            "CreatedDate": "2020-08-14T12:47:58.000+0000",
            "Id": "a2U2w00000096QEEAY",
            "Impact": "LOW",
            "LastModifiedDate": "2020-08-14T15:18:07.000+0000",
            "Number": "00000059",
            "Priority": "5",
            "Service": "Client Services",
            "Staff": "Staff Name",
            "Status": "OPENED",
            "Template": "Benefits Question - SR",
            "Type": "Incident",
            "Urgency": "LOW",
            "dueDateTime": "2020-08-17T20:47:58.000+0000",
            "openDateTime": "2020-08-14T12:47:58.000+0000"
        }
    }
}

Human Readable Output

Total retrieved incident(s): 1

Number Priority Client ID Status Staff
00000059 5 Client ID OPENED Staff Name

bmc-remedy-service-request-get


This command helps to get the service request details.

Base Command

bmc-remedy-service-request-get

Input

Argument Name Description Required
service_request_number The unique number of the service request whose details user wants to get. Optional
last_fetch_time The time range to consider for getting the service request. Use the format “<number> <time unit>”. Example: 12 hours, 7 days, 3 months, 1 year. Optional
maximum_service_request The maximum number of the service request user wants to get. Optional

Context Output

Path Type Description
BmcRemedyforce.ServiceRequest.Id String Service Request Id.
BmcRemedyforce.ServiceRequest.Number String Service Request number.
BmcRemedyforce.ServiceRequest.Priority String Service Request priority.
BmcRemedyforce.ServiceRequest.Description String Service Request description.
BmcRemedyforce.ServiceRequest.ClientID String Service Request client.
BmcRemedyforce.ServiceRequest.Status String Service Request status.
BmcRemedyforce.ServiceRequest.DueDateTime String Service Request due datetime.
BmcRemedyforce.ServiceRequest.Staff String Service Request staff.
BmcRemedyforce.ServiceRequest.Queue String Service Request queue.
BmcRemedyforce.ServiceRequest.Category String Service Request category.
BmcRemedyforce.ServiceRequest.Urgency String Service Request urgency.
BmcRemedyforce.ServiceRequest.Broadcast String Service Request broadcast.
BmcRemedyforce.ServiceRequest.closeDateTime String Service Request close datetime.
BmcRemedyforce.ServiceRequest.CreatedDate String Service Request created date.
BmcRemedyforce.ServiceRequest.LastUpdatedDate String Service Request last modified date.
BmcRemedyforce.ServiceRequest.OpenDateTime String Service Request open datetime.
BmcRemedyforce.ServiceRequest.Resolution String Service Request resolution.
BmcRemedyforce.ServiceRequest.ServiceOffering String Service Request service offering.
BmcRemedyforce.ServiceRequest.Template String Service Request template.
BmcRemedyforce.ServiceRequest.Impact String Service Request impact.
BmcRemedyforce.ServiceRequest.BusinessService String Service Request business service.
BmcRemedyforce.ServiceRequest.ServiceRequestDefinition String Service Request definition.
BmcRemedyforce.ServiceRequest.ClientAccount String Account held by service request.
BmcRemedyforce.ServiceRequest.Type String Service Desk Type.

Command Example

!bmc-remedy-service-request-get last_fetch_time="1 hours" maximum_service_request=2

Context Example

{
    "BmcRemedyforce": {
        "ServiceRequest": {
            "BusinessService": "Printing Services",
            "Category": "File & Print",
            "CreatedDate": "2020-08-14T13:32:17.000+0000",
            "DueDateTime": "2020-08-17T21:32:16.000+0000",
            "Id": "a2U2w00000096yCEAQ",
            "Impact": "LOW",
            "LastUpdatedDate": "2020-08-14T14:28:12.000+0000",
            "Number": "00000929",
            "OpenDateTime": "2020-08-14T13:32:16.000+0000",
            "Priority": "5",
            "Queue": "Incident Queue",
            "ServiceOffering": "Printer Configuration",
            "ServiceRequestDefinition": "Setup Printer",
            "Status": "OPENED",
            "Template": "Printer Setup - SR",
            "Type": "Service Request",
            "Urgency": "LOW"
        }
    }
}

Human Readable Output

Total retrieved service request(s): 1

Number Priority Status Queue
00000929 5 OPENED Incident Queue

Configuration parameters

  • url — BMC Remedyforce URL (e.g. https://example.com) (required)
  • auth_url — BMC Remedyforce Login URL
  • username — Username
  • password — Password
  • username_creds — Username
  • type — Type
  • category — Category
  • impact — Impact
  • urgency — Urgency
  • status — Status
  • queue — Queue
  • max_fetch — Max Incidents
  • fetch_note — Fetch Note(s)
  • query — Query (If provided other filtering parameters will be ignored) e.g. select Name, LastModifiedDate from BMCServiceDesk__Incident__c where BMCServiceDesk__Impact_Id__c = 'High'
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • request_timeout — HTTP(S) Request Timeout (in seconds) (required)
  • isFetch — Fetch incidents
  • first_fetch — First Fetch Timestamp (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year)

Commands (19)

  • bmc-remedy-account-details-get

    Returns account details for incidents and service requests.

  • bmc-remedy-asset-details-get

    Returns asset or configuration item details for incidents.

  • bmc-remedy-broadcast-details-get

    Returns broadcast details for incidents, which enables users to send messages to the entire organization, selected groups within the organization and to external customers.

  • bmc-remedy-category-details-get

    Returns category details for incidents and service requests. Categories allow users to classify the incident or service request using standard classifications to track the reporting purposes.

  • bmc-remedy-impact-details-get

    Returns the impact details for incidents and service requests. Impact helps calculate the priority of the incident or service request.

  • bmc-remedy-incident-create

    Creates a new incident.

  • bmc-remedy-incident-get

    Returns details of incidents.

  • bmc-remedy-incident-update

    Updates details of an incident for a given incident number.

  • bmc-remedy-note-create

    Creates notes for incidents and service requests.

  • bmc-remedy-queue-details-get

    Returns queue details for incidents and service requests.

  • bmc-remedy-service-offering-details-get

    Returns service offering details for incidents.

  • bmc-remedy-service-request-create

    Creates a new service request, which is the request record generated from the Service Request Definition to manage and track the execution.

  • bmc-remedy-service-request-definition-get

    Returns details of service request definitions using the Service Request Definition name.

  • bmc-remedy-service-request-get

    Returns the service request details.

  • bmc-remedy-service-request-update

    Updates details of a service request for a service request number.

  • bmc-remedy-status-details-get

    Returns status details for incidents and service requests. The status displays the progress of the service request or incident through stages from opening to closure.

  • bmc-remedy-template-details-get

    Returns template details for incidents. Templates enable users to prepopulate commonly used fields in a form.

  • bmc-remedy-urgency-details-get

    Returns urgency details for incidents and service requests. Urgency determines the priority of the incident or service request.

  • bmc-remedy-user-details-get

    Returns user details for incidents and service requests.

import json
import time
import unittest
from datetime import datetime
from unittest.mock import MagicMock, Mock, patch

import dateparser
import pytest
import requests
from BmcHelixRemedyForce import (
    DISPLAY_DATE_FORMAT,
    HR_MESSAGES,
    INCIDENT_CATEGORY_OBJECT,
    MESSAGES,
    OUTPUT_PREFIX,
    POSSIBLE_CATEGORY_TYPES,
    SERVICE_REQUEST_CATEGORY_OBJECT,
    URL_SUFFIX,
    Client,
    DemistoException,
    bmc_remedy_account_details_get_command,
    bmc_remedy_asset_details_get_command,
    bmc_remedy_broadcast_details_get_command,
    bmc_remedy_category_details_get_command,
    bmc_remedy_create_service_request_command,
    bmc_remedy_impact_details_get_command,
    bmc_remedy_service_offering_details_get_command,
    bmc_remedy_service_request_get_command,
    bmc_remedy_template_details_get_command,
    bmc_remedy_update_service_request_command,
    bmc_remedy_urgency_details_get_command,
    date_to_timestamp,
    get_request_params,
    get_service_request_details,
    get_valid_arguments,
    prepare_outputs_for_get_service_request,
    remove_prefix,
    update_incident,
)
from requests import Response
from requests.exceptions import InvalidSchema, MissingSchema

INCIDENT_TEST_DATA_FILE = "./TestData/incident_data.json"


def prepare_expected_response_for_fetch_incidents():
    """
    Prepares expected incidents list from response.
    :return: raw response, incident list.
    """
    from BmcHelixRemedyForce import prepare_date_or_markdown_fields_for_fetch_incidents, remove_empty_elements

    with open("./TestData/fetch_incident_response.json") as f:
        expected_response = json.load(f)
    incidents = expected_response["records"][0]
    prepare_date_or_markdown_fields_for_fetch_incidents(incidents)
    incidents["Bmc Severity"] = 4
    # expected incidents.
    expected_incidents = [
        {
            "name": "SR19657",
            "rawJSON": json.dumps(remove_empty_elements(incidents)),
        }
    ]
    return expected_response, expected_incidents


def fetch_dummy_response():
    """To mock requests.response object it is a dummy method."""
    with open("./TestData/service_request.json", encoding="utf-8") as f:
        data = json.load(f)
    return data


def fetch_dummy_get_impacts():
    """To mock requests.response object for fetch impacts command."""
    with open("./TestData/get_impacts.json", encoding="utf-8") as f:
        data = json.load(f)
    return data


def fetch_dummy_categories():
    """To mock requests.response object for fetch categories command."""
    with open("./TestData/get_categories.json", encoding="utf-8") as f:
        data = json.load(f)
    return data


def fetch_dummy_broadcasts():
    """To mock requests.response object for fetch broadcasts command."""
    with open("./TestData/get_broadcasts.json", encoding="utf-8") as f:
        data = json.load(f)
    return data


def get_failure_sr():
    """To mock requests.response object it is a dummy method."""
    return {"Success": False}


def fetch_empty_dummy_response():
    """To mock requests.response object it is a dummy method."""
    return {}


def mock_incident_success_response(method, *args, **kwargs):
    with open(INCIDENT_TEST_DATA_FILE) as f:
        api_response = json.load(f)

    if method == "POST":  # noqa: RET503
        return api_response["create_success"]
    elif method == "PATCH":
        patch_response = Response()
        patch_response.status_code = 204
        return patch_response


def mock_incident_warning_response(method, *args, **kwargs):
    with open(INCIDENT_TEST_DATA_FILE) as f:
        api_response = json.load(f)

    if method == "POST":  # noqa: RET503
        return api_response["create_success"]
    elif method == "PATCH":
        raise DemistoException("SOME_ISSUE_WITH_UPDATE")


def get_no_content_success_response():
    resp = Response()
    resp.status_code = 204
    return resp


class BmcHelixRemedyForceTestCase(unittest.TestCase):
    client = Client(
        base_url="https://sample.api.com",  # Compliant
        verify=False,
        proxy=False,
        username="username",
        password="password",
        request_timeout=60,
    )

    with open("./TestData/update_service_request.json", encoding="utf-8") as f:
        data = json.load(f)
    with open("TestData/get_remedy_command_return_null_result.json", encoding="utf-8") as f:
        expected_return_null_result = json.load(f)
    with open("TestData/dummy_categories.json", encoding="utf-8") as f:
        dummy_categories = json.load(f)
    with open("TestData/dummy_broadcasts.json", encoding="utf-8") as f:
        dummy_broadcasts = json.load(f)
    with open("TestData/get_service_request.json", encoding="utf-8") as f:
        get_service_request_response = json.load(f)
    incorrect_args = data["incorrect_args"]
    correct_args = data["correct_args"]
    valid_session_id = "SOME_VALID_SESSION_ID"
    msg_for_invalid_format = "{}".format(MESSAGES["INVALID_DATA_FORMAT"]).format("additional_fields")
    expected_zero_record = {"totalSize": 0, "done": True, "records": []}

    @patch("demistomock.getIntegrationContext")
    @patch("BmcHelixRemedyForce.Client.get_salesforce_session")
    @patch("demistomock.setIntegrationContext")
    def test_get_session_id_valid_credentials(self, mocker_set_context, mocker_session, mocker_get_context):
        """
        Given no integration context or integration context contains an expired session id
        when credentials are valid
        then a valid session id should be returned and integration context should be set once.

        :param mocker_get_context: mocker object for getting integration context
        :param mocker_session: mocker object for getting salesforce session
        :param mocker_set_context: mocker object for setting integration context
        :return: None
        """
        mocker_get_context.return_value = {}
        mocker_set_context.return_value = {}

        mocked_positive_response = Response()
        mocked_positive_response.status_code = 200
        with open("./TestData/successful_login_response.txt", encoding="utf-8") as f:
            mocked_positive_response._content = f.read()
        mocker_session.return_value = mocked_positive_response

        session_id = self.client.get_session_id()

        assert session_id == self.valid_session_id
        assert mocker_set_context.call_count == 1

    @patch("demistomock.getIntegrationContext")
    @patch("BmcHelixRemedyForce.Client.get_salesforce_session")
    @patch("demistomock.setIntegrationContext")
    def test_get_session_id_invalid_credentials(self, mocker_set_context, mocker_session, mocker_get_context):
        """
        Given no integration context
        when credentials are invalid
        then a demisto exception should be raised and integration context should not be set.

        :param mocker_get_context: mocker object for getting integration context
        :param mocker_session: mocker object for getting salesforce session
        :param mocker_set_context: mocker object for setting integration context
        :return: None
        """
        mocker_get_context.return_value = {}
        mocker_set_context.return_value = {}

        mocked_negative_response = Response()
        mocked_negative_response.status_code = 500
        mocker_session.return_value = mocked_negative_response

        with pytest.raises(DemistoException):
            self.client.get_session_id()

        assert mocker_set_context.call_count == 0

    @patch("demistomock.getIntegrationContext")
    @patch("BmcHelixRemedyForce.Client.get_salesforce_session")
    @patch("demistomock.setIntegrationContext")
    def test_get_session_id_valid_context(self, mocker_set_context, mocker_session, mocker_get_context):
        """
        Given integration context
        when session id in the context is valid
        then a valid session id should be returned, login attempt should not be made and integration
        context should not be set.

        :param mocker_get_context: mocker object for getting integration context
        :param mocker_session: mocker object for getting salesforce session
        :param mocker_set_context: mocker object for setting integration context
        :return: None
        """
        some_future_time = time.time() + 2700

        mocker_get_context.return_value = {"sessionId": self.valid_session_id, "validUntil": some_future_time}
        mocker_set_context.return_value = {}
        mocker_session.return_value = {}

        session_id = self.client.get_session_id()

        assert session_id == self.valid_session_id
        assert mocker_session.call_count == 0
        assert mocker_set_context.call_count == 0

    @patch("CommonServerPython.BaseClient._http_request")
    def test_get_salesforce_session_success(self, mocker_http_request):
        """
        Given working authentication API
        When method for getting salesforce session is called
        Then valid authentication response data should be returned

        :param mocker_http_request:
        :return: None
        """
        mocked_http_response = Response()
        mocked_http_response.status_code = 200
        mocker_http_request.return_value = mocked_http_response

        assert self.client.get_salesforce_session().ok

    @patch("CommonServerPython.BaseClient._http_request")
    def test_get_salesforce_session_failure(self, mocker_http_request):
        """
        Given failing authentication API
        When method for getting salesforce session is called
        Then some exception should be thrown

        :param mocker_http_request:
        :return: None
        """

        mocker_http_request.side_effect = DemistoException("some error!")

        with pytest.raises(DemistoException):
            self.client.get_salesforce_session()

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    def test_http_request_success_response(self, mocker_get_session_id, mocker_http_request):
        """
        Given overridden http request method
        When http response is successful
        Then json response content should be returned

        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """
        mocker_get_session_id.return_value = self.valid_session_id

        dummy_response = {"test": 15}

        mocked_positive_response = Response()
        mocked_positive_response.status_code = 200
        mocked_positive_response._content = json.dumps(dummy_response).encode("utf-8")
        mocker_http_request.return_value = mocked_positive_response

        response = self.client.http_request("GET", "SOME_URL_SUFFIX")

        assert response == dummy_response

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    def test_http_request_success_response_no_content(self, mocker_get_session_id, mocker_http_request):
        """
        Given overridden http request method
        When http response is successful with 204
        Then response should be returned as it is

        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """
        mocker_get_session_id.return_value = self.valid_session_id

        mocked_positive_response = Response()
        mocked_positive_response.status_code = 204
        mocker_http_request.return_value = mocked_positive_response

        response = self.client.http_request("GET", "SOME_URL_SUFFIX")

        assert response == mocked_positive_response

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("demistomock.getIntegrationContext")
    @patch("demistomock.setIntegrationContext")
    def test_http_request_unauthorized_response(
        self, mocker_set_context, mocker_get_context, mocker_get_session_id, mocker_http_request
    ):
        """
        Given the overridden http request method
        When response is unauthorized
        Then integration context should be set and DemistoException should be raised

        :param mocker_set_context: mocker object for setting integration context
        :param mocker_get_context: mocker object for getting integration context
        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """
        mocker_get_session_id.return_value = "SOME_INVALID_SESSION_ID"
        mocker_get_context.return_value = {}
        mocker_set_context.return_value = {}

        mocked_unauthorized_response = Response()
        mocked_unauthorized_response.status_code = 401  # Unauthorized response
        mocker_http_request.return_value = mocked_unauthorized_response

        with pytest.raises(DemistoException):
            self.client.http_request("GET", "SOME_URL_SUFFIX")

        assert mocker_get_context.call_count == 1
        assert mocker_set_context.call_count == 1

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    def test_http_request_missing_schema(self, mocker_get_session_id, mocker_http_request):
        """
        Given overridden http request method
        When there is missing schema error making the http call
        Then DemistoException should be raised with proper error message

        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """
        mocker_get_session_id.return_value = self.valid_session_id
        mocker_http_request.side_effect = MissingSchema("missing schema")

        with pytest.raises(DemistoException) as e:
            self.client.http_request("GET", "SOME_URL_SUFFIX", headers={"test": "test2"})

        assert str(e.value) == MESSAGES["MISSING_SCHEMA_ERROR"]

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    def test_http_request_invalid_schema(self, mocker_get_session_id, mocker_http_request):
        """
        Given overridden http request method
        When there is invalid schema error making the http call
        Then DemistoException should be raised with proper error message

        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """
        mocker_get_session_id.return_value = self.valid_session_id
        mocker_http_request.side_effect = InvalidSchema("invalid schema")

        with pytest.raises(DemistoException) as e:
            self.client.http_request("GET", "SOME_URL_SUFFIX")

        assert str(e.value) == MESSAGES["INVALID_SCHEMA_ERROR"]

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    def test_http_request_proxy_error(self, mocker_get_session_id, mocker_http_request):
        """
        Given overridden http request method
        When there is proxy error while making the http call
        Then ConnectionError should be raised with proper error message

        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """
        mocker_get_session_id.return_value = self.valid_session_id
        mocker_http_request.side_effect = DemistoException("Proxy Error")

        with pytest.raises(ConnectionError) as e:
            self.client.http_request("GET", "SOME_URL_SUFFIX")

        assert str(e.value) == MESSAGES["PROXY_ERROR"]

    @patch("CommonServerPython.handle_proxy")
    def test_http_request_proxy_blank_error(self, handle_proxy):
        """
        Given proxy=true
        When there is proxy set to blank in configuration
        Then Value Error should be raised with proper error message

        :param handle_proxy: mock of handle proxy method.
        :return: None
        """
        handle_proxy.return_value = {}
        with pytest.raises(ValueError) as e:
            Client(
                base_url="https://sample.api.com",  # Compliant
                verify=False,
                proxy=True,
                username="username",
                password="password",
                request_timeout=60,
            )
        assert str(e.value) == MESSAGES["PROXY_ERROR"]

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    def test_http_request_connection_error(self, mocker_get_session_id, mocker_http_request):
        """
        Given overridden http request method
        When there is 'ConnectionError'  or 'ConnectTimeout' error while making the http call
        Then ConnectionError should be raised with proper error message

        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """
        mocker_get_session_id.return_value = self.valid_session_id
        mocker_http_request.side_effect = DemistoException("ConnectionError or ConnectTimeout")

        with pytest.raises(ConnectionError) as e:
            self.client.http_request("GET", "SOME_URL_SUFFIX")

        assert str(e.value) == MESSAGES["CONNECTION_ERROR"]

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    def test_http_request_other_demisto_exception(self, mocker_get_session_id, mocker_http_request):
        """
        Given overridden http request method
        When there some error while making the http call
        Then DemistoException should be raised with proper error message

        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """
        mocker_get_session_id.return_value = self.valid_session_id
        mocker_http_request.side_effect = DemistoException("Some other error!")

        with pytest.raises(DemistoException) as e:
            self.client.http_request("GET", "SOME_URL_SUFFIX")

        assert str(e.value) == "Some other error!"

    @patch("CommonServerPython.BaseClient._http_request")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    def test_http_request_bad_request(self, mocker_get_session_id, mocker_http_request):
        """
        Given overridden http request method
        When there bad request response while making the http call
        Then DemistoException should be raised with proper error message from the http response

        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_http_request: mocker object for making http request call
        :return: None
        """

        response_data = [{"message": "custom bad request error message"}]

        mocker_get_session_id.return_value = self.valid_session_id
        mocked_http_response = Response()
        mocked_http_response.status_code = 400
        mocked_http_response._content = json.dumps(response_data).encode("utf-8")
        mocker_http_request.return_value = mocked_http_response

        with pytest.raises(DemistoException) as e:
            self.client.http_request("GET", "SOME_URL_SUFFIX")

        assert "custom bad request error message" in str(e.value)

    @patch("demistomock.params")
    def test_get_request_timeout_valid(self, mocker_params):
        """
        Given working integration configuration parameters
        When parameter value of request_timeout is valid
        Then valid request_timeout value should be returned

        :return: None
        """
        mocker_params.return_value = {"request_timeout": 25}

        from BmcHelixRemedyForce import get_request_timeout

        assert get_request_timeout() == 25

    @patch("demistomock.params")
    def test_get_request_timeout_invalid(self, mocker_params):
        """
        Given working integration configuration parameters
        When parameter value of request_timeout is invalid
        Then ValueError should be raised

        :return: None
        """
        mocker_params.return_value = {"request_timeout": "25asd"}

        from BmcHelixRemedyForce import get_request_timeout

        with pytest.raises(ValueError):
            assert get_request_timeout()

    @patch("demistomock.params")
    def test_get_request_timeout_negative(self, mocker_params):
        """
        Given working integration configuration parameters
        When parameter value of request_timeout is negative
        Then ValueError should be raised

        :return: None
        """
        mocker_params.return_value = {"request_timeout": -25}

        from BmcHelixRemedyForce import get_request_timeout

        with pytest.raises(ValueError):
            assert get_request_timeout()

    @patch("demistomock.params")
    def test_get_request_timeout_exceeding(self, mocker_params):
        """
        Given working integration configuration parameters
        When parameter value of request_timeout exceeds maximum allowed limit
        Then ValueError should be raised

        :return: None
        """
        mocker_params.return_value = {"request_timeout": 92233720361}

        from BmcHelixRemedyForce import get_request_timeout

        with pytest.raises(ValueError):
            assert get_request_timeout()

    @patch("BmcHelixRemedyForce.get_service_request_details")
    @patch("demistomock.command")
    @patch("BmcHelixRemedyForce.Client.http_request")
    @patch("BmcHelixRemedyForce.return_results")
    @patch("demistomock.params")
    def test_main_success(self, mocker_params, mocker_return_results, mocker_http_request, mocker_command, mocker_sr_results):
        """
        Given working service integration
        When test-module is called from main()
        Then return_results should be called with 'ok'

        :param mocker_params: mocker object for params
        :param mocker_return_results: mocker object for CommonServerPython.return_results
        :param mocker_http_request: mocker object for Client.http_request
        :param mocker_command: mocker object for demistomock.command
        :return: None
        """

        mocker_sr_results.return_value = {}
        mocker_http_request.return_value = None
        mocker_return_results.return_value = None

        mocker_command.return_value = "test-module"

        mocker_params.return_value = {"request_timeout": 50, "credentials": {}, "url": "some_base_url", "first_fetch": "10 hours"}

        from BmcHelixRemedyForce import main

        main()

        mocker_return_results.assert_called_with("ok")

    @patch("demistomock.error")
    @patch("demistomock.command")
    @patch("BmcHelixRemedyForce.Client.http_request")
    @patch("BmcHelixRemedyForce.return_error")
    @patch("demistomock.params")
    def test_main_failure(self, mocker_params, mocker_return_error, mocker_http_request, mocker_command, mocker_error):
        """
        Given non-working service integration
        When test-module is called from main()
        Then return_error should be called with some error details

        :param mocker_params: mocker object for params
        :param mocker_return_error: mocker object for return_error method
        :param mocker_http_request: mocker object for Client.http_request
        :param mocker_command: mocker object for demistomock.command
        :param mocker_error: mocker object for demistomock.error
        :return: None
        """

        mocker_http_request.side_effect = DemistoException("Some error!")
        mocker_return_error.return_value = None

        mocker_command.return_value = "test-module"

        mocker_params.return_value = {"request_timeout": 50, "credentials": {}, "url": "some_base_url"}

        from BmcHelixRemedyForce import main

        main()

        assert mocker_error.called
        assert mocker_return_error.called

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_service_request_definition_get_command_success(self, mocker_http_request):
        """
        Given working service integration
        When bmc_remedy_service_request_definition_get command is called
        Then expected row response should be processed and context data should be set with the same number of items in
            the results field of the response

        :param mocker_http_request: Mocker object for http request call
        :return: None
        """
        import BmcHelixRemedyForce

        BmcHelixRemedyForce.process_single_service_request_definition = MagicMock(
            side_effect=BmcHelixRemedyForce.process_single_service_request_definition
        )
        BmcHelixRemedyForce.process_single_service_request_definition_output = MagicMock(
            side_effect=BmcHelixRemedyForce.process_single_service_request_definition_output
        )
        success_resp = {"Success": True, "Result": [{}, {}]}
        mocker_http_request.return_value = success_resp

        command_resp = BmcHelixRemedyForce.bmc_remedy_service_request_definition_get_command(self.client, {})

        assert command_resp.raw_response == success_resp
        assert len(command_resp.outputs) == 2
        assert BmcHelixRemedyForce.process_single_service_request_definition.call_count == 2
        assert BmcHelixRemedyForce.process_single_service_request_definition_output.call_count == 2

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_service_request_definition_get_command_failure(self, mocker_http_request):
        """
        Given non-working service integration
        When bmc_remedy_service_request_definition_get command is called
        Then Demisto exception should be thrown

        :param mocker_http_request: Mocker object for http request call
        :return: None
        """
        failure_resp = {"Success": False}
        mocker_http_request.return_value = failure_resp
        from BmcHelixRemedyForce import bmc_remedy_service_request_definition_get_command

        with pytest.raises(DemistoException) as e:
            bmc_remedy_service_request_definition_get_command(self.client, {})

        assert MESSAGES["FAILED_MESSAGE"].format("get", "service request definition") == str(e.value)

    def test_prepare_output_for_get_service_request_definitions(self):
        """
        Given single service request definition data
        When prepare_output_for_get_service_request_definitions is called
        Then processed json object should be returned in the expected form

        :return: None
        """
        with open("./TestData/service_request_definition.json", encoding="utf-8") as f:
            data = json.load(f)

        from BmcHelixRemedyForce import prepare_hr_output_for_get_service_request_definitions

        output = prepare_hr_output_for_get_service_request_definitions(data["input_data"])
        assert output == data["expected_output"]

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_service_request_def_id_from_name_success(self, mocker_http_request):
        """
        Given working service integration
        When service request id is requested from name
        Then valid name should be returned

        :param mocker_http_request: Mocker object for http request call
        :return: None
        """
        success_resp = {"records": [{"Id": "ID_FOR_GIVEN_NAME"}]}
        mocker_http_request.return_value = success_resp

        from BmcHelixRemedyForce import get_service_request_def_id_from_name

        assert get_service_request_def_id_from_name("GIVEN_NAME", self.client) == "ID_FOR_GIVEN_NAME"

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_service_request_def_id_from_name_failure(self, mocker_http_request):
        """
        Given working service integration
        When service request id is requested from name is not found
        Then DemistoException should be raised with proper message

        :param mocker_http_request: Mocker object for http request call
        :return: None
        """
        mocker_http_request.side_effect = DemistoException("ERROR_MSG")

        from BmcHelixRemedyForce import get_service_request_def_id_from_name

        with pytest.raises(DemistoException) as e:
            get_service_request_def_id_from_name("GIVEN_NAME", self.client)

        assert "ERROR_MSG" in str(e.value)

    def test_validate_max_incidents(self):
        """
        Tests the validation of max_incidents parameter.
        """
        from BmcHelixRemedyForce import validate_max_incidents

        # When non integer.
        with pytest.raises(ValueError):
            validate_max_incidents("test")

        # When blank.
        with pytest.raises(ValueError):
            validate_max_incidents("")

        # When valid integer
        validate_max_incidents("10")

        # When invalid integer
        with pytest.raises(ValueError):
            validate_max_incidents("-1")

    def test_prepare_query_for_fetch_incidents(self):
        """
        Tests the various scenarios related to preparing query based on provided parameters.
        """
        from BmcHelixRemedyForce import SALESFORCE_QUERIES, prepare_query_for_fetch_incidents, timestamp_to_datestring

        # Without query
        params = {"category": "category", "impact": "impact", "max_fetch": "10", "type": "Incident"}
        fields = "BMCServiceDesk__Category_ID__c='category' and BMCServiceDesk__Impact_Id__c='impact' and "
        start_time = 1594250101000
        fetch_type = ("true", "Yes")
        assert prepare_query_for_fetch_incidents(params, start_time) == SALESFORCE_QUERIES["FETCH_INCIDENT_QUERY"].format(
            fields, *fetch_type, timestamp_to_datestring(start_time), "10"
        )

        del params["type"]
        with pytest.raises(ValueError):
            prepare_query_for_fetch_incidents(params, start_time)

        # With query

        # Multiple 'where' clause
        params = {"query": "select Id from table where Id=(select Id from table1 where Id=1)"}
        with pytest.raises(ValueError):
            prepare_query_for_fetch_incidents(params, start_time)

        # No 'where' clause
        params["query"] = "select id from table order by id"
        expected_query = "select id from table where LastModifiedDate > 2020-07-08T23:15:01.000Z order by id"
        assert prepare_query_for_fetch_incidents(params, start_time) == expected_query

        params["query"] = "select id from table"
        expected_query = "select id from table where LastModifiedDate > 2020-07-08T23:15:01.000Z"
        assert prepare_query_for_fetch_incidents(params, start_time) == expected_query

        # No from found
        with pytest.raises(ValueError):
            params["query"] = "select id table"
            prepare_query_for_fetch_incidents(params, start_time)

        # With Single 'where' clause
        params["query"] = "select id from table where id=1"
        expected_query = f"select id from table where LastModifiedDate > {timestamp_to_datestring(start_time)} and id=1"
        assert prepare_query_for_fetch_incidents(params, start_time) == expected_query

    @patch("BmcHelixRemedyForce.get_service_request_details")
    @patch("BmcHelixRemedyForce.get_attachments_for_incident")
    @patch("demistomock.params")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_fetch_incidents(self, http_request, demisto_params_url, mocker_get_attachments, mocker_sr_details):
        """
        Tests the fetch-incidents command.

        :param http_request: mocker object.
        :param demisto_params_url: mocker object for demisto.params()
        :param mocker_get_attachments: mocker object for get_attachments_for_incident()
        """
        from BmcHelixRemedyForce import fetch_incidents

        mocker_sr_details.return_value = {}
        expected_response, expected_incidents = prepare_expected_response_for_fetch_incidents()

        params = {"category": "category", "impact": "impact", "max_fetch": 10, "type": "Incident"}

        # Mocking http_request
        http_request.return_value = expected_response

        # Mocking demiso.params:
        demisto_params_url.return_value = {"url": "SOME_URL"}

        mocker_get_attachments.return_value = []

        # With first_fetch
        next_run, incidents = fetch_incidents(client=self.client, params=params, last_run={}, first_fetch=1594250101000)
        assert next_run == {"start_time": 1594250101000}

        assert incidents == expected_incidents

        # With last_run
        next_run, incidents = fetch_incidents(
            client=self.client, params=params, last_run={"start_time": 1582584487}, first_fetch=0
        )
        assert next_run == {
            "start_time": date_to_timestamp(
                json.loads(expected_incidents[0]["rawJSON"])["LastModifiedDate"], date_format="%Y-%m-%dT%H:%M:%S.%f%z"
            )
        }

        assert incidents == expected_incidents

    @patch("BmcHelixRemedyForce.get_service_request_details")
    @patch("BmcHelixRemedyForce.get_attachments_for_incident")
    @patch("demistomock.getLastRun")
    @patch("demistomock.setLastRun")
    @patch("demistomock.incidents")
    @patch("demistomock.command")
    @patch("BmcHelixRemedyForce.Client.http_request")
    @patch("demistomock.params")
    def test_main_fetch_incidents_success(self, *args):
        """
        Given working service integration
        When fetch-incidents is called from main()
        Then demistomock.incidents and demistomock.setLastRun should be called with respected values.

        :param args: Mocker objects.
        :return: None
        """
        from BmcHelixRemedyForce import main

        expected_response, expected_incidents = prepare_expected_response_for_fetch_incidents()
        args[1].return_value = expected_response

        args[2].return_value = "fetch-incidents"

        args[0].return_value = {
            "request_timeout": 50,
            "credentials": {},
            "url": "some_base_url",
            "type": "Incident",
            "first_fetch": "10 hours",
        }
        args[7].return_value = {}
        args[6].return_value = []

        args[5].return_value = {"start_time": 1594250101000}
        main()
        args[4].assert_called_with({"start_time": 1594250101000})
        args[3].assert_called_with(expected_incidents)

    def test_input_data_create_note(self):
        """
        Given notes and summary as input params return should match expected output
        :return:None
        """
        from BmcHelixRemedyForce import input_data_create_note

        summary = "test summery"
        notes = "test note"
        expected_output = {"ActivityLog": [{"Summary": summary, "Notes": notes}]}
        resp = input_data_create_note(summary, notes)
        assert expected_output == resp

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_id_from_incident_number_success(self, mocker_http_request):
        """
        Given input param incident number or service request should return expected id

        :param mocker_http_request: mocker object for Client.http_request
        :return: None
        """
        from BmcHelixRemedyForce import get_id_from_incident_number

        with open("TestData/get_id_from_name.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        mocker_http_request.return_value = expected_res

        resp = get_id_from_incident_number(self.client, "123")

        assert resp == "123456789"

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_id_from_incident_name_failed(self, mocker_http_request):
        """
        Given invalid input param incident number or service request should not  return expected id

        :param mocker_http_request: mocker object for Client.http_request
        :return: None
        """
        from BmcHelixRemedyForce import get_id_from_incident_number

        mocker_http_request.return_value = {}

        with pytest.raises(ValueError) as e:
            get_id_from_incident_number(self.client, "123")

        assert MESSAGES["NOTE_CREATE_FAIL"].format("123") == str(e.value)

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_id_from_incident_number_failed_value_error(self, mocker_http_request):
        """
        Given invalid input param incident or service request number should not  return expected id

        :param mocker_http_request: mocker object for Client.http_request
        :return: None
        """
        from BmcHelixRemedyForce import get_id_from_incident_number

        with open("TestData/get_id_from_name_null_id.json", encoding="utf-8") as f:
            expected_res = json.load(f)
        mocker_http_request.return_value = expected_res

        with pytest.raises(ValueError) as e:
            get_id_from_incident_number(self.client, "123")

        assert MESSAGES["NOT_FOUND_ERROR"] == str(e.value)

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_id_from_incident_number_type_incident(self, mocker_http_request):
        """
        Given working salesforce integration API
        When get_id_from_incident_number called with type
        Then query should contain appropriate where clause for getting either SR or IN only

        :param mocker_http_request: mocker object for Client.http_request
        :return: None
        """
        from BmcHelixRemedyForce import get_id_from_incident_number

        mocker_http_request.return_value = None

        with pytest.raises(Exception):
            get_id_from_incident_number(self.client, "123", "IN")

        for call in mocker_http_request.call_args_list:
            args, kwargs = call
            assert "and BMCServiceDesk__isServiceRequest__c=false" in kwargs["params"]["q"]

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_id_from_incident_number_type_SR(self, mocker_http_request):
        """
        Given working salesforce integration API
        When get_id_from_incident_number called with type
        Then query should contain appropriate where clause for getting either SR or IN only

        :param mocker_http_request: mocker object for Client.http_request
        :return: None
        """
        from BmcHelixRemedyForce import get_id_from_incident_number

        mocker_http_request.return_value = None

        with pytest.raises(Exception):
            get_id_from_incident_number(self.client, "123", "SR")

        for call in mocker_http_request.call_args_list:
            args, kwargs = call
            assert "and BMCServiceDesk__isServiceRequest__c=true" in kwargs["params"]["q"]

    @patch("BmcHelixRemedyForce.Client.http_request")
    @patch("BmcHelixRemedyForce.get_id_from_incident_number")
    def test_remedy_note_create_command_success(self, mocker_id_from_incident_number, mocker_http_request):
        """
        Given valid param command will run successful

        :param mocker_id_from_incident_number: mocker object for getting valid id from name
        :param mocker_http_request: mocker object for Client.http_request
        :return: None
        """
        from BmcHelixRemedyForce import bmc_remedy_note_create_command

        with open("TestData/get_create_note_response.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        mocker_id_from_incident_number.return_value = "a123bcd"
        mocker_http_request.return_value = expected_res
        args = {"request_number": "IN00000123", "summary": "Summary", "notes": "Notes"}
        result = bmc_remedy_note_create_command(self.client, args)
        assert result.raw_response == expected_res
        assert result.readable_output == HR_MESSAGES["NOTE_CREATE_SUCCESS"].format("IN00000123")
        assert result.outputs_key_field == "Id"

    @patch("BmcHelixRemedyForce.Client.http_request")
    @patch("BmcHelixRemedyForce.get_id_from_incident_number")
    def test_remedy_note_create_command_failed_raise_exception_with_message(
        self, mocker_id_from_incident_number, mocker_http_request
    ):
        """
        When command run and DemistoException called
        Then DemistoException should be raised with proper message

        :param mocker_id_from_incident_number: mocker object for getting valid id from name
        :param mocker_http_request: mocker object for Client.http_request
        :return: None
        """
        from BmcHelixRemedyForce import bmc_remedy_note_create_command

        # to cover expected error occurred
        mocker_http_request.side_effect = DemistoException(MESSAGES["UNEXPECTED_ERROR"])
        mocker_id_from_incident_number.return_value = "a123bcd"
        args = {"summary": "Summary", "notes": "Notes"}

        with pytest.raises(ValueError) as e:
            bmc_remedy_note_create_command(self.client, args)

        assert MESSAGES["EMPTY_REQUIRED_ARGUMENT"].format("request_number") == str(e.value)

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_template_details_get_command_success(self, mock_http_res):
        """
        When bmc_remedy_template_details_get command is called
        Then raw response and method called count should be as expected

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        import BmcHelixRemedyForce

        BmcHelixRemedyForce.create_template_output = MagicMock(side_effect=BmcHelixRemedyForce.create_template_output)

        with open("TestData/get_remedy_template_success.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        mock_http_res.return_value = expected_res
        args = {"template_name": "Summary"}
        result = BmcHelixRemedyForce.bmc_remedy_template_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert BmcHelixRemedyForce.create_template_output.call_count == 1

        args = {}
        result = BmcHelixRemedyForce.bmc_remedy_template_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert BmcHelixRemedyForce.create_template_output.call_count == 2

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_template_details_get_command_no_records_found(self, mock_http_res):
        """
        Testcase for bmc_remedy_template_details_get_command method in case of no records founds in get response.

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        expected_res = self.expected_return_null_result
        mock_http_res.return_value = expected_res
        args = {"template_name": "tname1"}

        result = bmc_remedy_template_details_get_command(self.client, args)

        assert result == MESSAGES["INVALID_ENTITY_NAME"].format("template_name", "tname1")

        args = {}
        result = bmc_remedy_template_details_get_command(self.client, args)
        assert result == MESSAGES["NO_ENTITY_FOUND"].format("template(s)")

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_update_incident_positive(self, req_obj, mocker_get_session_id):
        """
        Testcase for positive scenario of update_incident method.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        from requests import Session

        date_format = "%Y-%m-%d"
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 204
        resp1.text = ""
        req_obj.side_effect = [resp1]
        with open("./TestData/update_incident.json", encoding="utf-8") as f:
            data = json.load(f)
        expected_output = data["expected_output"]
        params = data["params"]
        actual_response = update_incident(self.client, "123", params=params)
        for call in Session.request.call_args_list:
            args, kwargs = call
            assert kwargs["json"] == expected_output
        assert actual_response["outputs"]["LastUpdatedDate"][:10] == datetime.now().strftime(date_format)

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_update_incident_exception(self, req_obj, mocker_get_session_id):
        """
        Testcase of update_incident method incase of exception scenarios
        and verfying  last_updated_status of context output in this scenarios.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        mocked_http_response = Response()
        mocked_http_response.status_code = 401
        req_obj.side_effect = [mocked_http_response]
        params = {"category_id": "abc", "broadcast_id": None}
        expected_response = {"outputs": {}, "message": MESSAGES["AUTHENTICATION_ERROR"]}
        actual_response = update_incident(self.client, "123", params=params)
        assert actual_response == expected_response

    def test_get_valid_arguments(self):
        """
        Testcase of get_valid_arguments method incase of invalid formatted argument
        and verifying exception message.
        """
        try:
            params = "category=abc;broadcast=brdcast;description= ;queue="
            data, exculded_fields = get_valid_arguments(params, "field")
        except Exception as e:
            assert str(e) == "{}".format(MESSAGES["INVALID_DATA_FORMAT"]).format("field")

    def test_get_valid_arguments_empty(self):
        """
        Testcase of get_valid_arguments method incase of empty argument.
        """
        data, exculded_fields = get_valid_arguments("", "field")
        assert data == ""
        assert exculded_fields == []

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_update_service_request_command_invalid_sr_number(self, req_obj, mocker_get_session_id):
        """
        Test-case to update service request in case of invalid service request number
        and verifying  exception message.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_empty_dummy_response
        req_obj.side_effect = [resp1]
        try:
            args = {
                "service_request_number": "345",
                "category_id": "sgs",
                "queue_id": None,
                "staff_id": "afs",
                "status_id": None,
                "urgency_id": "",
            }
            bmc_remedy_update_service_request_command(self.client, args)
        except Exception as e:
            assert str(e) == "{}".format(MESSAGES["NOT_FOUND_SERVICE_REQUEST"]).format("345")

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_update_service_request_command_duplication(self, req_obj, mocker_get_session_id):
        """
        Testcase to update service request incase of default arguments are available in
        additional_fields argument and verfying  exception message.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_empty_dummy_response
        req_obj.side_effect = [resp1]
        try:
            args = {
                "service_request_number": "345",
                "category_id": "sgs",
                "queue_id": None,
                "staff_id": "afs",
                "status_id": None,
                "urgency_id": "",
                "additional_fields": "category_id=dfdg",
            }
            bmc_remedy_update_service_request_command(self.client, args)
        except Exception as e:
            assert str(e) == "{}".format(MESSAGES["INVALID_FIELDS_ERROR"]).format("category_id", "additional_fields")

    @patch("BmcHelixRemedyForce.get_valid_arguments")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_update_service_request_command_invalid_additional_data(self, req_obj, mocker_get_session_id, get_mock):
        """
        Testcase to update service request incase of invlaid formatted additional_fields argument
        and verfying  exception message.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        :param get_mock: mocker object for get_valid_arguments method
        """
        get_mock.return_value = (["category_id", "dfdg"], [])
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_empty_dummy_response
        req_obj.side_effect = [resp1]
        try:
            args = self.incorrect_args
            bmc_remedy_update_service_request_command(self.client, args)
        except Exception as e:
            msg = "{}".format(MESSAGES["INVALID_FORMAT_ERROR"]).format("additional_fields", "field_id1=value_1; field_2=value_2")
            assert str(e) == msg

    @patch("BmcHelixRemedyForce.return_results")
    @patch("BmcHelixRemedyForce.update_incident")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_update_service_request(self, req_obj, mocker_get_session_id, mocker_update_incident, mocker_context):
        """
        Testcase to update service request in positive scenarios and verifying context ouput.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_update_incident: mocker object for update_incident method
        :param mocker_context: mocker object of return_results method of CommonServerPython
        """
        mocker_update_incident.return_value = {"outputs": {"key": "value"}}
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_response
        req_obj.side_effect = [resp1]
        args = self.correct_args
        bmc_remedy_update_service_request_command(self.client, args)
        for call in mocker_context.call_args_list:
            args, kwargs = call
            assert args[0].outputs_prefix == OUTPUT_PREFIX["SERVICE_REQUEST"]
            assert args[0].outputs_key_field == "Number"
            assert args[0].outputs["key"] == "value"
            assert args[0].outputs["Number"] == "345"
            assert args[0].readable_output == "{}".format(HR_MESSAGES["SERVICE_REQUEST_UPDATE_SUCCESS"]).format("345")

    @patch("demistomock.error")
    @patch("BmcHelixRemedyForce.return_warning")
    @patch("BmcHelixRemedyForce.get_valid_arguments")
    @patch("BmcHelixRemedyForce.update_incident")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_update_service_request_warning(
        self, req_obj, mocker_get_session_id, mocker_update_incident, get_mock, mocker_return_warning, mocker_error
    ):
        """
        Testcase to update service request in case of warning scenarios and verifying
        context data.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_update_incident: mocker object for update_incident method
        :param get_mock: mocker object for get_valid_arguments method
        :param mocker_return_warning: mocker object of return_warning method of CommonServerPython
        :param mocker_error: mocker object for demistomock.error
        """
        get_mock.return_value = ([], ["broadcast_id"])
        mocker_update_incident.return_value = {"outputs": {"key": "value"}}
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_response
        req_obj.side_effect = [resp1]
        args = self.incorrect_args
        bmc_remedy_update_service_request_command(self.client, args)
        for call in mocker_return_warning.call_args_list:
            args, kwargs = call
            assert kwargs["message"] == "{}".format(MESSAGES["UPDATE_SERVICE_REQUEST_WARNING"]).format(
                "345", "broadcast_id", MESSAGES["UNEXPECTED_ERROR"]
            )
            assert kwargs["exit"] is True
            assert kwargs["ignore_auto_extract"] is True
            assert kwargs["outputs"]["BmcRemedyforce.ServiceRequest(val.Number === obj.Number)"]["Number"] == "345"
            assert kwargs["outputs"]["BmcRemedyforce.ServiceRequest(val.Number === obj.Number)"]["key"] == "value"

    @patch("BmcHelixRemedyForce.return_results")
    @patch("BmcHelixRemedyForce.update_incident")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_update_service_request_failure(self, req_obj, mocker_get_session_id, mocker_update_incident, mocker_context):
        """
        Testcase to update service request in case of failure and verfying exception message.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_update_incident: mocker object for update_incident method
        :param mocker_context: mocker object of return_results method of CommonServerPython
        """
        mocker_update_incident.return_value = {"outputs": {"key": "value"}, "message": "Failure message"}
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_response
        req_obj.side_effect = [resp1]
        try:
            args = self.incorrect_args
            bmc_remedy_update_service_request_command(self.client, args)
        except Exception as e:
            assert str(e) == self.msg_for_invalid_format

    @patch("demistomock.error")
    @patch("BmcHelixRemedyForce.return_results")
    @patch("BmcHelixRemedyForce.update_incident")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_create_service_request(self, req_obj, mocker_get_session_id, mocker_update_incident, mocker_context, mocker_error):
        """
        Testcase to create service request in case of positive scenarios and verifying
        context data.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_update_incident: mocker object for update_incident method
        :param mocker_context: mocker object of return_results method of CommonServerPython
        :param mocker_error: mocker object for demistomock.error
        """
        mocker_update_incident.return_value = {"outputs": {"key": "value"}}
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_response
        req_obj.side_effect = [resp1]
        args = self.correct_args
        args["service_request_definition_id"] = "345"
        mocker_context.return_value = None
        bmc_remedy_create_service_request_command(self.client, args)
        for call in mocker_context.call_args_list:
            args, kwargs = call
            assert args[0].outputs_prefix == OUTPUT_PREFIX["SERVICE_REQUEST"]
            assert args[0].outputs_key_field == "Number"
            assert args[0].outputs["Number"] == "00000132"
            assert args[0].outputs["Id"] == "adfghjkl"
            assert args[0].readable_output == "{}".format(HR_MESSAGES["SERVICE_REQUEST_CREATE_SUCCESS"]).format("00000132")
            assert args[0].raw_response == fetch_dummy_response()

    @patch("BmcHelixRemedyForce.return_results")
    @patch("BmcHelixRemedyForce.update_incident")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_create_service_request_failure(self, req_obj, mocker_get_session_id, mocker_update_incident, mocker_context):
        """
        Testcase to create service request in case of failure and verfying exception message.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_update_incident: mocker object for update_incident method
        :param mocker_context: mocker object of return_results method of CommonServerPython
        """
        mocker_update_incident.return_value = {"outputs": {"key": "value"}}
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = get_failure_sr
        req_obj.side_effect = [resp1]
        args = {"service_request_definition_id": "345"}
        try:
            bmc_remedy_create_service_request_command(self.client, args)
        except Exception as e:
            assert str(e) == MESSAGES["UNEXPECTED_ERROR"]

    @patch("demistomock.error")
    @patch("BmcHelixRemedyForce.return_warning")
    @patch("BmcHelixRemedyForce.return_results")
    @patch("BmcHelixRemedyForce.update_incident")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_create_service_request_fail_to_update(
        self, req_obj, mocker_get_session_id, mocker_update_incident, mocker_context, mocker_return_warning, mocker_error
    ):
        """
        Testcase to update service request in case of warning scenarios and veryfing context data.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_update_incident: mocker object for update_incident method
        :param mocker_context: mocker object of return_results method of CommonServerPython
        :param mocker_return_warning: mocker object of return_warning method of CommonServerPython
        :param mocker_error: mocker object for demistomock.error
        """
        mock_return_value = {"outputs": {"key": "value"}, "message": "Fail to update"}
        mocker_update_incident.return_value = mock_return_value
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_response
        req_obj.side_effect = [resp1]
        args = {"service_request_definition_id": "345", "service_request_definition_params": "abc=xyz", "category_id": "sd"}
        bmc_remedy_create_service_request_command(self.client, args)
        for call in mocker_return_warning.call_args_list:
            args, kwargs = call
            assert kwargs["message"] == "{}".format(MESSAGES["CREATE_SERVICE_REQUEST_WARNING"]).format(
                "00000132", "category_id", mock_return_value["message"]
            )
            assert kwargs["exit"] is True
            assert kwargs["ignore_auto_extract"] is True
            assert kwargs["outputs"][OUTPUT_PREFIX["SERVICE_REQUEST_WARNING"]]["Number"] == "00000132"
            assert kwargs["outputs"][OUTPUT_PREFIX["SERVICE_REQUEST_WARNING"]]["Id"] == "adfghjkl"

    @patch("demistomock.error")
    @patch("BmcHelixRemedyForce.return_results")
    @patch("BmcHelixRemedyForce.update_incident")
    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_create_service_request_invalid_additional_fields(
        self, req_obj, mocker_get_session_id, mocker_update_incident, mocker_context, mocker_error
    ):
        """
        Testcase to update service request in case of invalid value of additional_fields
        argument.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        :param mocker_update_incident: mocker object for update_incident method
        :param mocker_context: mocker object of return_results method of CommonServerPython
        :param mocker_error: mocker object for demistomock.error
        """
        mocker_update_incident.return_value = {"outputs": {"key": "value"}}
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_response
        req_obj.side_effect = [resp1]
        args = {"service_request_definition_id": "345", "additional_fields": "broadcast_id= ;service_id="}
        try:
            bmc_remedy_create_service_request_command(self.client, args)
        except Exception as e:
            assert str(e) == MESSAGES["INVALID_DATA_FORMAT"].format("additional_fields")

    def test_remove_prefix(self):
        """
        Testcase remove_prefix method and verfying that is given prefix removed
        from given string or not.
        """
        field = remove_prefix("sr", "SR45678tyty")
        assert field == "45678tyty"

    def test_get_request_params(self):
        """
        Testcase of get_request_params method.
        """
        data = {"category_id": "abc", "queue_id": "xyz", "client_id": "def"}
        actual_result = get_request_params(data, {})
        assert actual_result == data

    def test_validate_params_for_fetch_incidents(self):
        """
        Tests, validation of parameters of fetch-incidents.

        :param params_mock: parameter mock object.
        """
        from BmcHelixRemedyForce import validate_params_for_fetch_incidents

        params = {
            "isFetch": True,
            "max_fetch": "10",
        }
        # type validation
        with pytest.raises(ValueError):
            validate_params_for_fetch_incidents(params)

        # query validation
        with pytest.raises(ValueError):
            validate_params_for_fetch_incidents({"query": "select * from a where where", "isFetch": True})
        with pytest.raises(ValueError):
            validate_params_for_fetch_incidents({"query": "select * a", "isFetch": True})

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_impact_details_get_command(self, req_obj, mocker_get_session_id):
        """
        Testcase for positive scenario of bmc_remedy_impact_details_get_command method.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_get_impacts
        req_obj.side_effect = [resp1]
        args = {"impact_name": "abc"}
        expected_output = fetch_dummy_get_impacts().get("records")
        actual_response = bmc_remedy_impact_details_get_command(self.client, args)
        assert actual_response.outputs_prefix == OUTPUT_PREFIX["IMPACT"]
        assert actual_response.outputs == expected_output
        assert actual_response.raw_response == expected_output
        assert len(actual_response.outputs) == 2

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_impact_details_get_command_no_records_found(self, mock_http_res):
        """
        Testcase for bmc_remedy_impact_details_get_command method in case of no records founds in get response.

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        expected_res = self.expected_return_null_result

        mock_http_res.return_value = expected_res
        args = {"impact_name": "impact1"}

        result = bmc_remedy_impact_details_get_command(self.client, args)

        assert result == MESSAGES["INVALID_ENTITY_NAME"].format("impact_name", "impact1")

        args = {}
        result = bmc_remedy_impact_details_get_command(self.client, args)
        assert result == MESSAGES["NO_ENTITY_FOUND"].format("impact(s)")

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_service_offering_details_get_command_success(self, mock_http_res):
        """
        Given valid param command will run successful

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        import BmcHelixRemedyForce

        BmcHelixRemedyForce.create_hr_context_output = MagicMock(side_effect=BmcHelixRemedyForce.create_hr_context_output)

        with open("TestData/get_service_offering_details.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        mock_http_res.return_value = expected_res
        args = {"service_offering_name": "name"}
        result = BmcHelixRemedyForce.bmc_remedy_service_offering_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert BmcHelixRemedyForce.create_hr_context_output.call_count == 1

        args = {}
        result = BmcHelixRemedyForce.bmc_remedy_service_offering_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert len(result.outputs) == 2
        assert BmcHelixRemedyForce.create_hr_context_output.call_count == 2

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_service_offering_details_get_command_no_record_found(self, mock_http_res):
        """
        Testcase for bmc_remedy_service_offering_details_get_command method in case of no records founds
        in get response.

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        expected_res = self.expected_return_null_result

        mock_http_res.return_value = expected_res
        args = {"service_offering_name": "sof1"}

        result = bmc_remedy_service_offering_details_get_command(self.client, args)

        assert result == MESSAGES["INVALID_ENTITY_NAME"].format("service_offering_name", "sof1")

        args = {}
        result = bmc_remedy_service_offering_details_get_command(self.client, args)
        assert result == MESSAGES["NO_ENTITY_FOUND"].format("service offering(s)")

    @patch("BmcHelixRemedyForce.return_results")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_incident_create_command_success(self, mocker_http_request, mocker_return_results):
        """
        Given working create and update incident api
        When command to create incident is called
        Then incident should be created and proper context and reatable output should be returned

        :param mocker_http_request: Mocker object for http_request
        :param mocker_return_results: Mocker object for return_results
        :return: None
        """

        with open(INCIDENT_TEST_DATA_FILE) as f:
            api_response = json.load(f)
        success_result = api_response["create_success"]["Result"]
        mocker_return_results.return_value = None
        mocker_http_request.side_effect = mock_incident_success_response

        from BmcHelixRemedyForce import bmc_remedy_incident_create_command

        bmc_remedy_incident_create_command(self.client, {"client_id": "SOME_CLIENT_ID", "description": "SOME_DESC"})

        assert mocker_return_results.call_count == 1

        for call in mocker_return_results.call_args_list:
            args, kwargs = call
            assert args[0].outputs == success_result
            assert args[0].raw_response == api_response["create_success"]
            assert "SUCCESS_NUMBER" in str(args[0].readable_output)

    @patch("demistomock.error")
    @patch("BmcHelixRemedyForce.return_warning")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_incident_create_command_warning(self, mocker_http_request, mocker_return_warning, mocker_error):
        """
        Given working create and but not update incident api
        When command to create incident is called
        Then incident should be created but warning output should be returned with proper context and readable
        output

        :param mocker_http_request: Mocker object for http_request
        :param mocker_return_warning: Mocker object for return_results
        :param mocker_error: mocker object for demistomock.error
        :return: None
        """

        with open(INCIDENT_TEST_DATA_FILE) as f:
            api_response = json.load(f)
        success_result = api_response["create_success"]["Result"]
        mocker_return_warning.return_value = None
        mocker_http_request.side_effect = mock_incident_warning_response

        from BmcHelixRemedyForce import bmc_remedy_incident_create_command

        bmc_remedy_incident_create_command(
            self.client, {"client_id": "SOME_CLIENT_ID", "additional_fields": "service_id=SOME_ID"}
        )

        assert mocker_return_warning.call_count == 1

        for call in mocker_return_warning.call_args_list:
            args, kwargs = call
            expected_msg = HR_MESSAGES["CREATE_INCIDENT_WARNING"].format(
                "SUCCESS_NUMBER", "client_id, service_id", "SOME_ISSUE_WITH_UPDATE"
            )
            assert expected_msg == str(kwargs["warning"])

            warning_output = {"BmcRemedyforce.Incident(val.Id === obj.Id)": success_result}

            assert warning_output == kwargs["outputs"]
            assert mocker_error.called

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_incident_create_command_failure(self, mocker_http_request):
        """
        Given non working create incident api
        When command to create incident is called
        Then error output should be returned with proper error message

        :param mocker_http_request: Mocker object for http_request
        :return: None
        """

        mocker_http_request.return_value = {"ErrorMessage": "ERROR_MSG"}

        from BmcHelixRemedyForce import bmc_remedy_incident_create_command

        with pytest.raises(DemistoException) as e:
            bmc_remedy_incident_create_command(self.client, {"client_id": "SOME_CLIENT_ID", "description": "SOME_DESC"})

        assert "ERROR_MSG" in str(e.value)

    def test_bmc_remedy_incident_create_command_input_error(self):
        """
        Given working create and update incident api
        When command to create incident is called with incorrect input
        Then error output should be returned with proper error message
        :return: None
        """

        from BmcHelixRemedyForce import bmc_remedy_incident_create_command

        with pytest.raises(DemistoException) as e:
            bmc_remedy_incident_create_command(self.client, {"client_id": "CLIENT_ID", "additional_fields": "description=test"})
        assert "description" in str(e.value)

    @patch("demistomock.error")
    @patch("BmcHelixRemedyForce.return_results")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_incident_update_command_success(self, mocker_http_request, mocker_return_results, mocker_error):
        """
        Given working update incident api
        When command for update incident is called
        Then command should return expected results and set context for update status success

        :param mocker_http_request: Mocker for http request
        :param mocker_return_results: Mocker for return_results
        :param mocker_error: mocker object for demistomock.error
        :return: None
        """
        dummy_response = fetch_dummy_response()
        dummy_response["records"][0]["BMCServiceDesk__isServiceRequest__c"] = False
        mocker_http_request.side_effect = [dummy_response, get_no_content_success_response]

        with open(INCIDENT_TEST_DATA_FILE) as f:
            update_success_context = json.load(f)["update_success"]

        from BmcHelixRemedyForce import bmc_remedy_incident_update_command

        bmc_remedy_incident_update_command(self.client, {"incident_number": "SOME_NUMBER"})

        for call in mocker_return_results.call_args_list:
            args, kwargs = call
            assert args[0].outputs["Id"] == update_success_context["Id"]
            assert args[0].outputs["Number"] == update_success_context["Number"]
            assert args[0].readable_output == HR_MESSAGES["UPDATE_INCIDENT_SUCCESS"].format("SOME_NUMBER")
            assert mocker_error.called

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_incident_update_command_input_error(self, mocker_http_request):
        """
        Given working update incident api
        When command to create incident is called with incorrect input
        Then error output should be returned with proper error message

        :param mocker_http_request: Mocker for http request
        :return: None
        """
        mocker_http_request.return_value = fetch_dummy_response()
        from BmcHelixRemedyForce import bmc_remedy_incident_update_command

        args = {"incident_number": "321"}
        with pytest.raises(DemistoException) as e:
            bmc_remedy_incident_update_command(self.client, args)
        assert MESSAGES["NOT_FOUND_INCIDENT"].format("321") == str(e.value)

    def test_remove_extra_space_from_args(self):
        """
        Given a dictionary of arguments
        When remove_extra_space_from_args is called upon them
        Then returned arguments dictionary should not contain any argument value with leading or trailing whitespaces
            and the ones with NoneType should be removed
        :return:
        """

    sample_args = {"bad_1": "", "bad_2": "      ", "can_be_better": " good  ", "good": "good", "very_bad": None}
    sanitized_args = {"can_be_better": "good", "good": "good"}
    from BmcHelixRemedyForce import remove_extra_space_from_args

    assert sanitized_args == remove_extra_space_from_args(sample_args)

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_asset_details_get_command_success(self, mock_http_res):
        """
        When bmc_remedy_asset_details_get_command command is called
        Then raw response and method called count should be as expected

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        import BmcHelixRemedyForce

        BmcHelixRemedyForce.create_asset_output = MagicMock(side_effect=BmcHelixRemedyForce.create_asset_output)

        with open("TestData/get_assets_details_records.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        mock_http_res.return_value = expected_res
        args = {"assets_name": "ADP", "instance_type": "Asset Classes"}
        result = BmcHelixRemedyForce.bmc_remedy_asset_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert BmcHelixRemedyForce.create_asset_output.call_count == 2

        args = {}
        result = BmcHelixRemedyForce.bmc_remedy_asset_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert BmcHelixRemedyForce.create_asset_output.call_count == 4

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_asset_details_get_command_no_record_found(self, mock_http_res):
        """
        Testcase for bmc_remedy_asset_details_get_command method in case of no records founds in get response.

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        expected_res = self.expected_return_null_result

        mock_http_res.return_value = expected_res
        args = {"asset_name": "aset1", "instance_type": "CI Classes"}

        result = bmc_remedy_asset_details_get_command(self.client, args)

        assert result == HR_MESSAGES["NOT_FOUND_FOR_ARGUMENTS"].format("asset(s)")

        args = {}
        result = bmc_remedy_asset_details_get_command(self.client, args)

        assert result == MESSAGES["NO_ENTITY_FOUND"].format("asset(s)")

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_account_details_get_command_success(self, mock_http_res):
        """
        Given valid param command will run successful

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        import BmcHelixRemedyForce

        BmcHelixRemedyForce.create_hr_context_output = MagicMock(side_effect=BmcHelixRemedyForce.create_hr_context_output)

        with open("TestData/get_accounts_details_success.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        mock_http_res.return_value = expected_res
        args = {"account_name": "name"}
        result = bmc_remedy_account_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert BmcHelixRemedyForce.create_hr_context_output.call_count == 1

        args = {}
        result = bmc_remedy_account_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert len(result.outputs) == 2
        assert BmcHelixRemedyForce.create_hr_context_output.call_count == 2

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_account_details_get_command_no_record_found(self, mock_http_res):
        """
        Testcase for bmc_remedy_account_details_get_command method in case of no records founds in get response.

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        expected_res = self.expected_return_null_result

        mock_http_res.return_value = expected_res
        args = {"account_name": "acc1"}
        result = bmc_remedy_account_details_get_command(self.client, args)
        assert result == MESSAGES["INVALID_ENTITY_NAME"].format("account_name", "acc1")

        args = {}
        result = bmc_remedy_account_details_get_command(self.client, args)
        assert result == MESSAGES["NO_ENTITY_FOUND"].format("account(s)")

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_status_details_get_command_success(self, mocker_http_request):
        """
        Given working platform integration
        When bmc_remedy_status_details_get_command is called with or without name parameter
        Then proper output and response should be set
        :param mocker_http_request: mocker object for http_request
        :return: None
        """

        with open("TestData/get_status_data.json", encoding="utf-8") as f:
            mock_success_response = json.load(f)

        mocker_http_request.return_value = mock_success_response

        from BmcHelixRemedyForce import bmc_remedy_status_details_get_command

        command_resp = bmc_remedy_status_details_get_command(self.client, {})

        assert len(command_resp.outputs) == 1
        assert command_resp.raw_response == mock_success_response["records"]

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_status_details_get_command_failure(self, mocker_http_request):
        """
        Given non-working platform integration
        When bmc_remedy_status_details_get_command is called with or without name parameter
        Then proper error message should be set
        :param mocker_http_request: mocker object for http_request
        :return: None
        """
        mock_empty_response = {}
        mocker_http_request.return_value = mock_empty_response

        from BmcHelixRemedyForce import bmc_remedy_status_details_get_command

        command_resp = bmc_remedy_status_details_get_command(self.client, {})

        assert MESSAGES["NO_ENTITY_FOUND"].format("status") == command_resp.readable_output

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_urgency_details_get_command_success(self, mock_http_res):
        """
        Given valid param command will run successful

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        import BmcHelixRemedyForce

        BmcHelixRemedyForce.create_hr_context_output = MagicMock(side_effect=BmcHelixRemedyForce.create_hr_context_output)

        with open("TestData/get_impacts.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        mock_http_res.return_value = expected_res
        args = {"urgency_name": "urg1"}
        result = bmc_remedy_urgency_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert BmcHelixRemedyForce.create_hr_context_output.call_count == 1

        args = {}
        result = bmc_remedy_urgency_details_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert len(result.outputs) == 2
        assert BmcHelixRemedyForce.create_hr_context_output.call_count == 2

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_urgency_details_get_command_no_record_found(self, mock_http_res):
        """
        Testcase for bmc_remedy_urgency_details_get_command method in case of no records founds in get response.

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        expected_res = self.expected_return_null_result

        mock_http_res.return_value = expected_res
        args = {"urgency_name": "urg2"}

        result = bmc_remedy_urgency_details_get_command(self.client, args)

        assert result == MESSAGES["INVALID_ENTITY_NAME"].format("urgency_name", "urg2")

        args = {}
        result = bmc_remedy_urgency_details_get_command(self.client, args)
        assert result == MESSAGES["NO_ENTITY_FOUND"].format("urgency")

    def test_bmc_remedy_category_details_get_command_invalid_type(self):
        """
        Testcase for bmc_remedy_category_details_get_command method by passing invalid type argument
        and validating exception.
        """
        args = {"type": "abc"}
        try:
            bmc_remedy_category_details_get_command(self.client, args)
        except ValueError as e:
            assert str(e) == "{}".format(MESSAGES["INVALID_TYPE_FOR_CATEGORIES"]).format(
                "type", "type", ", ".join(POSSIBLE_CATEGORY_TYPES)
            )

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_category_details_get_command_invalid_type_with_category(self, req_obj, mocker_get_session_id):
        """
        Testcase for bmc_remedy_category_details_get_command method to fetch a category mentioned
        in category_name argument but with invalid type and validating exception.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_categories
        req_obj.side_effect = [resp1]
        args = {"type": "abc", "category_name": "category"}
        try:
            bmc_remedy_category_details_get_command(self.client, args)
        except ValueError as e:
            assert str(e) == "{}".format(MESSAGES["INVALID_TYPE_FOR_CATEGORIES"]).format(
                "type", "type", ", ".join(POSSIBLE_CATEGORY_TYPES)
            )

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_category_details_get_command_type_as_service_request(self, req_obj, mocker_get_session_id):
        """
        Testcase for bmc_remedy_category_details_get_command method to fetch a categories
        which is applicable to service request.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_categories
        req_obj.side_effect = [resp1]
        args = {"type": "Service Request  "}
        actual_result = bmc_remedy_category_details_get_command(self.client, args)
        for call in req_obj.call_args_list:
            _, kwargs = call
        assert SERVICE_REQUEST_CATEGORY_OBJECT in kwargs["params"]["q"]
        assert actual_result.outputs_prefix == OUTPUT_PREFIX["CATEGORY"]
        assert actual_result.raw_response == fetch_dummy_categories()
        assert actual_result.outputs == self.dummy_categories

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_category_details_get_command_type_as_incident(self, req_obj, mocker_get_session_id):
        """
        Testcase for bmc_remedy_category_details_get_command method to fetch a categories
        which is applicable to incident.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_categories
        req_obj.side_effect = [resp1]
        args = {"type": "Incident"}
        actual_result = bmc_remedy_category_details_get_command(self.client, args)
        for call in req_obj.call_args_list:
            args, kwargs = call

        assert INCIDENT_CATEGORY_OBJECT in kwargs["params"]["q"]
        assert actual_result.outputs_prefix == OUTPUT_PREFIX["CATEGORY"]
        assert actual_result.raw_response == fetch_dummy_categories()
        assert actual_result.outputs == self.dummy_categories

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_category_details_get_command_no_record_found(self, req_obj, mocker_get_session_id):
        """
        Testcase for bmc_remedy_category_details_get_command method to fetch a mentioned category
        incase of its not found.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        expected_res = self.expected_return_null_result
        req_obj.return_value = expected_res
        args = {"category_name": "abc", "type": "Incident"}
        actual_result = bmc_remedy_category_details_get_command(self.client, args)
        assert actual_result == HR_MESSAGES["NOT_FOUND_FOR_ARGUMENTS"].format("category")

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_category_details_get_command_no_records_found(self, req_obj, mocker_get_session_id):
        """
        Testcase for bmc_remedy_category_details_get_command method to fetch all categories
        incase of no categories found.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        expected_res = self.expected_return_null_result
        req_obj.return_value = expected_res
        actual_result = bmc_remedy_category_details_get_command(self.client, {"type": "All"})
        assert actual_result == MESSAGES["NO_ENTITY_FOUND"].format("category")

    @patch("demistomock.args")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_queue_details_get_command(self, http_request, demisto_args):
        """
        Tests the get queue details command.

        :param http_request: mock object of http request.
        :param demisto_args: mock object of demisto.args.
        """
        from BmcHelixRemedyForce import bmc_remedy_queue_details_get_command

        with open("TestData/get_queue_details_response.json") as f:
            expected_response = json.load(f)
        http_request.return_value = expected_response

        args = {"type": "Incident/Service Request"}
        demisto_args.return_value = args

        response = bmc_remedy_queue_details_get_command(client=self.client, args=args)

        with open("TestData/get_queue_details_return_entry.json") as f:
            expected_return_entry = json.load(f)
        assert response.to_context() == expected_return_entry

        # No queue
        expected_response["totalSize"] = 0
        http_request.return_value = expected_response
        response = bmc_remedy_queue_details_get_command(client=self.client, args=args)
        assert response == HR_MESSAGES["NO_QUEUE_FOUND"]

    @staticmethod
    def test_prepare_query_for_queue_details_get():
        """
        Tests the user details get command query by applying parameters.
        """
        from BmcHelixRemedyForce import QUEUE_TYPES, SALESFORCE_QUERIES, prepare_query_for_queue_details_get

        # Without type and queue_name
        assert prepare_query_for_queue_details_get({}) == SALESFORCE_QUERIES["GET_QUEUE_DETAIL"].format("")

        # With queue name
        assert prepare_query_for_queue_details_get({"queue_name": "queue1"}) == SALESFORCE_QUERIES["GET_QUEUE_DETAIL"].format(
            " and name = 'queue1'"
        )

        # With type from option
        queue_type = "Incident/Service Request"
        assert prepare_query_for_queue_details_get({"type": queue_type}) == SALESFORCE_QUERIES[
            "GET_QUEUE_DETAIL_FOR_SPECIFIC_TYPE"
        ].format(QUEUE_TYPES[queue_type])

        # With type unknown
        queue_type = "task"
        assert prepare_query_for_queue_details_get({"type": queue_type}) == SALESFORCE_QUERIES[
            "GET_QUEUE_DETAIL_FOR_SPECIFIC_TYPE"
        ].format("task")

        # With type and name
        assert (
            prepare_query_for_queue_details_get({"type": "type", "queue_name": "q1"})
            == SALESFORCE_QUERIES["GET_QUEUE_DETAIL_FOR_SPECIFIC_TYPE"].format("type") + " and queue.name = 'q1'"
        )

    @patch("demistomock.args")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_user_details_get_command(self, http_request, demisto_args):
        """
        Tests the get user details command.

        :param http_request: mock object of http request.
        :param demisto_args: mock object of demisto.args.
        """
        from BmcHelixRemedyForce import bmc_remedy_user_details_get_command

        with open("TestData/get_user_details_response.json") as f:
            expected_response = json.load(f)
        http_request.return_value = expected_response

        args = {"username": "username", "email": "email"}
        demisto_args.return_value = args

        response = bmc_remedy_user_details_get_command(client=self.client, args=args)

        with open("TestData/get_user_details_return_entry.json") as f:
            expected_return_entry = json.load(f)
        assert response.to_context() == expected_return_entry

        # No users
        expected_response["totalSize"] = 0
        http_request.return_value = expected_response
        response = bmc_remedy_user_details_get_command(client=self.client, args=args)
        assert response == "No user(s) found for the given argument(s)."

    def test_prepare_query_for_user_details_get(self):
        """
        Tests the user details get command query by applying parameters.
        """
        from BmcHelixRemedyForce import prepare_query_for_user_details_get

        args = {"email": "email", "queue_name": "queue_name", "is_staff": "true", "username": "username"}
        expected_query = (
            "select id,name, firstname, lastname, username,"
            " email, phone, companyname, division, department, title,"
            " BMCServiceDesk__IsStaffUser__c, BMCServiceDesk__Account_Name__c from user where"
            " isactive=true and"
            " BMCServiceDesk__User_License__c != null and email='email' and id IN"
            " (SELECT userOrGroupId FROM groupmember WHERE group.name ='queue_name') and"
            " BMCServiceDesk__IsStaffUser__c=true and username='username'"
        )
        assert prepare_query_for_user_details_get(args) == expected_query

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_broadcast_details_get_command_with_broadcast_name(self, req_obj, mocker_get_session_id):
        """
        Testcase for bmc_remedy_broadcast_details_get_command method to fetch a broadcast
        mentioned in the argument.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_broadcasts
        req_obj.side_effect = [resp1]
        args = {"broadcast_name": "abc  "}
        actual_result = bmc_remedy_broadcast_details_get_command(self.client, args)
        for call in req_obj.call_args_list:
            args, kwargs = call
        assert args[1] == "https://sample.api.com/services/data/v48.0/query"
        assert actual_result.outputs_prefix == OUTPUT_PREFIX["BROADCAST"]
        assert actual_result.raw_response == fetch_dummy_broadcasts()
        assert actual_result.outputs == self.dummy_broadcasts

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("requests.Session.request")
    def test_bmc_remedy_broadcast_details_get_command_with_category_name(self, req_obj, mocker_get_session_id):
        """
        Testcase for bmc_remedy_broadcast_details_get_command method to fetch a broadcast with having category
        mentioned in the argument.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        resp1 = Mock(spec=requests.Response)
        resp1.status_code = 200
        resp1.json = fetch_dummy_broadcasts
        req_obj.side_effect = [resp1]
        args = {"category_name": "abc  "}
        actual_result = bmc_remedy_broadcast_details_get_command(self.client, args)
        for call in req_obj.call_args_list:
            args, kwargs = call

        assert args[1] == "https://sample.api.com/services/data/v48.0/query"
        assert "BMCServiceDesk__Category_ID__c='abc'" in kwargs["params"]["q"]
        assert actual_result.outputs_prefix == OUTPUT_PREFIX["BROADCAST"]
        assert actual_result.raw_response == fetch_dummy_broadcasts()
        assert actual_result.outputs == self.dummy_broadcasts

    @patch("BmcHelixRemedyForce.Client.get_session_id")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_broadcast_details_get_command_no_records_found(self, req_obj, mocker_get_session_id):
        """
        Testcase for bmc_remedy_category_details_get_command method to fetch all categories
        incase of no categories found.

        :param req_obj: mocker object for making http request call
        :param mocker_get_session_id: mocker object for getting valid session id
        """
        mocker_get_session_id.return_value = self.valid_session_id
        expected_res = self.expected_return_null_result
        req_obj.return_value = expected_res
        actual_result = bmc_remedy_broadcast_details_get_command(self.client, {})
        assert actual_result == HR_MESSAGES["NO_BROADCAST_DETAILS_FOUND"]

    def test_prepare_iso_date_string(self):
        from BmcHelixRemedyForce import prepare_iso_date_string

        assert prepare_iso_date_string("") == ""
        assert prepare_iso_date_string("random string") == ""
        assert prepare_iso_date_string("2020-07-23T07:40:06.000+0000") == "2020-07-23T07:40:06+00:00"

    def test_validate_and_get_date_argument(self):
        """
        Given arguments dictionary and date key
        When validate_and_get_date_argument is called
        Then a valid datetime object should be returned or an exception should be thrown if key exists,
        None should be returned if key does not exist
        :return:None
        """
        from BmcHelixRemedyForce import validate_and_get_date_argument

        assert isinstance(validate_and_get_date_argument({"date_key": "2020-08-23T08:53:00.000Z"}, "date_key", "date"), datetime)
        assert isinstance(
            validate_and_get_date_argument({"date1_key": "2020-08-23T08:53:00.000+0530"}, "date1_key", "date1"), datetime
        )
        assert isinstance(validate_and_get_date_argument({"date1_key": "2020-08-23"}, "date1_key", "date1"), datetime)
        assert not validate_and_get_date_argument({"date_key": "2020-08-23"}, "date2_key", "date")

        with pytest.raises(ValueError) as e:
            validate_and_get_date_argument({"wrong_date_key": "2020-08-23asd"}, "wrong_date_key", "wrong_date")

        assert "wrong_date" in str(e.value)

    def test_validate_incident_update_payload(self):
        """
        Given arguments dictionary with incident update details
        When validate_incident_update_payload is called
        Then required validations should take place and an exception should be raised, in case provided payload is
        invalid
        :return: None
        """
        from BmcHelixRemedyForce import MAPPING_OF_FIELDS_WITH_SALESFORCE_COLUMNS, validate_incident_update_payload

        sample_payload = {
            MAPPING_OF_FIELDS_WITH_SALESFORCE_COLUMNS["opened_date"]: "2020-08-23T08:53:00.000Z",
            MAPPING_OF_FIELDS_WITH_SALESFORCE_COLUMNS["due_date"]: "2020-08-23T08:54:00.000Z",
            MAPPING_OF_FIELDS_WITH_SALESFORCE_COLUMNS["outage_start"]: "2020-08-23T08:53:00.000Z",
            MAPPING_OF_FIELDS_WITH_SALESFORCE_COLUMNS["outage_end"]: "2020-08-23T08:50:00.000Z",
        }

        with pytest.raises(ValueError) as e:
            validate_incident_update_payload(sample_payload)

        assert MESSAGES["DATE_VALIDATION_ERROR"].format("outage_end", "outage_start") == str(e.value)

        sample_payload[MAPPING_OF_FIELDS_WITH_SALESFORCE_COLUMNS["due_date"]] = "2020-08-23T08:50:00.000Z"

        with pytest.raises(ValueError) as e:
            validate_incident_update_payload(sample_payload)

        assert MESSAGES["DATE_VALIDATION_ERROR"].format("due_date", "opened_date") == str(e.value)

    @patch("demistomock.params")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_attachments_for_incident_success(self, mocker_http_request, mocker_params):
        """
        Given working integration instance
        When get_attachments_for_incident() is called
        Then attachments for the passed id, should be returned in the expected format
        :param mocker_http_request: mocker object for http call
        :param mocker_params: mocker object for demisto.params()
        :return: None
        """

        with open("./TestData/get_incident_attachments.json") as f:
            api_response = json.load(f)

        mocker_params.return_value = {"url": "BASE_URL"}

        mocker_http_request.return_value = api_response

        from BmcHelixRemedyForce import get_attachments_for_incident

        response = get_attachments_for_incident(self.client, "SOME_ID")

        assert len(response) == 1
        assert "BASE_URL" + URL_SUFFIX["DOWNLOAD_ATTACHMENT"].format("CONTENT_ID") == response[0].get("Download Link", "")
        assert response[0].get("File", "") == "test_doc"
        assert response[0].get("Created By", "") == "TEST USER"

    @patch("demistomock.params")
    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_attachments_for_incident_failure(self, mocker_http_request, mocker_params):
        """
        Given non working integration instance
        When get_attachments_for_incident() is called
        Then exception should be thrown with proper message
        :param mocker_http_request: mocker object for http call
        :param mocker_params: mocker object for demisto.params()
        :return: None
        """

        mocker_params.return_value = {"url": "BASE_URL"}

        mocker_http_request.side_effect = DemistoException("ERROR_MSG")

        from BmcHelixRemedyForce import get_attachments_for_incident

        with pytest.raises(DemistoException) as e:
            get_attachments_for_incident(self.client, "SOME_ID")

        assert str(e.value) == "ERROR_MSG"

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_notes_for_incident_success(self, mock_http_res):
        """
        When get_notes_for_incident method is called
        Then return value should be as expected

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        import BmcHelixRemedyForce

        BmcHelixRemedyForce.process_notes_record = MagicMock(side_effect=BmcHelixRemedyForce.process_notes_record)

        with open("TestData/get_note_from_incident_success.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        date_time = dateparser.parse("2020-07-28T10:44:33.000+0000")
        date = date_time.strftime(DISPLAY_DATE_FORMAT)
        records = [
            {
                "Note": "note_c",
                "Date & Time [UTC]": date,
                "Incident History ID": "123_0",
                "Action~": "action_id",
                "Description": "desc",
                "Sender": "sample_name",
            }
        ]
        mock_http_res.return_value = expected_res

        result = BmcHelixRemedyForce.get_notes_for_incident(self.client, "33")
        assert result == records
        assert BmcHelixRemedyForce.process_notes_record.call_count == 1

        result2 = BmcHelixRemedyForce.get_notes_for_incident(self.client, "")
        assert result2 == []
        assert BmcHelixRemedyForce.process_notes_record.call_count == 1

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_get_service_request_details(self, mock_http_res):
        """
        When get_service_request_details method is called
        Then return value should be as expected

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        resp1 = {
            "Success": True,
            "Result": {
                "Answers": [{"QuestionText": "question1", "Text": "answer1"}, {"QuestionText": "question2", "Text": "answer2"}]
            },
        }
        mock_http_res.return_value = resp1
        actual_response = get_service_request_details(self.client, "abc")
        assert actual_response == {"question1": "answer1", "question2": "answer2"}

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_incident_get_command_success(self, mock_http_res):
        """
        Given valid param command will run successful.

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        import BmcHelixRemedyForce

        BmcHelixRemedyForce.create_output_for_incident = MagicMock(side_effect=BmcHelixRemedyForce.create_output_for_incident)

        with open("TestData/fetch_incident_response.json", encoding="utf-8") as f:
            expected_res = json.load(f)

        mock_http_res.return_value = expected_res
        args = {"time": "1 day", "incident_number": "123"}

        result = BmcHelixRemedyForce.bmc_remedy_incident_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert BmcHelixRemedyForce.create_output_for_incident.call_count == 1

        args = {}
        result = BmcHelixRemedyForce.bmc_remedy_incident_get_command(self.client, args)
        assert result.raw_response == expected_res
        assert len(result.outputs) == 1
        assert BmcHelixRemedyForce.create_output_for_incident.call_count == 2

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_incident_get_command_no_incident_found(self, mock_http_res):
        """
        Given valid param command will run with message.

        :param mock_http_res: mocker object for Client.http_request
        :return: None
        """
        import BmcHelixRemedyForce

        mock_http_res.return_value = {}
        args = {"time": "2 months", "incident_number": "321", "maximum_incident ": "50"}
        result = BmcHelixRemedyForce.bmc_remedy_incident_get_command(self.client, args)
        assert result == HR_MESSAGES["NO_INCIDENT_DETAILS_FOUND"]

    def test_bmc_remedy_incident_get_command_invalid_maximum_service_request(self):
        """
        Testcase for bmc_remedy_incident_get_command method to fetch a service request with
        given arguments and verify exception when invalid maximum_service_request is given.

        """
        from BmcHelixRemedyForce import bmc_remedy_incident_get_command

        args = {"maximum_incident": "aaa"}
        try:
            bmc_remedy_incident_get_command(self.client, args)
        except ValueError as e:
            assert str(e) == MESSAGES["MAX_INCIDENT_LIMIT"].format("maximum_incident")
        args = {"maximum_incident": "501"}
        try:
            bmc_remedy_incident_get_command(self.client, args)
        except ValueError as e:
            assert str(e) == MESSAGES["MAX_INCIDENT_LIMIT"].format("maximum_incident")

    def test_prepare_outputs_for_get_service_request(self):
        """
        Testcase of prepare_outputs_for_get_service_request method
        and verify context and human readable outputs.
        """
        outputs, hr_outputs = prepare_outputs_for_get_service_request(self.get_service_request_response["input_records"])
        assert outputs == self.get_service_request_response["expected_records"]
        assert hr_outputs == self.get_service_request_response["expected_records"]

    @patch("BmcHelixRemedyForce.Client.http_request")
    def test_bmc_remedy_service_request_get_command(self, mock_http_res):
        """
        Testcase for bmc_remedy_service_request_get_command method to fetch a service request with
        given arguments.

        :param mock_http_res: mocker object for making http request call
        """
        mock_http_res.return_value = self.get_service_request_response["actual_response"]
        input_args = self.get_service_request_response["input_args"]
        actual_result = bmc_remedy_service_request_get_command(self.client, input_args)
        assert actual_result.outputs_prefix == OUTPUT_PREFIX["SERVICE_REQUEST"]
        assert actual_result.outputs_key_field == "Number"
        assert actual_result.outputs == self.get_service_request_response["expected_records"]
        assert actual_result.raw_response == self.get_service_request_response["actual_response"]

    def test_bmc_remedy_service_request_get_command_invalid_maximum_service_request(self):
        """
        Testcase for bmc_remedy_service_request_get_command method to fetch a service request with
        given arguments and verify exception when invalid maximum_service_request is given.

        :param mock_http_res: mocker object for making http request call
        """
        input_args = self.get_service_request_response["input_args"]
        input_args["maximum_service_request"] = "abc"
        try:
            bmc_remedy_service_request_get_command(self.client, input_args)
        except ValueError as e:
            assert str(e) == MESSAGES["MAX_INCIDENT_LIMIT"].format("maximum_service_request")
        input_args["maximum_service_request"] = "1000"
        try:
            bmc_remedy_service_request_get_command(self.client, input_args)
        except ValueError as e:
            assert str(e) == MESSAGES["MAX_INCIDENT_LIMIT"].format("maximum_service_request")