Skip to content

Commit 516c2f1

Browse files
handle custom exceptions in cases (#222)
1 parent 18f0082 commit 516c2f1

File tree

6 files changed

+127
-3
lines changed

6 files changed

+127
-3
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ how a consumer would use the library (e.g. adding unit tests, updating documenta
1010

1111
## Unreleased
1212

13+
### Changed
14+
15+
- The error text in cases command when:
16+
- `cases create` sets a name that already exists in the system.
17+
- `cases create` sets a description that has more than 250 characters.
18+
- `cases update` sets a description that has more than 250 characters.
19+
- `cases file-events add` is performed on an already closed case.
20+
- `cases file-events add` sets an event id that is already added to the case.
21+
- `cases file-events remove` is performed on an already closed case.
22+
1323
### Added
1424

1525
- New choice `TLS-TCP` for `--protocol` option used by `send-to` commands:

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"keyring==18.0.1",
3838
"keyrings.alt==3.2.0",
3939
"pandas>=1.1.3",
40-
"py42>=1.11",
40+
"py42>=1.11.1",
4141
],
4242
extras_require={
4343
"dev": [

src/code42cli/click_ext/groups.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
from collections import OrderedDict
44

55
import click
6+
from py42.exceptions import Py42CaseAlreadyHasEventError
7+
from py42.exceptions import Py42CaseNameExistsError
8+
from py42.exceptions import Py42DescriptionLimitExceededError
69
from py42.exceptions import Py42ForbiddenError
710
from py42.exceptions import Py42HTTPError
811
from py42.exceptions import Py42InvalidRuleOperationError
912
from py42.exceptions import Py42LegalHoldNotFoundOrPermissionDeniedError
13+
from py42.exceptions import Py42UpdateClosedCaseError
1014
from py42.exceptions import Py42UserAlreadyAddedError
1115
from py42.exceptions import Py42UserNotOnListError
1216

@@ -59,6 +63,10 @@ def invoke(self, ctx):
5963
Py42InvalidRuleOperationError,
6064
Py42LegalHoldNotFoundOrPermissionDeniedError,
6165
SyslogServerNetworkConnectionError,
66+
Py42CaseNameExistsError,
67+
Py42DescriptionLimitExceededError,
68+
Py42CaseAlreadyHasEventError,
69+
Py42UpdateClosedCaseError,
6270
) as err:
6371
self.logger.log_error(err)
6472
raise Code42CLIError(str(err))

src/code42cli/cmds/cases.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import click
55
from py42.clients.cases import CaseStatus
66
from py42.exceptions import Py42BadRequestError
7+
from py42.exceptions import Py42CaseAlreadyHasEventError
78
from py42.exceptions import Py42NotFoundError
9+
from py42.exceptions import Py42UpdateClosedCaseError
810

911
from code42cli.click_ext.groups import OrderedGroup
1012
from code42cli.errors import Code42CLIError
@@ -241,6 +243,10 @@ def add(state, case_number, event_id):
241243
"""Associate a file event to a case, by event ID."""
242244
try:
243245
state.sdk.cases.file_events.add(case_number, event_id)
246+
except Py42UpdateClosedCaseError:
247+
raise
248+
except Py42CaseAlreadyHasEventError:
249+
raise
244250
except Py42BadRequestError:
245251
raise Code42CLIError("Invalid case-number or event-id.")
246252

tests/cmds/conftest.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,17 @@ def cli_state_without_user(sdk_without_user, cli_state):
7272

7373

7474
@pytest.fixture
75-
def user_already_added_error(mocker):
75+
def custom_error(mocker):
7676
err = mocker.MagicMock(spec=HTTPError)
7777
resp = mocker.MagicMock(spec=Response)
7878
resp.text = "TEST_ERR"
7979
err.response = resp
80-
return Py42UserAlreadyAddedError(err, TEST_ID, "detection list")
80+
return err
81+
82+
83+
@pytest.fixture
84+
def user_already_added_error(custom_error):
85+
return Py42UserAlreadyAddedError(custom_error, TEST_ID, "detection list")
8186

8287

8388
def get_filter_value_from_json(json, filter_index):

tests/cmds/test_cases.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55

66
import pytest
77
from py42.exceptions import Py42BadRequestError
8+
from py42.exceptions import Py42CaseAlreadyHasEventError
9+
from py42.exceptions import Py42CaseNameExistsError
10+
from py42.exceptions import Py42DescriptionLimitExceededError
811
from py42.exceptions import Py42NotFoundError
12+
from py42.exceptions import Py42UpdateClosedCaseError
913
from py42.response import Py42Response
1014

1115
from code42cli.main import cli
@@ -51,6 +55,26 @@ def py42_response(mocker):
5155
return mocker.MagicMock(spec=Py42Response)
5256

5357

58+
@pytest.fixture
59+
def case_already_exists_error(custom_error):
60+
return Py42CaseNameExistsError(custom_error, "test case")
61+
62+
63+
@pytest.fixture
64+
def case_description_limit_exceeded_error(custom_error):
65+
return Py42DescriptionLimitExceededError(custom_error)
66+
67+
68+
@pytest.fixture
69+
def case_already_has_event_error(custom_error):
70+
return Py42CaseAlreadyHasEventError(custom_error)
71+
72+
73+
@pytest.fixture
74+
def update_on_a_closed_case_error(custom_error):
75+
return Py42UpdateClosedCaseError(custom_error)
76+
77+
5478
def test_create_calls_create_with_expected_params(runner, cli_state):
5579
runner.invoke(
5680
cli, ["cases", "create", "TEST_CASE"], obj=cli_state,
@@ -333,3 +357,74 @@ def test_file_events_list_when_missing_case_number_prints_error(runner, cli_stat
333357
result = runner.invoke(cli, command, obj=cli_state)
334358
assert result.exit_code == 2
335359
assert MISSING_CASE_NUMBER_ARG in result.output
360+
361+
362+
def test_cases_create_when_case_name_already_exists_raises_exception_prints_error_message(
363+
runner, cli_state, case_already_exists_error
364+
):
365+
cli_state.sdk.cases.create.side_effect = case_already_exists_error
366+
result = runner.invoke(cli, ["cases", "create", "test case"], obj=cli_state,)
367+
assert (
368+
"Case name 'test case' already exists, please set another name" in result.output
369+
)
370+
371+
372+
def test_cases_create_when_description_length_limit_exceeds_raises_exception_prints_error_message(
373+
runner, cli_state, case_description_limit_exceeded_error
374+
):
375+
cli_state.sdk.cases.create.side_effect = case_description_limit_exceeded_error
376+
result = runner.invoke(
377+
cli,
378+
["cases", "create", "test case", "--description", "too long"],
379+
obj=cli_state,
380+
)
381+
assert "Description limit exceeded, max 250 characters allowed." in result.output
382+
383+
384+
def test_cases_udpate_when_description_length_limit_exceeds_raises_exception_prints_error_message(
385+
runner, cli_state, case_description_limit_exceeded_error
386+
):
387+
cli_state.sdk.cases.update.side_effect = case_description_limit_exceeded_error
388+
result = runner.invoke(
389+
cli, ["cases", "update", "1", "--description", "too long"], obj=cli_state,
390+
)
391+
assert "Description limit exceeded, max 250 characters allowed." in result.output
392+
393+
394+
def test_fileevents_add_on_closed_case_when_py42_raises_exception_prints_error_message(
395+
runner, cli_state, update_on_a_closed_case_error
396+
):
397+
cli_state.sdk.cases.file_events.add.side_effect = update_on_a_closed_case_error
398+
result = runner.invoke(
399+
cli,
400+
["cases", "file-events", "add", "--case-number", "1", "--event-id", "1"],
401+
obj=cli_state,
402+
)
403+
cli_state.sdk.cases.file_events.add.assert_called_once_with(1, "1")
404+
assert "Cannot update a closed case." in result.output
405+
406+
407+
def test_fileevents_remove_on_closed_case_when_py42_raises_exception_prints_error_message(
408+
runner, cli_state, update_on_a_closed_case_error
409+
):
410+
cli_state.sdk.cases.file_events.delete.side_effect = update_on_a_closed_case_error
411+
result = runner.invoke(
412+
cli,
413+
["cases", "file-events", "remove", "--case-number", "1", "--event-id", "1"],
414+
obj=cli_state,
415+
)
416+
cli_state.sdk.cases.file_events.delete.assert_called_once_with(1, "1")
417+
assert "Cannot update a closed case." in result.output
418+
419+
420+
def test_fileevents_when_event_id_is_already_associated_with_case_py42_raises_exception_prints_error_message(
421+
runner, cli_state, case_already_has_event_error
422+
):
423+
cli_state.sdk.cases.file_events.add.side_effect = case_already_has_event_error
424+
result = runner.invoke(
425+
cli,
426+
["cases", "file-events", "add", "--case-number", "1", "--event-id", "1"],
427+
obj=cli_state,
428+
)
429+
cli_state.sdk.cases.file_events.add.assert_called_once_with(1, "1")
430+
assert "Event is already associated to the case." in result.output

0 commit comments

Comments
 (0)