import json import pytest import demistomock as demisto from Gamma import Client, fetch_incidents, Command, main MOCK_URL = "mock://fake-api.net" MOCK_VIOLATION = { "response": [ { "app_name": "jira", "dashboard_url": f"{MOCK_URL}/violationId/2036", "file_labels_map": {}, "text_labels": [], "user": { "active_directory_user_id": None, "atlassian_account_id": None, "email_address": None, "github_handle": None, "name": "Amane Suzuha", "slack_user_id": None, }, "violation_category": "mock_category", "violation_event_timestamp": 1605805555, "violation_id": 2036, "violation_status": "OPEN", } ] } MOCK_VIOLATION_2 = { "response": [ { "app_name": "jira", "dashboard_url": f"{MOCK_URL}/violationId/5100", "file_labels_map": {}, "text_labels": [], "user": { "active_directory_user_id": None, "atlassian_account_id": None, "email_address": None, "github_handle": None, "name": "Rintaro Okabe", "slack_user_id": None, }, "violation_category": "mock_category", "violation_event_timestamp": 1605804455, "violation_id": 5100, "violation_status": "OPEN", } ] } MOCK_VIOLATION_2_UPDATED = { "response": [ { "app_name": "jira", "dashboard_url": f"{MOCK_URL}/violationId/5100", "file_labels_map": {}, "text_labels": [], "user": { "active_directory_user_id": None, "atlassian_account_id": None, "email_address": None, "github_handle": None, "name": "Rintaro Okabe", "slack_user_id": None, }, "violation_category": "mock_category", "violation_event_timestamp": 1605804455, "violation_id": 5100, "violation_status": "RESOLVED", } ] } MOCK_ALL_VIOLATIONS = {"response": [MOCK_VIOLATION["response"][0], MOCK_VIOLATION_2["response"][0]]} def mock_demisto(mocker, args_value=None, command_value=None): mocker.patch.object(demisto, "results") mocker.patch.object(demisto, "params", return_value={"api_key": "thisisatestkey", "url": MOCK_URL}) if not args_value: args_value = {"entryID": "entry_id", "parseAll": "yes", "codec": "utf-8"} if command_value: mocker.patch.object(demisto, "command", return_value=command_value) mocker.patch.object(demisto, "args", return_value=args_value) def mock_client(mocker, demisto): mocker.patch.object(demisto, "params", return_value={"api_key": "thisisatestkey", "url": MOCK_URL}) client = Client(demisto) return client @pytest.mark.parametrize( "last_run_violation,first_fetch_violation,max_results,output_1,output_2", [ ({}, "1", "10", "Gamma Violation 2036", 5100), ({}, "1", "0", "Gamma Violation 2036", 5100), ({}, "1", "-1", "Gamma Violation 2036", 5100), ({}, "1", "200", "Gamma Violation 2036", 5100), ], ) def test_fetch_incidents(last_run_violation, first_fetch_violation, max_results, output_1, output_2, requests_mock, mocker): requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_ALL_VIOLATIONS) # Test fetch next_run, incidents = fetch_incidents(mock_client(mocker, demisto), last_run_violation, first_fetch_violation, max_results) mocker.patch.object(demisto, "incidents", incidents) assert output_1 == demisto.incidents[0]["name"] assert output_2 == next_run["starting_violation"] @pytest.mark.parametrize( "next_run,first_fetch_violation,max_results,output_1,output_2", [({"starting_violation": 2036}, "1", "10", 1, 5100), ({"starting_violation": 5100}, "1", "10", 0, 5100)], ) def test_fetch_incidents_next_fetch(next_run, first_fetch_violation, max_results, output_1, output_2, requests_mock, mocker): requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_ALL_VIOLATIONS) next_run, incidents = fetch_incidents(mock_client(mocker, demisto), next_run, first_fetch_violation, max_results) assert output_1 == len(incidents) assert output_2 == next_run["starting_violation"] @pytest.mark.parametrize( "last_run_violation,first_fetch_violation,max_results,output", [ ({}, "0", "10", "first_fetch_violation must be equal to 1 or higher"), ({}, "-1", "10", "first_fetch_violation must be equal to 1 or higher"), ({}, "test", "10", "first_fetch_violation and max_limit must be integers"), ({}, "1", "test", "first_fetch_violation and max_limit must be integers"), ], ) def test_fetch_incidents_bad_input(last_run_violation, first_fetch_violation, max_results, output, mocker): with pytest.raises(ValueError) as err: fetch_incidents(mock_client(mocker, demisto), last_run_violation, first_fetch_violation, max_results) assert output == str(err.value) def test_get_violation_command(requests_mock, mocker, capfd): requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_VIOLATION) args = {"violation": "2036"} mock_demisto(mocker, args, "gamma-get-violation") with capfd.disabled(): main() content = demisto.results.call_args[0][0]["Contents"][0]["violation_id"] assert content == 2036 @pytest.mark.parametrize( "demisto_args,output", [ ({"violation": "0"}, "Violation must be greater than 0"), ({"violation": "-1"}, "Violation must be greater than 0"), ({"violation": "test"}, "invalid literal for int() with base 10: 'test'"), ], ) def test_get_violation_command_bad_input(demisto_args, output, mocker): client = mock_client(mocker, demisto) with pytest.raises(ValueError) as err: Command.get_violation(client, demisto_args) assert output == str(err.value) @pytest.mark.parametrize( "demisto_args,output", [ ({"minimum_violation": "2036", "limit": "2"}, 2036), ({"minimum_violation": "2035", "limit": "2"}, 2036), ], ) def test_get_violation_list_command(demisto_args, output, requests_mock, mocker, capfd): requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_ALL_VIOLATIONS) mock_demisto(mocker, demisto_args, "gamma-get-violation-list") with capfd.disabled(): main() content = demisto.results.call_args[0][0]["Contents"][0]["violation_id"] assert output == content @pytest.mark.parametrize( "demisto_args,output", [ ({"minimum_violation": "0", "limit": "2"}, "minimum_violation must be greater than 0"), ({"minimum_violation": "test", "limit": "2"}, "invalid literal for int() with base 10: 'test'"), ({"minimum_violation": "-1", "limit": "2"}, "minimum_violation must be greater than 0"), ({"minimum_violation": "2035", "limit": "0"}, "limit must be between 1 and 100"), ({"minimum_violation": "2035", "limit": "-1"}, "limit must be between 1 and 100"), ({"minimum_violation": "2035", "limit": "test"}, "invalid literal for int() with base 10: 'test'"), ], ) def test_get_violation_list_command_bad_input(demisto_args, output, mocker): client = mock_client(mocker, demisto) with pytest.raises(ValueError) as err: Command.get_violation_list(client, demisto_args) assert output == str(err.value) @pytest.mark.parametrize( "demisto_args,demisto_command,output", [ ( {"violation": "5100", "status": "resolved", "notes": "This has been updated!"}, "gamma-update-violation", "RESOLVED", ), ], ) def test_update_violation_command(demisto_args, demisto_command, output, requests_mock, mocker, capfd): test_violation = 5100 requests_mock.put(MOCK_URL + f"/api/discovery/v1/violation/{test_violation}", json=MOCK_VIOLATION_2) requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_VIOLATION_2_UPDATED) mock_demisto(mocker, demisto_args, demisto_command) with capfd.disabled(): main() contents = demisto.results.call_args[0][0]["Contents"][0]["violation_status"] assert output == contents @pytest.mark.parametrize( "demisto_args,output", [ ({"violation": "0", "status": "resolved", "notes": "This has been updated!"}, "Violation must be greater than 0"), ({"violation": "-1", "status": "resolved", "notes": "This has been updated!"}, "Violation must be greater than 0"), ( {"violation": "test", "status": "resolved", "notes": "This has been updated!"}, "invalid literal for int() with base 10: 'test'", ), ( {"violation": "5100", "status": "closed", "notes": "This has been updated!"}, "Status must be one of the following: OPEN, RESOLVED, IGNORED", ), ], ) def test_update_violation_command_bad_input(demisto_args, output, mocker): client = mock_client(mocker, demisto) with pytest.raises(ValueError) as err: Command.update_violation(client, demisto_args) assert output == str(err.value) @pytest.mark.parametrize( "demisto_args,demisto_command,output_1,output_2", [ ({}, "fetch-incidents", "Gamma Violation 2036", "Gamma Violation 5100"), ( {"first_fetch_violation": "2036", "max_results": "5"}, "fetch-incidents", "Gamma Violation 2036", "Gamma Violation 5100", ), ], ) def test_main_fetch_incidents(demisto_args, demisto_command, output_1, output_2, requests_mock, mocker, capfd): # Test fetch requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_ALL_VIOLATIONS) mock_demisto(mocker, demisto_args, demisto_command) with capfd.disabled(): main() contents = json.loads(demisto.results.call_args[0][0]["Contents"]) assert output_1 == contents[0]["name"] assert output_2 == contents[1]["name"] def test_main_get_violation_list(requests_mock, mocker, capfd): # Test fetch requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_ALL_VIOLATIONS) args = {"minimum_id": "2036", "limit": "5"} command = "gamma-get-violation-list" mock_demisto(mocker, args, command) with capfd.disabled(): main() response = demisto.results.call_args[0][0]["Contents"] assert {2036, 5100} == {i["violation_id"] for i in response} def test_main_get_bad_violation(mocker, requests_mock, capfd): requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_VIOLATION) # Test wrong ID command = "gamma-get-violation" args = {"violation": "5100"} mock_demisto(mocker, args, command) with pytest.raises(SystemExit), capfd.disabled(): main() assert ( demisto.results.call_args[0][0]["Contents"] == "Failed to execute gamma-get-violation " "command.\nError:\nViolation with this " "ID does not exist." ) def test_main_get_violation(requests_mock, mocker, capfd): # Test get violation requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_VIOLATION) args = {"violation": "2036"} command = "gamma-get-violation" mock_demisto(mocker, args, command) with capfd.disabled(): main() assert demisto.results.call_args[0][0]["Contents"][0]["violation_id"] == 2036 def test_main_update(requests_mock, mocker, capfd): # Test get violation test_violation = 2036 requests_mock.put(MOCK_URL + f"/api/discovery/v1/violation/{test_violation}", json=MOCK_VIOLATION) requests_mock.get(MOCK_URL + "/api/discovery/v1/violation/list", json=MOCK_VIOLATION) args = {"violation": f"{test_violation}", "status": "RESOLVED", "notes": ""} command = "gamma-update-violation" mock_demisto(mocker, args, command) with capfd.disabled(): main() assert test_violation == demisto.results.call_args[0][0]["Contents"][0]["violation_id"] def test_bad_command(mocker, capfd): test_violation = 2036 args = {"violation": f"{test_violation}", "status": "resolved", "notes": ""} command = "gamma-violation-update" mock_demisto(mocker, args, command) with pytest.raises(SystemExit), capfd.disabled(): main() assert ( demisto.results.call_args[0][0]["Contents"] == "Failed to execute " "gamma-violation-update " "command.\nError:\nCommand " '"gamma-violation-update" is not ' "implemented." )