From 10613091d3da1b178ed6dab8b006d1cb62756789 Mon Sep 17 00:00:00 2001 From: Jordan Woods <13803242+jorwoods@users.noreply.github.com> Date: Thu, 20 Nov 2025 22:13:28 -0600 Subject: [PATCH 1/2] fix: black ci errors --- test/test_datasource.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_datasource.py b/test/test_datasource.py index 7f4cca75..56eb11ab 100644 --- a/test/test_datasource.py +++ b/test/test_datasource.py @@ -895,7 +895,8 @@ def test_publish_description(server: TSC.Server) -> None: ds_elem = body.find(".//datasource") assert ds_elem is not None assert ds_elem.attrib["description"] == "Sample description" - + + def test_get_datasource_no_owner(server: TSC.Server) -> None: with requests_mock.mock() as m: m.get(server.datasources.baseurl, text=GET_NO_OWNER.read_text()) From 976e1f105696bf5c6570c59b264b78b35ca58e60 Mon Sep 17 00:00:00 2001 From: Jordan Woods <13803242+jorwoods@users.noreply.github.com> Date: Sun, 9 Nov 2025 22:29:00 -0600 Subject: [PATCH 2/2] chore: pytestify project --- test/test_project.py | 837 +++++++++++++++++++------------------ test/test_project_model.py | 31 +- 2 files changed, 439 insertions(+), 429 deletions(-) diff --git a/test/test_project.py b/test/test_project.py index c51f2e1e..f2cfab5d 100644 --- a/test/test_project.py +++ b/test/test_project.py @@ -1,438 +1,447 @@ -import os -import unittest +from pathlib import Path +import pytest import requests_mock import tableauserverclient as TSC from tableauserverclient import GroupItem -from ._utils import read_xml_asset, asset - -TEST_ASSET_DIR = os.path.join(os.path.dirname(__file__), "assets") - -GET_XML = asset("project_get.xml") -GET_XML_ALL_FIELDS = asset("project_get_all_fields.xml") -UPDATE_XML = asset("project_update.xml") -SET_CONTENT_PERMISSIONS_XML = asset("project_content_permission.xml") -CREATE_XML = asset("project_create.xml") -POPULATE_PERMISSIONS_XML = "project_populate_permissions.xml" -POPULATE_WORKBOOK_DEFAULT_PERMISSIONS_XML = "project_populate_workbook_default_permissions.xml" -UPDATE_DATASOURCE_DEFAULT_PERMISSIONS_XML = "project_update_datasource_default_permissions.xml" -POPULATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML = "project_populate_virtualconnection_default_permissions.xml" -UPDATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML = "project_update_virtualconnection_default_permissions.xml" - - -class ProjectTests(unittest.TestCase): - def setUp(self) -> None: - self.server = TSC.Server("http://test", False) - - # Fake signin - self.server._site_id = "dad65087-b08b-4603-af4e-2887b8aafc67" - self.server._auth_token = "j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM" - - self.baseurl = self.server.projects.baseurl - - def test_get(self) -> None: - with open(GET_XML, "rb") as f: - response_xml = f.read().decode("utf-8") - with requests_mock.mock() as m: - m.get(self.baseurl, text=response_xml) - all_projects, pagination_item = self.server.projects.get() - - self.assertEqual(3, pagination_item.total_available) - self.assertEqual("ee8c6e70-43b6-11e6-af4f-f7b0d8e20760", all_projects[0].id) - self.assertEqual("default", all_projects[0].name) - self.assertEqual("The default project that was automatically created by Tableau.", all_projects[0].description) - self.assertEqual("ManagedByOwner", all_projects[0].content_permissions) - self.assertEqual(None, all_projects[0].parent_id) - self.assertEqual("dd2239f6-ddf1-4107-981a-4cf94e415794", all_projects[0].owner_id) - - self.assertEqual("1d0304cd-3796-429f-b815-7258370b9b74", all_projects[1].id) - self.assertEqual("Tableau", all_projects[1].name) - self.assertEqual("ManagedByOwner", all_projects[1].content_permissions) - self.assertEqual(None, all_projects[1].parent_id) - self.assertEqual("2a47bbf8-8900-4ebb-b0a4-2723bd7c46c3", all_projects[1].owner_id) - - self.assertEqual("4cc52973-5e3a-4d1f-a4fb-5b5f73796edf", all_projects[2].id) - self.assertEqual("Tableau > Child 1", all_projects[2].name) - self.assertEqual("ManagedByOwner", all_projects[2].content_permissions) - self.assertEqual("1d0304cd-3796-429f-b815-7258370b9b74", all_projects[2].parent_id) - self.assertEqual("dd2239f6-ddf1-4107-981a-4cf94e415794", all_projects[2].owner_id) - - def test_get_before_signin(self) -> None: - self.server._auth_token = None - self.assertRaises(TSC.NotSignedInError, self.server.projects.get) - - def test_delete(self) -> None: - with requests_mock.mock() as m: - m.delete(self.baseurl + "/ee8c6e70-43b6-11e6-af4f-f7b0d8e20760", status_code=204) - self.server.projects.delete("ee8c6e70-43b6-11e6-af4f-f7b0d8e20760") - - def test_delete_missing_id(self) -> None: - self.assertRaises(ValueError, self.server.projects.delete, "") - - def test_update(self) -> None: - with open(UPDATE_XML, "rb") as f: - response_xml = f.read().decode("utf-8") - with requests_mock.mock() as m: - m.put(self.baseurl + "/1d0304cd-3796-429f-b815-7258370b9b74", text=response_xml) - single_project = TSC.ProjectItem( - name="Test Project", - content_permissions="LockedToProject", - description="Project created for testing", - parent_id="9a8f2265-70f3-4494-96c5-e5949d7a1120", - ) - single_project._id = "1d0304cd-3796-429f-b815-7258370b9b74" - single_project.owner_id = "dd2239f6-ddf1-4107-981a-4cf94e415794" - single_project = self.server.projects.update(single_project) - - self.assertEqual("1d0304cd-3796-429f-b815-7258370b9b74", single_project.id) - self.assertEqual("Test Project", single_project.name) - self.assertEqual("Project created for testing", single_project.description) - self.assertEqual("LockedToProject", single_project.content_permissions) - self.assertEqual("9a8f2265-70f3-4494-96c5-e5949d7a1120", single_project.parent_id) - self.assertEqual("dd2239f6-ddf1-4107-981a-4cf94e415794", single_project.owner_id) - - def test_content_permission_locked_to_project_without_nested(self) -> None: - with open(SET_CONTENT_PERMISSIONS_XML, "rb") as f: - response_xml = f.read().decode("utf-8") - with requests_mock.mock() as m: - m.put(self.baseurl + "/cb3759e5-da4a-4ade-b916-7e2b4ea7ec86", text=response_xml) - project_item = TSC.ProjectItem( - name="Test Project Permissions", - content_permissions="LockedToProjectWithoutNested", - description="Project created for testing", - parent_id="7687bc43-a543-42f3-b86f-80caed03a813", - ) - project_item._id = "cb3759e5-da4a-4ade-b916-7e2b4ea7ec86" - project_item = self.server.projects.update(project_item) - self.assertEqual("cb3759e5-da4a-4ade-b916-7e2b4ea7ec86", project_item.id) - self.assertEqual("Test Project Permissions", project_item.name) - self.assertEqual("Project created for testing", project_item.description) - self.assertEqual("LockedToProjectWithoutNested", project_item.content_permissions) - self.assertEqual("7687bc43-a543-42f3-b86f-80caed03a813", project_item.parent_id) - - def test_update_datasource_default_permission(self) -> None: - response_xml = read_xml_asset(UPDATE_DATASOURCE_DEFAULT_PERMISSIONS_XML) - with requests_mock.mock() as m: - m.put( - self.baseurl + "/b4065286-80f0-11ea-af1b-cb7191f48e45/default-permissions/datasources", - text=response_xml, - ) - project = TSC.ProjectItem("test-project") - project._id = "b4065286-80f0-11ea-af1b-cb7191f48e45" - - group = TSC.GroupItem("test-group") - group._id = "b4488bce-80f0-11ea-af1c-976d0c1dab39" - - capabilities = {TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny} - - rules = [TSC.PermissionsRule(grantee=GroupItem.as_reference(group._id), capabilities=capabilities)] - - new_rules = self.server.projects.update_datasource_default_permissions(project, rules) - - self.assertEqual("b4488bce-80f0-11ea-af1c-976d0c1dab39", new_rules[0].grantee.id) - - updated_capabilities = new_rules[0].capabilities - self.assertEqual(4, len(updated_capabilities)) - self.assertEqual("Deny", updated_capabilities["ExportXml"]) - self.assertEqual("Allow", updated_capabilities["Read"]) - self.assertEqual("Allow", updated_capabilities["Write"]) - self.assertEqual("Allow", updated_capabilities["Connect"]) - - def test_update_missing_id(self) -> None: - single_project = TSC.ProjectItem("test") - self.assertRaises(TSC.MissingRequiredFieldError, self.server.projects.update, single_project) - - def test_create(self) -> None: - with open(CREATE_XML, "rb") as f: - response_xml = f.read().decode("utf-8") - with requests_mock.mock() as m: - m.post(self.baseurl, text=response_xml) - new_project = TSC.ProjectItem(name="Test Project", description="Project created for testing") - new_project.content_permissions = "ManagedByOwner" - new_project.parent_id = "9a8f2265-70f3-4494-96c5-e5949d7a1120" - new_project = self.server.projects.create(new_project) - - self.assertEqual("ccbea03f-77c4-4209-8774-f67bc59c3cef", new_project.id) - self.assertEqual("Test Project", new_project.name) - self.assertEqual("Project created for testing", new_project.description) - self.assertEqual("ManagedByOwner", new_project.content_permissions) - self.assertEqual("9a8f2265-70f3-4494-96c5-e5949d7a1120", new_project.parent_id) - - def test_create_missing_name(self) -> None: - TSC.ProjectItem() - - def test_populate_permissions(self) -> None: - with open(asset(POPULATE_PERMISSIONS_XML), "rb") as f: - response_xml = f.read().decode("utf-8") - with requests_mock.mock() as m: - m.get(self.baseurl + "/0448d2ed-590d-4fa0-b272-a2a8a24555b5/permissions", text=response_xml) - single_project = TSC.ProjectItem("Project3") - single_project._id = "0448d2ed-590d-4fa0-b272-a2a8a24555b5" - - self.server.projects.populate_permissions(single_project) - permissions = single_project.permissions - - self.assertEqual(permissions[0].grantee.tag_name, "group") - self.assertEqual(permissions[0].grantee.id, "c8f2773a-c83a-11e8-8c8f-33e6d787b506") - self.assertDictEqual( - permissions[0].capabilities, - { - TSC.Permission.Capability.Write: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Read: TSC.Permission.Mode.Allow, - }, - ) - - def test_populate_workbooks(self) -> None: - response_xml = read_xml_asset(POPULATE_WORKBOOK_DEFAULT_PERMISSIONS_XML) - with requests_mock.mock() as m: - m.get( - self.baseurl + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/workbooks", text=response_xml - ) - single_project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") - single_project.owner_id = "dd2239f6-ddf1-4107-981a-4cf94e415794" - single_project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" - - self.server.projects.populate_workbook_default_permissions(single_project) - permissions = single_project.default_workbook_permissions - - rule1 = permissions.pop() - - self.assertEqual("c8f2773a-c83a-11e8-8c8f-33e6d787b506", rule1.grantee.id) - self.assertEqual("group", rule1.grantee.tag_name) - self.assertDictEqual( - rule1.capabilities, - { - TSC.Permission.Capability.Write: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Read: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Filter: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ChangePermissions: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.WebAuthoring: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ExportImage: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny, - TSC.Permission.Capability.ShareView: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ViewUnderlyingData: TSC.Permission.Mode.Deny, - TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.AddComment: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Allow, - }, + +TEST_ASSET_DIR = Path(__file__).parent / "assets" + +GET_XML = TEST_ASSET_DIR / "project_get.xml" +GET_XML_ALL_FIELDS = TEST_ASSET_DIR / "project_get_all_fields.xml" +UPDATE_XML = TEST_ASSET_DIR / "project_update.xml" +SET_CONTENT_PERMISSIONS_XML = TEST_ASSET_DIR / "project_content_permission.xml" +CREATE_XML = TEST_ASSET_DIR / "project_create.xml" +POPULATE_PERMISSIONS_XML = TEST_ASSET_DIR / "project_populate_permissions.xml" +POPULATE_WORKBOOK_DEFAULT_PERMISSIONS_XML = TEST_ASSET_DIR / "project_populate_workbook_default_permissions.xml" +UPDATE_DATASOURCE_DEFAULT_PERMISSIONS_XML = TEST_ASSET_DIR / "project_update_datasource_default_permissions.xml" +POPULATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML = ( + TEST_ASSET_DIR / "project_populate_virtualconnection_default_permissions.xml" +) +UPDATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML = ( + TEST_ASSET_DIR / "project_update_virtualconnection_default_permissions.xml" +) + + +@pytest.fixture(scope="function") +def server(): + """Fixture to create a TSC.Server instance for testing.""" + server = TSC.Server("http://test", False) + + # Fake signin + server._site_id = "dad65087-b08b-4603-af4e-2887b8aafc67" + server._auth_token = "j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM" + + return server + + +def test_get(server: TSC.Server) -> None: + response_xml = GET_XML.read_text() + with requests_mock.mock() as m: + m.get(server.projects.baseurl, text=response_xml) + all_projects, pagination_item = server.projects.get() + + assert 3 == pagination_item.total_available + assert "ee8c6e70-43b6-11e6-af4f-f7b0d8e20760" == all_projects[0].id + assert "default" == all_projects[0].name + assert "The default project that was automatically created by Tableau." == all_projects[0].description + assert "ManagedByOwner" == all_projects[0].content_permissions + assert None == all_projects[0].parent_id + assert "dd2239f6-ddf1-4107-981a-4cf94e415794" == all_projects[0].owner_id + + assert "1d0304cd-3796-429f-b815-7258370b9b74" == all_projects[1].id + assert "Tableau" == all_projects[1].name + assert "ManagedByOwner" == all_projects[1].content_permissions + assert None == all_projects[1].parent_id + assert "2a47bbf8-8900-4ebb-b0a4-2723bd7c46c3" == all_projects[1].owner_id + + assert "4cc52973-5e3a-4d1f-a4fb-5b5f73796edf" == all_projects[2].id + assert "Tableau > Child 1" == all_projects[2].name + assert "ManagedByOwner" == all_projects[2].content_permissions + assert "1d0304cd-3796-429f-b815-7258370b9b74" == all_projects[2].parent_id + assert "dd2239f6-ddf1-4107-981a-4cf94e415794" == all_projects[2].owner_id + + +def test_get_before_signin(server: TSC.Server) -> None: + server._auth_token = None + with pytest.raises(TSC.NotSignedInError): + server.projects.get() + + +def test_delete(server: TSC.Server) -> None: + with requests_mock.mock() as m: + m.delete(server.projects.baseurl + "/ee8c6e70-43b6-11e6-af4f-f7b0d8e20760", status_code=204) + server.projects.delete("ee8c6e70-43b6-11e6-af4f-f7b0d8e20760") + + +def test_delete_missing_id(server: TSC.Server) -> None: + with pytest.raises(ValueError): + server.projects.delete("") + + +def test_update(server: TSC.Server) -> None: + response_xml = UPDATE_XML.read_text() + with requests_mock.mock() as m: + m.put(server.projects.baseurl + "/1d0304cd-3796-429f-b815-7258370b9b74", text=response_xml) + single_project = TSC.ProjectItem( + name="Test Project", + content_permissions="LockedToProject", + description="Project created for testing", + parent_id="9a8f2265-70f3-4494-96c5-e5949d7a1120", + ) + single_project._id = "1d0304cd-3796-429f-b815-7258370b9b74" + single_project.owner_id = "dd2239f6-ddf1-4107-981a-4cf94e415794" + single_project = server.projects.update(single_project) + + assert "1d0304cd-3796-429f-b815-7258370b9b74" == single_project.id + assert "Test Project" == single_project.name + assert "Project created for testing" == single_project.description + assert "LockedToProject" == single_project.content_permissions + assert "9a8f2265-70f3-4494-96c5-e5949d7a1120" == single_project.parent_id + assert "dd2239f6-ddf1-4107-981a-4cf94e415794" == single_project.owner_id + + +def test_content_permission_locked_to_project_without_nested(server: TSC.Server) -> None: + response_xml = SET_CONTENT_PERMISSIONS_XML.read_text() + with requests_mock.mock() as m: + m.put(server.projects.baseurl + "/cb3759e5-da4a-4ade-b916-7e2b4ea7ec86", text=response_xml) + project_item = TSC.ProjectItem( + name="Test Project Permissions", + content_permissions="LockedToProjectWithoutNested", + description="Project created for testing", + parent_id="7687bc43-a543-42f3-b86f-80caed03a813", + ) + project_item._id = "cb3759e5-da4a-4ade-b916-7e2b4ea7ec86" + project_item = server.projects.update(project_item) + assert "cb3759e5-da4a-4ade-b916-7e2b4ea7ec86" == project_item.id + assert "Test Project Permissions" == project_item.name + assert "Project created for testing" == project_item.description + assert "LockedToProjectWithoutNested" == project_item.content_permissions + assert "7687bc43-a543-42f3-b86f-80caed03a813" == project_item.parent_id + + +def test_update_datasource_default_permission(server: TSC.Server) -> None: + response_xml = UPDATE_DATASOURCE_DEFAULT_PERMISSIONS_XML.read_text() + with requests_mock.mock() as m: + m.put( + server.projects.baseurl + "/b4065286-80f0-11ea-af1b-cb7191f48e45/default-permissions/datasources", + text=response_xml, + ) + project = TSC.ProjectItem("test-project") + project._id = "b4065286-80f0-11ea-af1b-cb7191f48e45" + + group = TSC.GroupItem("test-group") + group._id = "b4488bce-80f0-11ea-af1c-976d0c1dab39" + + capabilities = {TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny} + + rules = [TSC.PermissionsRule(grantee=GroupItem.as_reference(group._id), capabilities=capabilities)] + + new_rules = server.projects.update_datasource_default_permissions(project, rules) + + assert "b4488bce-80f0-11ea-af1c-976d0c1dab39" == new_rules[0].grantee.id + + updated_capabilities = new_rules[0].capabilities + assert 4 == len(updated_capabilities) + assert "Deny" == updated_capabilities["ExportXml"] + assert "Allow" == updated_capabilities["Read"] + assert "Allow" == updated_capabilities["Write"] + assert "Allow" == updated_capabilities["Connect"] + + +def test_update_missing_id(server: TSC.Server) -> None: + single_project = TSC.ProjectItem("test") + with pytest.raises(TSC.MissingRequiredFieldError): + server.projects.update(single_project) + + +def test_create(server: TSC.Server) -> None: + response_xml = CREATE_XML.read_text() + with requests_mock.mock() as m: + m.post(server.projects.baseurl, text=response_xml) + new_project = TSC.ProjectItem(name="Test Project", description="Project created for testing") + new_project.content_permissions = "ManagedByOwner" + new_project.parent_id = "9a8f2265-70f3-4494-96c5-e5949d7a1120" + new_project = server.projects.create(new_project) + + assert "ccbea03f-77c4-4209-8774-f67bc59c3cef" == new_project.id + assert "Test Project" == new_project.name + assert "Project created for testing" == new_project.description + assert "ManagedByOwner" == new_project.content_permissions + assert "9a8f2265-70f3-4494-96c5-e5949d7a1120" == new_project.parent_id + + +def test_create_missing_name() -> None: + TSC.ProjectItem() + + +def test_populate_permissions(server: TSC.Server) -> None: + response_xml = POPULATE_PERMISSIONS_XML.read_text() + with requests_mock.mock() as m: + m.get(server.projects.baseurl + "/0448d2ed-590d-4fa0-b272-a2a8a24555b5/permissions", text=response_xml) + single_project = TSC.ProjectItem("Project3") + single_project._id = "0448d2ed-590d-4fa0-b272-a2a8a24555b5" + + server.projects.populate_permissions(single_project) + permissions = single_project.permissions + + assert permissions[0].grantee.tag_name == "group" + assert permissions[0].grantee.id == "c8f2773a-c83a-11e8-8c8f-33e6d787b506" + assert permissions[0].capabilities == { + TSC.Permission.Capability.Write: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Read: TSC.Permission.Mode.Allow, + } + + +def test_populate_workbooks(server: TSC.Server) -> None: + response_xml = POPULATE_WORKBOOK_DEFAULT_PERMISSIONS_XML.read_text() + with requests_mock.mock() as m: + m.get( + server.projects.baseurl + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/workbooks", + text=response_xml, + ) + single_project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") + single_project.owner_id = "dd2239f6-ddf1-4107-981a-4cf94e415794" + single_project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" + + server.projects.populate_workbook_default_permissions(single_project) + permissions = single_project.default_workbook_permissions + + rule1 = permissions.pop() + + assert "c8f2773a-c83a-11e8-8c8f-33e6d787b506" == rule1.grantee.id + assert "group" == rule1.grantee.tag_name + assert rule1.capabilities == { + TSC.Permission.Capability.Write: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Read: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Filter: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ChangePermissions: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.WebAuthoring: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ExportImage: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny, + TSC.Permission.Capability.ShareView: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ViewUnderlyingData: TSC.Permission.Mode.Deny, + TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.AddComment: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Allow, + } + + +def test_delete_permission(server: TSC.Server) -> None: + response_xml = POPULATE_PERMISSIONS_XML.read_text() + with requests_mock.mock() as m: + m.get(server.projects.baseurl + "/0448d2ed-590d-4fa0-b272-a2a8a24555b5/permissions", text=response_xml) + + single_group = TSC.GroupItem("Group1") + single_group._id = "c8f2773a-c83a-11e8-8c8f-33e6d787b506" + + single_project = TSC.ProjectItem("Project3") + single_project._id = "0448d2ed-590d-4fa0-b272-a2a8a24555b5" + + server.projects.populate_permissions(single_project) + permissions = single_project.permissions + + capabilities = {} + + for permission in permissions: + if permission.grantee.tag_name == "group": + if permission.grantee.id == single_group._id: + capabilities = permission.capabilities + + rules = TSC.PermissionsRule(grantee=GroupItem.as_reference(single_group._id), capabilities=capabilities) + + endpoint = f"{single_project._id}/permissions/groups/{single_group._id}" + m.delete(f"{server.projects.baseurl}/{endpoint}/Read/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/Write/Allow", status_code=204) + server.projects.delete_permission(item=single_project, rules=rules) + + +def test_delete_workbook_default_permission(server: TSC.Server) -> None: + response_xml = POPULATE_WORKBOOK_DEFAULT_PERMISSIONS_XML.read_text() + + with requests_mock.mock() as m: + m.get( + server.projects.baseurl + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/workbooks", + text=response_xml, ) - def test_delete_permission(self) -> None: - with open(asset(POPULATE_PERMISSIONS_XML), "rb") as f: - response_xml = f.read().decode("utf-8") - with requests_mock.mock() as m: - m.get(self.baseurl + "/0448d2ed-590d-4fa0-b272-a2a8a24555b5/permissions", text=response_xml) - - single_group = TSC.GroupItem("Group1") - single_group._id = "c8f2773a-c83a-11e8-8c8f-33e6d787b506" - - single_project = TSC.ProjectItem("Project3") - single_project._id = "0448d2ed-590d-4fa0-b272-a2a8a24555b5" - - self.server.projects.populate_permissions(single_project) - permissions = single_project.permissions - - capabilities = {} - - for permission in permissions: - if permission.grantee.tag_name == "group": - if permission.grantee.id == single_group._id: - capabilities = permission.capabilities - - rules = TSC.PermissionsRule(grantee=GroupItem.as_reference(single_group._id), capabilities=capabilities) - - endpoint = f"{single_project._id}/permissions/groups/{single_group._id}" - m.delete(f"{self.baseurl}/{endpoint}/Read/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/Write/Allow", status_code=204) - self.server.projects.delete_permission(item=single_project, rules=rules) - - def test_delete_workbook_default_permission(self) -> None: - with open(asset(POPULATE_WORKBOOK_DEFAULT_PERMISSIONS_XML), "rb") as f: - response_xml = f.read().decode("utf-8") - - with requests_mock.mock() as m: - m.get( - self.baseurl + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/workbooks", text=response_xml - ) - - single_group = TSC.GroupItem("Group1") - single_group._id = "c8f2773a-c83a-11e8-8c8f-33e6d787b506" - - single_project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") - single_project._owner_id = "dd2239f6-ddf1-4107-981a-4cf94e415794" - single_project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" - - self.server.projects.populate_workbook_default_permissions(single_project) - permissions = single_project.default_workbook_permissions - - capabilities = { - # View - TSC.Permission.Capability.Read: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ExportImage: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.AddComment: TSC.Permission.Mode.Allow, - # Interact/Edit - TSC.Permission.Capability.Filter: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ViewUnderlyingData: TSC.Permission.Mode.Deny, - TSC.Permission.Capability.ShareView: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.WebAuthoring: TSC.Permission.Mode.Allow, - # Edit - TSC.Permission.Capability.Write: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny, - TSC.Permission.Capability.ChangePermissions: TSC.Permission.Mode.Allow, - } - - rules = TSC.PermissionsRule(grantee=GroupItem.as_reference(single_group._id), capabilities=capabilities) - - endpoint = f"{single_project._id}/default-permissions/workbooks/groups/{single_group._id}" - m.delete(f"{self.baseurl}/{endpoint}/Read/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/ExportImage/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/ExportData/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/ViewComments/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/AddComment/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/Filter/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/ViewUnderlyingData/Deny", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/ShareView/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/WebAuthoring/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/Write/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/ExportXml/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/ChangeHierarchy/Allow", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/Delete/Deny", status_code=204) - m.delete(f"{self.baseurl}/{endpoint}/ChangePermissions/Allow", status_code=204) - self.server.projects.delete_workbook_default_permissions(item=single_project, rule=rules) - - def test_populate_virtualconnection_default_permissions(self): - response_xml = read_xml_asset(POPULATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML) - - self.server.version = "3.23" - base_url = self.server.projects.baseurl - - with requests_mock.mock() as m: - m.get( - base_url + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/virtualConnections", - text=response_xml, - ) - project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") - project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" - - self.server.projects.populate_virtualconnection_default_permissions(project) - permissions = project.default_virtualconnection_permissions - - rule = permissions.pop() - - self.assertEqual("c8f2773a-c83a-11e8-8c8f-33e6d787b506", rule.grantee.id) - self.assertEqual("group", rule.grantee.tag_name) - self.assertDictEqual( - rule.capabilities, - { - TSC.Permission.Capability.Read: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Connect: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Deny, - TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny, - TSC.Permission.Capability.ChangePermissions: TSC.Permission.Mode.Deny, - }, + single_group = TSC.GroupItem("Group1") + single_group._id = "c8f2773a-c83a-11e8-8c8f-33e6d787b506" + + single_project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") + single_project._owner_id = "dd2239f6-ddf1-4107-981a-4cf94e415794" + single_project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" + + server.projects.populate_workbook_default_permissions(single_project) + permissions = single_project.default_workbook_permissions + + capabilities = { + # View + TSC.Permission.Capability.Read: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ExportImage: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.AddComment: TSC.Permission.Mode.Allow, + # Interact/Edit + TSC.Permission.Capability.Filter: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ViewUnderlyingData: TSC.Permission.Mode.Deny, + TSC.Permission.Capability.ShareView: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.WebAuthoring: TSC.Permission.Mode.Allow, + # Edit + TSC.Permission.Capability.Write: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny, + TSC.Permission.Capability.ChangePermissions: TSC.Permission.Mode.Allow, + } + + rules = TSC.PermissionsRule(grantee=GroupItem.as_reference(single_group._id), capabilities=capabilities) + + endpoint = f"{single_project._id}/default-permissions/workbooks/groups/{single_group._id}" + m.delete(f"{server.projects.baseurl}/{endpoint}/Read/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/ExportImage/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/ExportData/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/ViewComments/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/AddComment/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/Filter/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/ViewUnderlyingData/Deny", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/ShareView/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/WebAuthoring/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/Write/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/ExportXml/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/ChangeHierarchy/Allow", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/Delete/Deny", status_code=204) + m.delete(f"{server.projects.baseurl}/{endpoint}/ChangePermissions/Allow", status_code=204) + server.projects.delete_workbook_default_permissions(item=single_project, rule=rules) + + +def test_populate_virtualconnection_default_permissions(server: TSC.Server) -> None: + response_xml = POPULATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML.read_text() + + server.version = "3.23" + base_url = server.projects.baseurl + + with requests_mock.mock() as m: + m.get( + base_url + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/virtualConnections", + text=response_xml, ) + project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") + project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" + + server.projects.populate_virtualconnection_default_permissions(project) + permissions = project.default_virtualconnection_permissions + + rule = permissions.pop() + + assert "c8f2773a-c83a-11e8-8c8f-33e6d787b506" == rule.grantee.id + assert "group" == rule.grantee.tag_name + assert rule.capabilities == { + TSC.Permission.Capability.Read: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Connect: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Deny, + TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny, + TSC.Permission.Capability.ChangePermissions: TSC.Permission.Mode.Deny, + } + + +def test_update_virtualconnection_default_permissions(server: TSC.Server) -> None: + response_xml = UPDATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML.read_text() - def test_update_virtualconnection_default_permissions(self): - response_xml = read_xml_asset(UPDATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML) - - self.server.version = "3.23" - base_url = self.server.projects.baseurl - - with requests_mock.mock() as m: - m.put( - base_url + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/virtualConnections", - text=response_xml, - ) - project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") - project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" - - group = TSC.GroupItem("test-group") - group._id = "c8f2773a-c83a-11e8-8c8f-33e6d787b506" - - capabilities = { - TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Read: TSC.Permission.Mode.Deny, - } - - rules = [TSC.PermissionsRule(GroupItem.as_reference(group.id), capabilities)] - new_rules = self.server.projects.update_virtualconnection_default_permissions(project, rules) - - rule = new_rules.pop() - - self.assertEqual(group.id, rule.grantee.id) - self.assertEqual("group", rule.grantee.tag_name) - self.assertDictEqual( - rule.capabilities, - { - TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow, - TSC.Permission.Capability.Read: TSC.Permission.Mode.Deny, - }, + server.version = "3.23" + base_url = server.projects.baseurl + + with requests_mock.mock() as m: + m.put( + base_url + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/virtualConnections", + text=response_xml, ) + project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") + project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" + + group = TSC.GroupItem("test-group") + group._id = "c8f2773a-c83a-11e8-8c8f-33e6d787b506" + + capabilities = { + TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Read: TSC.Permission.Mode.Deny, + } + + assert group.id is not None + rules = [TSC.PermissionsRule(GroupItem.as_reference(group.id), capabilities)] + new_rules = server.projects.update_virtualconnection_default_permissions(project, rules) + + rule = new_rules.pop() - def test_delete_virtualconnection_default_permimssions(self): - response_xml = read_xml_asset(POPULATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML) + assert group.id == rule.grantee.id + assert "group" == rule.grantee.tag_name + assert rule.capabilities == { + TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow, + TSC.Permission.Capability.Read: TSC.Permission.Mode.Deny, + } - self.server.version = "3.23" - base_url = self.server.projects.baseurl - with requests_mock.mock() as m: - m.get( - base_url + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/virtualConnections", - text=response_xml, - ) +def test_delete_virtualconnection_default_permimssions(server: TSC.Server) -> None: + response_xml = POPULATE_VIRTUALCONNECTION_DEFAULT_PERMISSIONS_XML.read_text() + + server.version = "3.23" + base_url = server.projects.baseurl + + with requests_mock.mock() as m: + m.get( + base_url + "/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb/default-permissions/virtualConnections", + text=response_xml, + ) + + project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") + project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" - project = TSC.ProjectItem("test", "1d0304cd-3796-429f-b815-7258370b9b74") - project._id = "9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" + group = TSC.GroupItem("test-group") + group._id = "c8f2773a-c83a-11e8-8c8f-33e6d787b506" - group = TSC.GroupItem("test-group") - group._id = "c8f2773a-c83a-11e8-8c8f-33e6d787b506" + server.projects.populate_virtualconnection_default_permissions(project) + permissions = project.default_virtualconnection_permissions - self.server.projects.populate_virtualconnection_default_permissions(project) - permissions = project.default_virtualconnection_permissions + del_caps = { + TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Deny, + TSC.Permission.Capability.Connect: TSC.Permission.Mode.Allow, + } - del_caps = { - TSC.Permission.Capability.ChangeHierarchy: TSC.Permission.Mode.Deny, - TSC.Permission.Capability.Connect: TSC.Permission.Mode.Allow, - } + assert group.id is not None + rule = TSC.PermissionsRule(GroupItem.as_reference(group.id), del_caps) - rule = TSC.PermissionsRule(GroupItem.as_reference(group.id), del_caps) + endpoint = f"{project.id}/default-permissions/virtualConnections/groups/{group.id}" + m.delete(f"{base_url}/{endpoint}/ChangeHierarchy/Deny", status_code=204) + m.delete(f"{base_url}/{endpoint}/Connect/Allow", status_code=204) - endpoint = f"{project.id}/default-permissions/virtualConnections/groups/{group.id}" - m.delete(f"{base_url}/{endpoint}/ChangeHierarchy/Deny", status_code=204) - m.delete(f"{base_url}/{endpoint}/Connect/Allow", status_code=204) + server.projects.delete_virtualconnection_default_permissions(project, rule) - self.server.projects.delete_virtualconnection_default_permissions(project, rule) - def test_get_all_fields(self) -> None: - self.server.version = "3.23" - base_url = self.server.projects.baseurl - with open(GET_XML_ALL_FIELDS, "rb") as f: - response_xml = f.read().decode("utf-8") +def test_get_all_fields(server: TSC.Server) -> None: + server.version = "3.23" + base_url = server.projects.baseurl + response_xml = GET_XML_ALL_FIELDS.read_text() - ro = TSC.RequestOptions() - ro.all_fields = True + ro = TSC.RequestOptions() + ro.all_fields = True - with requests_mock.mock() as m: - m.get(f"{base_url}?fields=_all_", text=response_xml) - all_projects, pagination_item = self.server.projects.get(req_options=ro) + with requests_mock.mock() as m: + m.get(f"{base_url}?fields=_all_", text=response_xml) + all_projects, pagination_item = server.projects.get(req_options=ro) - assert pagination_item.total_available == 3 - assert len(all_projects) == 1 - project: TSC.ProjectItem = all_projects[0] - assert isinstance(project, TSC.ProjectItem) - assert project.id == "ee8c6e70-43b6-11e6-af4f-f7b0d8e20760" - assert project.name == "Samples" - assert project.description == "This project includes automatically uploaded samples." - assert project.top_level_project is True - assert project.content_permissions == "ManagedByOwner" - assert project.parent_id is None - assert project.writeable is True + assert pagination_item.total_available == 3 + assert len(all_projects) == 1 + project: TSC.ProjectItem = all_projects[0] + assert isinstance(project, TSC.ProjectItem) + assert project.id == "ee8c6e70-43b6-11e6-af4f-f7b0d8e20760" + assert project.name == "Samples" + assert project.description == "This project includes automatically uploaded samples." + assert project.top_level_project is True + assert project.content_permissions == "ManagedByOwner" + assert project.parent_id is None + assert project.writeable is True diff --git a/test/test_project_model.py b/test/test_project_model.py index ecfe1bd1..b51a218e 100644 --- a/test/test_project_model.py +++ b/test/test_project_model.py @@ -1,21 +1,22 @@ -import unittest +import pytest import tableauserverclient as TSC -class ProjectModelTests(unittest.TestCase): - def test_nullable_name(self): - TSC.ProjectItem(None) - TSC.ProjectItem("") - project = TSC.ProjectItem("proj") - project.name = None +def test_nullable_name(): + TSC.ProjectItem(None) + TSC.ProjectItem("") + project = TSC.ProjectItem("proj") + project.name = None - def test_invalid_content_permissions(self): - project = TSC.ProjectItem("proj") - with self.assertRaises(ValueError): - project.content_permissions = "Hello" - def test_parent_id(self): - project = TSC.ProjectItem("proj") - project.parent_id = "foo" - self.assertEqual(project.parent_id, "foo") +def test_invalid_content_permissions(): + project = TSC.ProjectItem("proj") + with pytest.raises(ValueError): + project.content_permissions = "Hello" + + +def test_parent_id(): + project = TSC.ProjectItem("proj") + project.parent_id = "foo" + assert project.parent_id == "foo"