From: Shane Jaroch Date: Fri, 19 Apr 2024 16:57:06 +0000 (-0400) Subject: cover bugs and arg parse funcs X-Git-Tag: v0.2.8.dev2~24 X-Git-Url: https://git.nutra.tk/v1?a=commitdiff_plain;h=ec3736ef337bc49880b0a805cb8b24bf057b2a68;p=nutratech%2Fcli.git cover bugs and arg parse funcs --- diff --git a/ntclient/argparser/funcs.py b/ntclient/argparser/funcs.py index 8939410..c6e7df4 100644 --- a/ntclient/argparser/funcs.py +++ b/ntclient/argparser/funcs.py @@ -350,34 +350,13 @@ def bug_simulate(args: argparse.Namespace) -> tuple: raise NotImplementedError("This service intentionally raises an error, for testing") -def bugs_list(args: argparse.Namespace) -> tuple: +def bugs_list(args: argparse.Namespace) -> tuple[int, list]: """List bug reports that have been saved""" - rows, _ = ntclient.services.bugs.list_bugs() - n_bugs_total = len(rows) - n_bugs_unsubmitted = len([x for x in rows if not bool(x[-1])]) - - print(f"You have: {n_bugs_total} total bugs amassed in your journey.") - print(f"Of these, {n_bugs_unsubmitted} require submission/reporting.") - print() - - for bug in rows: - if not args.show: - continue - # Skip submitted bugs by default - if bool(bug[-1]) and not args.debug: - continue - # Print all bug properties (except noisy stacktrace) - print(", ".join(str(x) for x in bug if "\n" not in str(x))) - print() - - if n_bugs_unsubmitted > 0: - print("NOTE: You have bugs awaiting submission. Please run the report command") - - return 0, rows + return ntclient.services.bugs.list_bugs(show_all=args.show) # pylint: disable=unused-argument -def bugs_report(args: argparse.Namespace) -> tuple: +def bugs_report(args: argparse.Namespace) -> tuple[int, int]: """Report bugs""" n_submissions = ntclient.services.bugs.submit_bugs() return 0, n_submissions diff --git a/ntclient/services/bugs.py b/ntclient/services/bugs.py index 050d8af..c16373c 100644 --- a/ntclient/services/bugs.py +++ b/ntclient/services/bugs.py @@ -61,30 +61,68 @@ INSERT INTO bug ) if repr(exc) == dupe_bug_insertion_exc: print("INFO: bug report already exists") - else: + else: # pragma: no cover raise -def list_bugs() -> tuple[list, list]: - """List all bugs, with headers.""" - rows, headers, _, _ = sql_nt("SELECT * FROM bug") - return rows, headers +def _list_bugs() -> list: + """List all bugs, with headers as dict keys.""" + rows, _, _, _ = sql_nt("SELECT * FROM bug") + bugs = [dict(x) for x in rows] + return bugs + + +def list_bugs(show_all: bool) -> tuple[int, list]: + """List all bugs, with headers. Returns (exit_code, bugs: list[dict]).""" + + bugs = _list_bugs() + n_bugs_total = len(bugs) + n_bugs_unsubmitted = len([x for x in bugs if not bool(x["submitted"])]) + + print(f"You have: {n_bugs_total} total bugs amassed in your journey.") + print(f"Of these, {n_bugs_unsubmitted} require submission/reporting.") + print() + + for bug in bugs: + if not show_all: + continue + # Skip submitted bugs by default + if bool(bug["submitted"]) and not CLI_CONFIG.debug: + continue + # Print all bug properties (except noisy stacktrace) + print(", ".join(str(x) for x in bug if "\n" not in str(x))) + print() + + if n_bugs_unsubmitted > 0: + print("NOTE: You have bugs awaiting submission. Please run the report command") + return 0, bugs + + +def _list_bugs_unsubmitted() -> list: + """List unsubmitted bugs, with headers as dict keys.""" + rows, _, _, _ = sql_nt("SELECT * FROM bug WHERE submitted = 0") + bugs = [dict(x) for x in rows] + return bugs def submit_bugs() -> int: """Submit bug reports to developer, return n_submitted.""" - # TODO: mock sql_nt() for testing - # Gather bugs for submission - rows, _, _, _ = sql_nt("SELECT * FROM bug WHERE submitted = 0") + bugs = _list_bugs_unsubmitted() + + if len(bugs) == 0: + print("INFO: no unsubmitted bugs found") + return 0 + api_client = ntclient.services.api.ApiClient() n_submitted = 0 - print(f"submitting {len(rows)} bug reports...") - print("_" * len(rows)) + print(f"submitting {len(bugs)} bug reports...") + print("_" * len(bugs)) - for bug in rows: + for bug in bugs: _res = api_client.post_bug(bug) - if CLI_CONFIG.debug: + + if CLI_CONFIG.debug: # pragma: no cover print(_res.json()) # Distinguish bug which are unique vs. duplicates (someone else submitted) @@ -92,7 +130,7 @@ def submit_bugs() -> int: sql_nt("UPDATE bug SET submitted = 1 WHERE id = ?", (bug["id"],)) elif _res.status_code == 204: sql_nt("UPDATE bug SET submitted = 2 WHERE id = ?", (bug["id"],)) - else: + else: # pragma: no cover print("WARN: unknown status [{0}]".format(_res.status_code)) continue @@ -100,5 +138,4 @@ def submit_bugs() -> int: n_submitted += 1 print("submitted: {0} bugs".format(n_submitted)) - return n_submitted diff --git a/tests/services/test_bug.py b/tests/services/test_bug.py index 93b5a69..646bfe1 100644 --- a/tests/services/test_bug.py +++ b/tests/services/test_bug.py @@ -23,14 +23,59 @@ class TestBug(unittest.TestCase): def test_bug_list(self) -> None: """Tests the functions for listing bugs""" - bugs.list_bugs() + exit_code, _bugs = bugs.list_bugs(show_all=True) + + assert exit_code == 0 + assert len(_bugs) >= 0 + # assert len(rows) >= 0 + # assert len(headers) == 11 + + def test_bug_list_unsubmitted(self) -> None: + """Tests the functions for listing unsubmitted bugs""" + with patch( + "ntclient.services.bugs._list_bugs", + return_value=[{"submitted": False}], + ): + exit_code, _bugs = bugs.list_bugs(show_all=False) + + assert exit_code == 0 + assert len(_bugs) == 1 + _bug = _bugs[0] + assert len(_bug.values()) >= 0 + assert len(_bug.keys()) == 1 @patch("ntclient.services.api.cache_mirrors", return_value="https://someurl.com") @patch( "ntclient.services.api.ApiClient.post", return_value=MagicMock(status_code=201), ) + @patch("ntclient.services.bugs._list_bugs_unsubmitted", return_value=[{"id": 1}]) + @patch("ntclient.services.bugs.sql_nt") # pylint: disable=unused-argument def test_bug_report(self, *args: MagicMock) -> None: """Tests the functions for submitting bugs""" bugs.submit_bugs() + + @patch("ntclient.services.api.cache_mirrors", return_value="https://someurl.com") + @patch( + "ntclient.services.api.ApiClient.post", + return_value=MagicMock(status_code=204), + ) + @patch("ntclient.services.bugs._list_bugs_unsubmitted", return_value=[{"id": 1}]) + @patch("ntclient.services.bugs.sql_nt") + # pylint: disable=unused-argument + def test_bug_report_on_204_status(self, *args: MagicMock) -> None: + """Tests the functions for submitting bugs""" + bugs.submit_bugs() + + @patch("ntclient.services.api.cache_mirrors", return_value="https://someurl.com") + @patch( + "ntclient.services.api.ApiClient.post", + return_value=MagicMock(status_code=201), + ) + @patch("ntclient.services.bugs._list_bugs_unsubmitted", return_value=[]) + # pylint: disable=unused-argument + def test_bug_report_empty_list(self, *args: MagicMock) -> None: + """Tests the functions for submitting bugs""" + result = bugs.submit_bugs() + assert result == 0 diff --git a/tests/test_cli.py b/tests/test_cli.py index 9e49710..b292a2e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -292,6 +292,11 @@ class TestCli(unittest.TestCase): assert code == 0 assert isinstance(result, list) + args = arg_parser.parse_args(args="bug report".split()) + code, result = args.func(args) + assert code == 0 + assert isinstance(result, int) + def test_415_invalid_path_day_throws_error(self): """Ensures invalid path throws exception in `day` subcommand""" invalid_day_csv_path = os.path.join(