FlashpointReportDetails

Retrieves the full information of the report.

python · Flashpoint

Details

IDFlashpointReportDetails
Languagepython
From Version6.10.0
Docker Imagedemisto/python3:3.12.13.10404775

README

Retrieves the full information of the report.

Script Data


Name Description
Script Type python3
Cortex XSOAR Version 6.10.0

Inputs


Argument Name Description
report_id The ID of the report for which the details are to be fetched.

Note: If not provided, the script will try to retrieve it from the incident context.

Outputs


There are no outputs for this script.

"""FlashpointReportDetails Test File."""

import json
from unittest.mock import patch

import demistomock as demisto
import pytest
from FlashpointReportDetails import (
    ALERT_TEXT_FIELD,
    EMPTY_DATA,
    ERROR_MESSAGES,
    REPORT_GET_COMMAND,
    SET_INCIDENT_COMMAND,
    get_report_details,
    main,
)

""" CONSTANTS """

REPORT_ID = "00000000000000000001"

""" UTILITY FUNCTIONS """


def util_load_json(path: str):
    """Load a json to python dict."""
    with open(path, encoding="utf-8") as f:
        return json.loads(f.read())


def get_execute_command_mock(mocker, report_response):
    """
    Mock demisto.executeCommand to return the given response for the report-get command.

    :type mocker: pytest_mock.MockerFixture
    :param mocker: Mocker fixture.

    :type report_response: Any
    :param report_response: Response to return for the report-get command.

    :return: The mocked executeCommand object.
    """

    def side_effect(command, args):
        if command == REPORT_GET_COMMAND:
            return report_response
        return [{"Type": 1, "Contents": "", "ContentsFormat": "text"}]

    return mocker.patch.object(demisto, "executeCommand", side_effect=side_effect)


def assert_set_incident_call(execute_command_mock, expected_body):
    """
    Assert that setIncident was called with the expected report body.

    :type execute_command_mock: unittest.mock.MagicMock
    :param execute_command_mock: The mocked executeCommand object.

    :type expected_body: str
    :param expected_body: Expected value of the report body field.
    """
    set_incident_calls = [call for call in execute_command_mock.call_args_list if call.args[0] == SET_INCIDENT_COMMAND]

    assert len(set_incident_calls) == 1
    assert set_incident_calls[0].args[1] == {ALERT_TEXT_FIELD: expected_body}


""" TEST CASES """


@pytest.mark.parametrize(
    "args, incident",
    [
        ({"report_id": REPORT_ID}, {}),
        ({}, {"CustomFields": {"flashpointsourceid": REPORT_ID}}),
    ],
)
def test_get_report_details_success(mocker, args, incident):
    """
    Test case scenario for successful execution of get_report_details.

    Given:
       - report_id argument, or an incident with the 'flashpointsourceid' custom field
    When:
       - Calling `get_report_details` function
    Then:
       - Returns the raw report entry and sets the report body on the incident.
    """
    report_response = util_load_json("test_data/report_get_success.json")

    mocker.patch.object(demisto, "incident", return_value=incident)
    execute_command_mock = get_execute_command_mock(mocker, [report_response])

    result = get_report_details(args)

    assert result == report_response
    assert execute_command_mock.call_args_list[0].args == (REPORT_GET_COMMAND, {"report_id": REPORT_ID})
    assert_set_incident_call(execute_command_mock, report_response["Contents"]["body"])


def test_get_report_details_when_no_report_body(mocker):
    """
    Test case scenario for execution of get_report_details when the command succeeds without a report body.

    Given:
       - report_id argument and a successful response without a body
    When:
       - Calling `get_report_details` function
    Then:
       - Returns the raw report entry and sets the placeholder message on the incident.
    """
    report_response = util_load_json("test_data/report_get_success_without_body.json")

    mocker.patch.object(demisto, "incident", return_value={})
    execute_command_mock = get_execute_command_mock(mocker, [report_response])

    result = get_report_details({"report_id": REPORT_ID})

    assert result == report_response
    assert_set_incident_call(execute_command_mock, EMPTY_DATA)


def test_get_report_details_when_command_fails(mocker):
    """
    Test case scenario for execution of get_report_details when the report-get command fails.

    Given:
       - report_id argument and a non-list error response from the report-get command
    When:
       - Calling `get_report_details` function
    Then:
       - Returns an empty dict, logs the error and sets the placeholder message on the incident.
    """
    error = "Error in API call [404] - Not Found"

    mocker.patch.object(demisto, "incident", return_value={})
    error_mock = mocker.patch.object(demisto, "error")
    execute_command_mock = get_execute_command_mock(mocker, {"Type": 4, "Contents": error, "ContentsFormat": "text"})

    result = get_report_details({"report_id": REPORT_ID})

    assert result == {}
    assert error_mock.call_args.args[0] == ERROR_MESSAGES["FAILED_COMMAND"].format(REPORT_GET_COMMAND, error)
    assert_set_incident_call(execute_command_mock, EMPTY_DATA)


@pytest.mark.parametrize(
    "args, incident",
    [
        ({}, {}),
        ({"report_id": None}, {}),
        ({"report_id": ""}, {"CustomFields": {}}),
        ({"report_id": ""}, {"CustomFields": {"flashpointsourceid": ""}}),
    ],
)
def test_get_report_details_when_invalid_arguments(mocker, args, incident):
    """
    Test case scenario for execution of get_report_details when report_id can not be resolved.

    Given:
       - no report_id argument and an incident without the 'flashpointsourceid' custom field
    When:
       - Calling `get_report_details` function
    Then:
       - Raises a valid error message.
    """
    mocker.patch.object(demisto, "incident", return_value=incident)
    execute_command_mock = mocker.patch.object(demisto, "executeCommand")

    with pytest.raises(ValueError) as error:
        get_report_details(args)

    assert str(error.value) == ERROR_MESSAGES["MISSING_ARGUMENT"].format("report_id")
    assert execute_command_mock.call_count == 0


@patch("FlashpointReportDetails.return_results")
def test_main_success(mock_return_results, mocker):
    """
    Test case scenario for successful execution of the script through the main function.

    Given:
       - report_id argument with surrounding whitespaces
    When:
       - Calling `main` function
    Then:
       - Returns the raw report entry and sets the report body on the incident.
    """
    report_response = util_load_json("test_data/report_get_success.json")

    mocker.patch.object(demisto, "args", return_value={"report_id": f" {REPORT_ID} "})
    mocker.patch.object(demisto, "incident", return_value={})
    execute_command_mock = get_execute_command_mock(mocker, [report_response])

    main()

    assert mock_return_results.call_args.args[0] == report_response
    assert execute_command_mock.call_args_list[0].args == (REPORT_GET_COMMAND, {"report_id": REPORT_ID})
    assert_set_incident_call(execute_command_mock, report_response["Contents"]["body"])


@patch("FlashpointReportDetails.return_error")
def test_main_calls_return_error_on_exception(mock_return_error, mocker):
    """
    Test case scenario for execution of the script through the main function when an exception is raised.

    Given:
       - no report_id argument and an incident without the 'flashpointsourceid' custom field
    When:
       - Calling `main` function
    Then:
       - Returns a valid error message.
    """
    mocker.patch.object(demisto, "args", return_value={})
    mocker.patch.object(demisto, "incident", return_value={})
    mocker.patch.object(demisto, "error")

    main()

    assert mock_return_error.call_args.args[0] == (
        f"Failed to execute FlashpointReportDetails. Error: {ERROR_MESSAGES['MISSING_ARGUMENT'].format('report_id')}"
    )