import pytest from CommonServerPython import * RETURN_ERROR_TARGET = "GetListRow.return_error" DATA_WITH_CUSTOM_SEP = [{"Contents": "name;id\nname1;id1\nname2;id2"}] DATA_WITH_NEW_LINE_SEP = [{"Contents": "name\nid\nname1\nid1\nname2\nid2"}] DATA_WITH_TAB_SEP = [{"Contents": "name id\nname1 id1\nname2 id2"}] DATA_WITH_TAB_SEP_2 = [{"Contents": "name\tid\nname1\tid1\nname2\tid2"}] @pytest.mark.parametrize( "parse_all, header, value, expected", [("True", "", "", 0), ("true", "", "test", 0), ("False", "", "test", 1), ("False", "", "", 1), ("False", "test", "test", 0)], ) def test_validate_args(mocker, parse_all, header, value, expected): from GetListRow import validate_args return_error_mock = mocker.patch(RETURN_ERROR_TARGET) validate_args(parse_all, header, value) assert return_error_mock.call_count == expected @pytest.mark.parametrize("list_result, expected", [("False", 0), ("id, name, status, title", 0), ("Item not found", 1), ("", 1)]) def test_does_list_exist(mocker, list_result, expected): from GetListRow import validate_list_exists return_error_mock = mocker.patch(RETURN_ERROR_TARGET) validate_list_exists(list_result) assert return_error_mock.call_count == expected @pytest.mark.parametrize( "headers, header, expected", [ (["id", "name", "title", "status"], "id", 0), (["id", "name", "title", "status"], "status", 0), (["id", "name", "title", "status"], "statu", 1), (["id", "name"], "title", 1), ], ) def test_does_header_exist(mocker, headers, header, expected): from GetListRow import validate_header_exists return_error_mock = mocker.patch(RETURN_ERROR_TARGET) validate_header_exists(headers, header) assert return_error_mock.call_count == expected @pytest.mark.parametrize( "parse_all, header, value, list_name, list_separator, expected", [ ("True", "", "on", "getListRow", ",", "List Result"), ("False", "status", "on", "getListRow", ",", "List Result"), ("False", "status", "n", "getListRow", ",", "No results found"), ], ) def test_parse_list(mocker, parse_all, header, value, list_name, list_separator, expected): from GetListRow import parse_list mocker.patch.object( demisto, "executeCommand", return_value=[ { "Contents": """id,name,title,status 1,Chanoch,junior,on 2,Or,manager,off 3,Chen,developer,on""" } ], ) res = parse_list(parse_all, header, value, list_name, list_separator) assert expected in res.readable_output @pytest.mark.parametrize( "data, parse_all, header, value, list_name, list_separator, expected", [ ( DATA_WITH_CUSTOM_SEP, "True", "name", "id", "getListRow", ";", [{"name": "name1", "id": "id1"}, {"name": "name2", "id": "id2"}], ), (DATA_WITH_CUSTOM_SEP, "False", "name", "name2", "getListRow", ";", [{"name": "name2", "id": "id2"}]), ], ) def test_custom_list_separator(mocker, data, parse_all, header, value, list_name, list_separator, expected): """ Given: - Data that should be split by the custom separator ';'. When: - Running the script with a custom separator arg Then: - Ensure the parsed sata was split correctly """ from GetListRow import parse_list mocker.patch.object(demisto, "executeCommand", return_value=data) res = parse_list(parse_all, header, value, list_name, list_separator) assert res.outputs.get("Results") == expected @pytest.mark.parametrize( "data, parse_all, header, value, list_name, list_separator, expected", [ ( DATA_WITH_NEW_LINE_SEP, "True", "name", "id", "getListRow", "\n", [{"name": "id"}, {"name": "name1"}, {"name": "id1"}, {"name": "name2"}, {"name": "id2"}], ), (DATA_WITH_NEW_LINE_SEP, "False", "name", "name2", "getListRow", "\n", [{"name": "name2"}]), ], ) def test_custom_list_new_line_sep(mocker, data, parse_all, header, value, list_name, list_separator, expected): """ Given: - Data that should be split by the custom separator '\n'. When: - Running the script with a custom separator arg Then: - Ensure the parsed sata was split correctly """ from GetListRow import parse_list mocker.patch.object(demisto, "executeCommand", return_value=data) res = parse_list(parse_all, header, value, list_name, list_separator) assert res.outputs.get("Results") == expected @pytest.mark.parametrize( "data, parse_all, header, value, list_name, list_separator, expected", [ ( DATA_WITH_TAB_SEP, "True", "name", "id", "getListRow", "\t", [{"name": "name1", "id": "id1"}, {"name": "name2", "id": "id2"}], ), (DATA_WITH_TAB_SEP, "False", "name", "name2", "getListRow", " ", [{"name": "name2", "id": "id2"}]), ( DATA_WITH_TAB_SEP_2, "True", "name", "id", "getListRow", "\\t", [{"name": "name1", "id": "id1"}, {"name": "name2", "id": "id2"}], ), ( DATA_WITH_TAB_SEP_2, "True", "name", "id", "getListRow", "\t", [{"name": "name1", "id": "id1"}, {"name": "name2", "id": "id2"}], ), ], ) def test_custom_list_tab_sep(mocker, data, parse_all, header, value, list_name, list_separator, expected): """ Given: - Data that should be split by the tab separator (' '). When: - Running the script with a custom separator arg Then: - Ensure the parsed sata was split correctly """ import GetListRow mock_args = { "list_name": list_name, "parse_all": parse_all, "header": header, "value": value, "list_separator": list_separator, } mocker.patch.object(demisto, "args", return_value=mock_args) mocker.patch.object(demisto, "executeCommand", return_value=data) mocker.patch.object(GetListRow, "return_results", return_value=data) GetListRow.main() assert GetListRow.return_results.call_args[0][0].outputs.get("Results") == expected @pytest.mark.parametrize( "data, parse_all, header, value, expected_context_key", [ (DATA_WITH_NEW_LINE_SEP, "True", "name", "id", ["list_name", "parse_all"]), (DATA_WITH_NEW_LINE_SEP, "False", "name", "name2", ["list_name", "parse_all", "header", "value"]), ], ) def test_context_path_are_correct(mocker, data, parse_all, header, value, expected_context_key): from GetListRow import parse_list mocker.patch.object(demisto, "executeCommand", return_value=data) res = parse_list(parse_all, header, value, list_name="getListRow", list_separator="\n") assert res.outputs_prefix == "GetListRow" assert res.outputs_key_field == expected_context_key @pytest.mark.parametrize( "list_data, expected_headers, expected_lines", [ ( "header_a ,header_b\nline_1_item_a,line_1_item_b\nline_2_item_a,line_2_item_b", ["header_a ", "header_b"], [["line_1_item_a", "line_1_item_b"], ["line_2_item_a", "line_2_item_b"]], ), ( "header_a ,header_b\nline\r_1_item_a,line_1_item_b\nline\r_2_item_a,line_2_item_b", ["header_a ", "header_b"], [["line\r_1_item_a", "line_1_item_b"], ["line\r_2_item_a", "line_2_item_b"]], ), ( "header_a ,header_b\r\nline_1_item_a,line_1_item_b\r\nline_2_item_a,line_2_item_b", ["header_a ", "header_b"], [["line_1_item_a", "line_1_item_b"], ["line_2_item_a", "line_2_item_b"]], ), ], ) def test_list_to_headers_and_lines(list_data, expected_headers, expected_lines): """ Given: - list_data. - Case 1: list data without any \r. - Case 2: list data with \r in the middle of a line. - Case 3: list data with \r followed by \n at the end of each line (except for last). When: - Running list_to_headers_and_lines. Then: - Ensure that the right parts of line was parsed into headers & lines. - Case 1: Should split the lines by \n. - Case 2: Should split the lines by \n and not do anything about the \r. - Case 3: Should split the lines by \r\n. """ from GetListRow import list_to_headers_and_lines headers, lines = list_to_headers_and_lines(list_data, ",") assert expected_headers == headers assert expected_lines == lines def test_parse_list_with_new_line_at_the_end(mocker): """ Given: - A list with a new line at the end. When: - Parsing the list. Then: - Make sure that no exception is raised and the code finished gracefully. """ list_with_new_line_at_the_end = """,mapping_framework,mapping_framework_version,capability_group,capability_id 0,veris,1.3.7,action.hacking """ from GetListRow import parse_list mocker.patch.object(demisto, "executeCommand", return_value=[{"Contents": list_with_new_line_at_the_end}]) res = parse_list(parse_all="false", header="mapping_framework", value="veris", list_name="test_list", list_separator=",") assert res