From bdb63c2ed1bc43331ca9244c4fa8c081de53d25d Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 1 Sep 2022 11:19:45 -0700 Subject: [PATCH 1/2] Fix some e2e tests Current status 1. publish_samples fails with permissions error on project? 2. extracts tests fail b/c the workbooks use an MS Access connection --- tabcmd/commands/group/delete_group_command.py | 2 +- tabcmd/commands/server.py | 25 +++--- .../user/delete_site_users_command.py | 2 +- tabcmd/commands/user/user_data.py | 31 +++++-- tests/e2e/online_tests.py | 83 +++++++++---------- 5 files changed, 75 insertions(+), 68 deletions(-) diff --git a/tabcmd/commands/group/delete_group_command.py b/tabcmd/commands/group/delete_group_command.py index 01a8a4b5..6d2741f1 100644 --- a/tabcmd/commands/group/delete_group_command.py +++ b/tabcmd/commands/group/delete_group_command.py @@ -27,7 +27,7 @@ def run_command(args): server = session.create_session(args) try: logger.info(_("tabcmd.find.group").format(args.name)) - group_id = Server.find_group_id(logger, server, args.name) + group_id = Server.find_group(logger, server, args.name).id logger.info(_("deletegroup.status").format(group_id)) server.groups.delete(group_id) logger.info(_("common.output.succeeded")) diff --git a/tabcmd/commands/server.py b/tabcmd/commands/server.py index 09fa965c..cf3700cf 100644 --- a/tabcmd/commands/server.py +++ b/tabcmd/commands/server.py @@ -39,18 +39,12 @@ def find_group(logger, server, group_name): Errors.exit_with_error(logger, exception=e) @staticmethod - def find_group_id(logger, server, group_name): - return Server.find_group(logger, server, group_name).id + def find_user(logger, server, username): + return Server.get_items_by_name(logger, server.users, username)[0] @staticmethod - def find_user_id(logger, server, username): - try: - return Server.get_items_by_name(logger, server.users, username)[0].id - except Exception as e: - Errors.exit_with_error(logger, exception=e) - - @staticmethod - def get_items_by_name(logger, item_endpoint, item_name: str, container: TSC.ProjectItem = None): + def get_items_by_name(logger, item_endpoint, item_name: str, container: TSC.ProjectItem = None) -> List: + # TODO: typing should reflect that this returns TSC.TableauItem and item_endpoint is of type TSC.QuerysetEndpoint[same] item_type = type(item_endpoint).__name__ item_log_name: str = "[" + item_type + "] " + item_name if container: @@ -58,10 +52,13 @@ def get_items_by_name(logger, item_endpoint, item_name: str, container: TSC.Proj logger.debug(_("export.status").format(item_log_name)) req_option = TSC.RequestOptions() req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, item_name)) - all_items, pagination_item = item_endpoint.get(req_option) if all_items is None or all_items == []: - raise ValueError("[" + item_type + "] " + _("errors.xmlapi.not_found")) + raise TSC.ServerResponseError( + code=404, + summary=_("errors.xmlapi.not_found"), + detail=_("errors.xmlapi.not_found") + ": " + item_log_name, + ) if len(all_items) == 1: logger.debug("Exactly one result found") result = all_items @@ -120,7 +117,7 @@ def get_project_by_name_and_parent_path(logger, server, project_name: str, paren if not parent_path: if not project_name: project_name = "Default" - project: TSC.ProjectItem = Server.get_items_by_name(logger, server.projects, project_name, None) + project: TSC.ProjectItem = Server.get_items_by_name(logger, server.projects, project_name, None)[0] return project project_tree: List[str] = Server._parse_project_path_to_list(parent_path) @@ -129,7 +126,9 @@ def get_project_by_name_and_parent_path(logger, server, project_name: str, paren return project parent = Server._get_parent_project_from_tree(logger, server, project_tree) + logger.debug(parent) project = Server._get_project_by_name_and_parent(logger, server, project_name, parent) + logger.debug(project) if not project: Errors.exit_with_error(logger, message=_("publish.errors.server_resource_not_found")) return project diff --git a/tabcmd/commands/user/delete_site_users_command.py b/tabcmd/commands/user/delete_site_users_command.py index 7f46a311..aa749a5a 100644 --- a/tabcmd/commands/user/delete_site_users_command.py +++ b/tabcmd/commands/user/delete_site_users_command.py @@ -42,7 +42,7 @@ def run_command(args): for user_obj in user_obj_list: logger.info(_("importcsvsummary.line.processed").format(number_of_users_deleted)) try: - user_id = UserCommand.find_user_id(logger, server, user_obj.name) + user_id = UserCommand.find_user(logger, server, user_obj.name).id server.users.remove(user_id) logger.debug(_("tabcmd.result.success.delete_user").format(user_obj.name, user_id)) number_of_users_deleted += 1 diff --git a/tabcmd/commands/user/user_data.py b/tabcmd/commands/user/user_data.py index ed7082c4..f8c088f7 100644 --- a/tabcmd/commands/user/user_data.py +++ b/tabcmd/commands/user/user_data.py @@ -229,17 +229,25 @@ def act_on_users( logger.debug(_("importcsvsummary.line.processed").format(n_users_listed)) error_list = [] + line_no = 0 user_obj_list: List[TSC.UserItem] = UserCommand.get_users_from_file(args.users) logger.debug(_("tabcmd.result.success.parsed_users").format(len(user_obj_list))) for user_obj in user_obj_list: - username: str = user_obj.name or "unknown user" + line_no += 1 + if not user_obj.name: + number_of_errors += 1 + error_list.append(_("importcsvsummary.error.line").format(line_no, "No username", "")) + continue + try: - user_id: str = UserCommand.find_user_id(logger, server, username) + username: str = user_obj.name + user_id: str = UserCommand.find_user(logger, server, username).id logger.debug("{} user {} ({})".format(action_name, username, user_id)) except TSC.ServerResponseError as e: - Errors.check_common_error_codes_and_explain(logger, e) number_of_errors += 1 - error_list.append(e) + error_list.append( + _("importcsvsummary.error.line").format(line_no, username, "{}: {}".format(e.code, e.detail)) + ) logger.debug(_("tabcmd.result.failure.user").format(username)) continue @@ -248,11 +256,20 @@ def act_on_users( n_users_handled += 1 logger.info(_("tabcmd.result.success.user_actions").format(action_name, username, group)) except TSC.ServerResponseError as e: - Errors.check_common_error_codes_and_explain(logger, e) number_of_errors += 1 - error_list.append(e) + error_list.append( + _("importcsvsummary.error.line").format(line_no, username, "{}: {}".format(e.code, e.detail)) + ) logger.info(_("session.monitorjob.percent_complete").format(100)) logger.info(_("importcsvsummary.errors.count").format(number_of_errors)) if number_of_errors > 0: - logger.info(_("importcsvsummary.error.details").format(error_list)) + i = 0 + max_printing = 5 + logger.info(_("importcsvsummary.error.details")) + while i < number_of_errors and i < max_printing: + logger.info(error_list[i]) + i += 1 + if number_of_errors > max_printing: + logger.info(_("importcsvsummary.error.too_many_errors")) + logger.info(_("importcsvsummary.remainingerrors")) diff --git a/tests/e2e/online_tests.py b/tests/e2e/online_tests.py index cb391e29..68f02fcd 100644 --- a/tests/e2e/online_tests.py +++ b/tests/e2e/online_tests.py @@ -51,10 +51,9 @@ def setup_class(cls): def _create_project(self, project_name, parent_path=None): command = "createproject" arguments = [command, "--name", project_name] - if parent_path or parent_location: + if parent_path: arguments.append("--parent-project-path") - arguments.append(parent_path or parent_location) - print(arguments) + arguments.append(parent_path) _test_command(arguments) def _delete_project(self, project_name, parent_path=None): @@ -136,7 +135,7 @@ def test_login(self): @pytest.mark.order(1) def test_version(self): - command = "" + command = "-v" arguments = [command] _test_command(arguments) @@ -147,7 +146,7 @@ def test_help(self): _test_command(arguments) @pytest.mark.order(2) - def test_create_site_users(self): + def test_users_create_site_users(self): if not server_admin and not site_admin: pytest.skip("Must be server or site administrator to create site users") command = "createsiteusers" @@ -156,7 +155,7 @@ def test_create_site_users(self): _test_command(arguments) @pytest.mark.order(3) - def test_creategroup(self): + def test_group_creategroup(self): if not server_admin and not site_admin: pytest.skip("Must be server or site administrator to create groups") groupname = group_name @@ -165,7 +164,7 @@ def test_creategroup(self): _test_command(arguments) @pytest.mark.order(4) - def test_add_users_to_group(self): + def test_users_add_to_group(self): if not server_admin and not site_admin: pytest.skip("Must be server or site administrator to add to groups") @@ -176,7 +175,7 @@ def test_add_users_to_group(self): _test_command(arguments) @pytest.mark.order(5) - def test_remove_users_to_group(self): + def test_users_remove_from_group(self): if not server_admin and not site_admin: pytest.skip("Must be server or site administrator to remove from groups") @@ -187,7 +186,7 @@ def test_remove_users_to_group(self): _test_command(arguments) @pytest.mark.order(6) - def test_deletegroup(self): + def test_group_deletegroup(self): if not server_admin and not site_admin: pytest.skip("Must be server or site administrator to delete groups") @@ -198,9 +197,12 @@ def test_deletegroup(self): @pytest.mark.order(8) def test_create_projects(self): - if not project_admin: pytest.skip("Must be project administrator to create projects") + + # project 1 + self._create_project(parent_location) + time.sleep(indexing_sleep_time) # project 1 self._create_project(project_name) time.sleep(indexing_sleep_time) @@ -216,58 +218,53 @@ def test_create_projects(self): def test_list_projects(self): self._list("projects") - @pytest.mark.order(9) + """ + @pytest.mark.order(9) + def test_publish_samples(self): + self._publish_samples(project_name) + """ + + @pytest.mark.order(10) def test_delete_projects(self): if not project_admin: pytest.skip("Must be project administrator to create projects") self._delete_project("project_name_2", project_name) # project 2 self._delete_project(project_name) - @pytest.mark.order(9) - def test_publish_samples(self): - self._publish_samples(project_name) - @pytest.mark.order(10) - def test_publish(self): + def test_wb_publish(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) self._publish_wb(file, name_on_server) @pytest.mark.order(10) - def test__get_wb(self): - wb_name_on_server = OnlineCommandTest.TWBX_WITHOUT_EXTRACT_NAME - self._get_workbook(wb_name_on_server + ".twbx") + def test_wb_get(self): + self._get_workbook(OnlineCommandTest.TWBX_WITH_EXTRACT_NAME + ".twbx") @pytest.mark.order(10) - def test__get_wb(self): + def test_view_get_pdf(self): wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME - self._get_workbook(wb_name_on_server + ".twbx") - - @pytest.mark.order(10) - def test__get_view(self): - wb_name_on_server = OnlineCommandTest.TWBX_WITHOUT_EXTRACT_NAME - sheet_name = OnlineCommandTest.TWBX_WITHOUT_EXTRACT_SHEET + sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET self._get_view(wb_name_on_server, sheet_name + ".pdf") @pytest.mark.order(10) - def test__get_view_csv(self): + def test_view_get_csv(self): wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET self._get_view(wb_name_on_server, sheet_name + ".csv") @pytest.mark.order(10) - def test__get_view_png(self): + def test_view_get_png(self): wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET self._get_view(wb_name_on_server, sheet_name + ".png") - @pytest.mark.order(11) - def test__delete_wb(self): + def test_wb_delete(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME self._delete_wb(name_on_server) @pytest.mark.order(12) - def test_delete_extract(self): + def test_extract_delete(self): # fails because the extract has a bad data connection :/ name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) @@ -275,30 +272,24 @@ def test_delete_extract(self): self._delete_extract(name_on_server) @pytest.mark.order(13) - def test_create_extract(self): + def test_extract_create(self): # Fails because it 'already has an extract' :/ name_on_server = OnlineCommandTest.TWBX_WITHOUT_EXTRACT_NAME self._create_extract(name_on_server) @pytest.mark.order(14) - def test_refresh_extract(self): + def test_extract_refresh(self): # must be a datasource owned by the test user + name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME + file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) + self._publish_wb(file, name_on_server) + name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME self._refresh_extract(name_on_server) self._delete_wb(name_on_server) - def test_version(self): - _test_command(["-v"]) - - def test_help(self): - _test_command(["help"]) - - # this just gets in the way :( - # def test_logout(self): - # _test_command(["logout"]) - @pytest.mark.order(15) - def test_export_wb(self): + def test_export_wb_pdf(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) self._publish_wb(file, name_on_server) @@ -308,7 +299,7 @@ def test_export_wb(self): _test_command(arguments) @pytest.mark.order(15) - def test_export_view(self): + def test_export_view_pdf(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME file = os.path.join("tests", "assets", OnlineCommandTest.TWBX_FILE_WITH_EXTRACT) self._publish_wb(file, name_on_server) @@ -318,7 +309,7 @@ def test_export_view(self): _test_command(arguments) @pytest.mark.order(16) - def test_delete_site_users(self): + def test_users_delete_site_users(self): if not server_admin and not site_admin: pytest.skip("Must be server or site administrator to delete site users") From 985cfb2726b9ec5becbeae88a425a9b68ce660fc Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 1 Sep 2022 16:12:57 -0700 Subject: [PATCH 2/2] formatting --- tests/e2e/online_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/online_tests.py b/tests/e2e/online_tests.py index 68f02fcd..a1ab9d2e 100644 --- a/tests/e2e/online_tests.py +++ b/tests/e2e/online_tests.py @@ -258,6 +258,7 @@ def test_view_get_png(self): wb_name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME sheet_name = OnlineCommandTest.TWBX_WITH_EXTRACT_SHEET self._get_view(wb_name_on_server, sheet_name + ".png") + @pytest.mark.order(11) def test_wb_delete(self): name_on_server = OnlineCommandTest.TWBX_WITH_EXTRACT_NAME