diff --git a/magpie/api/exception.py b/magpie/api/exception.py index 5711cf869..9b27cb947 100644 --- a/magpie/api/exception.py +++ b/magpie/api/exception.py @@ -41,7 +41,7 @@ URL_REGEX = colander.URL_REGEX -def verify_param( # noqa: E126 +def verify_param( # noqa: E126 # pylint: disable=R0913,too-many-arguments # --- verification values --- param, # type: Any param_compare=None, # type: Optional[Union[Any, List[Any]]] diff --git a/magpie/api/login/login.py b/magpie/api/login/login.py index 14ed4f28b..2d6653d5c 100644 --- a/magpie/api/login/login.py +++ b/magpie/api/login/login.py @@ -292,4 +292,4 @@ def get_providers(request): # noqa: F811 """ return ax.valid_http(http_success=HTTPOk, detail=s.Providers_GET_OkResponseSchema.description, content={"providers": {"internal": sorted(MAGPIE_INTERNAL_PROVIDERS.values()), - "external": sorted(MAGPIE_EXTERNAL_PROVIDERS.values()), }}) + "external": sorted(MAGPIE_EXTERNAL_PROVIDERS.values()), }}) diff --git a/magpie/api/management/resource/resource_formats.py b/magpie/api/management/resource/resource_formats.py index 881be4d1b..b819efc98 100644 --- a/magpie/api/management/resource/resource_formats.py +++ b/magpie/api/management/resource/resource_formats.py @@ -83,8 +83,11 @@ def format_resource_tree(children, db_session, resources_perms_dict=None, _inter perms = _internal_svc_res_perm_dict[service_id][resource.resource_type] # 'resource_type' is str here fmt_res_tree[child_id] = format_resource(resource, perms) - fmt_res_tree[child_id]["children"] = format_resource_tree(new_children, db_session, - resources_perms_dict, _internal_svc_res_perm_dict) + fmt_res_tree[child_id]["children"] = format_resource_tree( + new_children, db_session, + resources_perms_dict, + _internal_svc_res_perm_dict + ) return fmt_res_tree diff --git a/magpie/api/management/resource/resource_utils.py b/magpie/api/management/resource/resource_utils.py index 0c1b7afa4..134b124ca 100644 --- a/magpie/api/management/resource/resource_utils.py +++ b/magpie/api/management/resource/resource_utils.py @@ -25,7 +25,7 @@ # pylint: disable=W0611,unused-import from pyramid.httpexceptions import HTTPException from sqlalchemy.orm.session import Session - from magpie.typedefs import List, Str, Optional, Tuple, Type, ServiceOrResourceType # noqa: F401 + from magpie.typedefs import List, Str, Optional, Tuple, Type, ServiceOrResourceType, Union # noqa: F401 from magpie.services import ServiceInterface # noqa: F401 @@ -121,7 +121,7 @@ def get_resource_permissions(resource, db_session): msg_on_fail=s.UserResourcePermissions_GET_BadRequestResourceResponseSchema.description) # directly access the service resource if resource.root_service_id is None: - service = resource + service = resource # type: models.Service # noqa return SERVICE_TYPE_DICT[service.type].permissions # otherwise obtain root level service to infer sub-resource permissions @@ -137,7 +137,7 @@ def get_resource_permissions(resource, db_session): def get_resource_root_service(resource, db_session): - # type: (models.Resource, Session) -> Optional[models.Resource] + # type: (Union[models.Service, models.Resource], Session) -> Optional[models.Service] """ Recursively rewinds back through the top of the resource tree up to the top-level service-resource. diff --git a/magpie/api/management/service/service_utils.py b/magpie/api/management/service/service_utils.py index 29bb99ecf..cf583d1ff 100644 --- a/magpie/api/management/service/service_utils.py +++ b/magpie/api/management/service/service_utils.py @@ -1,6 +1,5 @@ from typing import TYPE_CHECKING -import colander from pyramid.httpexceptions import HTTPBadRequest, HTTPConflict, HTTPCreated, HTTPForbidden, HTTPInternalServerError from ziggurat_foundations.models.services.group import GroupService from ziggurat_foundations.models.services.resource import ResourceService diff --git a/magpie/register.py b/magpie/register.py index 849ca1827..1924720ba 100644 --- a/magpie/register.py +++ b/magpie/register.py @@ -48,7 +48,7 @@ if TYPE_CHECKING: # pylint: disable=W0611,unused-import from magpie.typedefs import ( # noqa: F401 - Any, AnyCookiesType, CookiesOrSessionType, Dict, List, JSON, Optional, Str, Tuple, Union + Any, AnyCookiesType, CookiesOrSessionType, Dict, Iterable, List, JSON, Optional, Str, Tuple, Union ) ConfigItem = Dict[Str, Str] ConfigList = List[ConfigItem] @@ -276,25 +276,27 @@ def _register_services(where, # type: Optional[Str] return success, statuses -def sync_services_phoenix(services_object_dict, services_as_dicts=False): - # type: (Dict[Str, Union[models.Service, JSON]], bool) -> bool +def sync_services_phoenix(services, services_as_dicts=False): + # type: (Union[Iterable[models.Service], JSON], bool) -> bool """ Syncs Magpie services by pushing updates to Phoenix. Services must be one of types specified in :py:data:`magpie.register.SERVICES_PHOENIX_ALLOWED`. - :param services_object_dict: - dictionary of ``{svc-name: models.Service}`` objects containing each service's information - :param services_as_dicts: - alternatively specify :paramref:`services_object_dict` as dict of ``{svc-name: {service-info}}`` - where ``{service-info}`` is defined as:: + :param services: + An iterable of :class:`models.Service` by default, or a dictionary of ``{svc-name: {}}`` JSON + objects containing each service's information if :paramref:`services_ad_dicts` is ``True``. + + where ```` is defined as:: {"public_url": , "service_name": , "service_type": } + + :param services_as_dicts: indicate if services must be parsed as JSON definitions. """ services_dict = {} - for svc in services_object_dict: + for svc in services: if services_as_dicts: - svc_dict = services_object_dict[svc] + svc_dict = services[svc] services_dict[svc] = {"url": svc_dict["public_url"], "title": svc_dict["service_name"], "type": svc_dict["service_type"], "c4i": False, "public": True} else: diff --git a/magpie/typedefs.py b/magpie/typedefs.py index d4cf824cf..42b563aec 100644 --- a/magpie/typedefs.py +++ b/magpie/typedefs.py @@ -45,7 +45,6 @@ AnyCookiesType = Union[CookiesType, RequestsCookieJar] AnyResponseType = Union[WebobResponse, PyramidResponse, TestResponse] CookiesOrSessionType = Union[RequestsCookieJar, Session] - OptionalHeaderCookiesType = Tuple[Optional[AnyHeadersType], Optional[AnyCookiesType]] AnyKey = Union[Str, int] AnyValue = Union[Str, Number, bool, None] diff --git a/tests/interfaces.py b/tests/interfaces.py index 575aca804..e4d8f2158 100644 --- a/tests/interfaces.py +++ b/tests/interfaces.py @@ -1,6 +1,6 @@ import unittest import warnings -from abc import ABCMeta, abstactmethod +from abc import ABCMeta, abstractmethod from copy import deepcopy from distutils.version import LooseVersion from typing import TYPE_CHECKING @@ -29,7 +29,7 @@ class Base_Magpie_TestCase(six.with_metaclass(ABCMeta, unittest.TestCase)): """ Base definition for all other Test Suite interfaces. - The implementers must provide :meth:`initClass` which prepares the various test parameters, session cookies and + The implementers must provide :meth:`setUpClass` which prepares the various test parameters, session cookies and the local application or remote Magpie URL configuration to evaluate test cases on. The implementers Test Suites must also set :attr:`__test__` to ``True`` so that tests are picked up as executable. @@ -37,37 +37,32 @@ class Base_Magpie_TestCase(six.with_metaclass(ABCMeta, unittest.TestCase)): .. note:: Attribute attr:`__test__` is employed to avoid duplicate runs of this base class or other derived classes that must not be considered as the *final implementer* Test Suite. - - .. warning:: - Do not use :meth:`setUpClass` with :py:exception:`NotImplementedError` in this class or any derived *incomplete* - class as this method still gets called by some test runners although marked with ``__test__ = False``. - The tests would be interpreted as failing in this situation (due to raised error) instead of only indicating an - abstract class definition. You are free to use it if the method is non-raising, but remember that the code will - be executed during initialization of the Test Suite even if seemingly disabled for testing. """ # pylint: disable=C0103,invalid-name version = None # type: Optional[Str] + require = None # type: Optional[Str] + # parameters for setup operations, admin-level access to the app grp = None # type: Optional[Str] usr = None # type: Optional[Str] pwd = None # type: Optional[Str] - require = None # type: Optional[Str] cookies = None # type: Optional[CookiesType] headers = None # type: Optional[HeadersType] json_headers = None # type: Optional[HeadersType] + # parameters for testing, extracted automatically within utils.TestSetup methods test_service_type = None # type: Optional[Str] test_service_name = None # type: Optional[Str] - test_user = None # type: Optional[Str] - test_group = None # type: Optional[Str] + test_user_name = None # type: Optional[Str] + test_group_name = None # type: Optional[Str] __test__ = False # won't run this as a test suite, only its derived classes that overrides to True @classmethod - @abstactmethod - def initClass(cls): + @abstractmethod + def setUpClass(cls): raise NotImplementedError @classmethod - def tearDownClass(cls): # noqa: N802 + def tearDownClass(cls): pyramid.testing.tearDown() @@ -77,16 +72,12 @@ class Interface_MagpieAPI_NoAuth(six.with_metaclass(ABCMeta, Base_Magpie_TestCas """ Interface class for unittests of Magpie API. Test any operation that do not require user AuthN/AuthZ. - Derived classes must implement :meth:`initClass` accordingly to generate the Magpie test application. + Derived classes must implement :meth:`setUpClass` accordingly to generate the Magpie test application. """ - @classmethod - def initClass(cls): - raise NotImplementedError - @classmethod def setUpClass(cls): - cls.initClass() + raise NotImplementedError @runner.MAGPIE_TEST_LOGIN def test_GetSession_Anonymous(self): @@ -130,18 +121,30 @@ def test_NotAcceptableRequest(self): utils.check_response_basic_info(resp, expected_code=406) @runner.MAGPIE_TEST_USERS + @runner.MAGPIE_TEST_LOGGED def test_RegisterDiscoverableGroup_Unauthorized(self): """Not logged-in user cannot update membership to group although group is discoverable.""" - raise NotImplementedError # TODO + utils.warn_version(self, "User registration views not yet available.", "2.0.0", skip=True) + resp = utils.test_request(self, "GET", "/register/groups", headers=self.json_headers, expect_errors=True) + body = utils.check_response_basic_info(resp, 401) + utils.check_val_not_in("group_names", body) @runner.MAGPIE_TEST_USERS def test_UnregisterDiscoverableGroup_Unauthorized(self): """Not logged-in user cannot remove membership to group although group is discoverable.""" - raise NotImplementedError # TODO + utils.warn_version(self, "User registration views not yet available.", "2.0.0", skip=True) + path = "/register/groups/random-group" + resp = utils.test_request(self, "DELETE", path, headers=self.json_headers, expect_errors=True) + utils.check_response_basic_info(resp, 401) def test_ViewDiscoverableGroup_Unauthorized(self): """Not logged-in user cannot view group although group is discoverable.""" - raise NotImplementedError # TODO + utils.warn_version(self, "User registration views not yet available.", "2.0.0", skip=True) + utils.TestSetup + + path = "/register/groups/random-group" + resp = utils.test_request(self, "DELETE", path, headers=self.json_headers, expect_errors=True) + utils.check_response_basic_info(resp, 401) def test_ListDiscoverableGroup_Unauthorized(self): """Not logged-in user cannot list group names although groups are discoverable.""" @@ -154,11 +157,11 @@ class Interface_MagpieAPI_UsersAuth(six.with_metaclass(ABCMeta, Base_Magpie_Test """ Interface class for unittests of Magpie API. Test any operation that require at least logged user AuthN/AuthZ. - Derived classes must implement :meth:`initClass` accordingly to generate the Magpie test application. + Derived classes must implement :meth:`setUpClass` accordingly to generate the Magpie test application. """ @classmethod - def initClass(cls): + def setUpClass(cls): raise NotImplementedError @classmethod @@ -352,11 +355,11 @@ class Interface_MagpieAPI_AdminAuth(six.with_metaclass(ABCMeta, Base_Magpie_Test Interface class for unittests of Magpie API. Test any operation that require at least 'administrator' group AuthN/AuthZ. - Derived classes must implement :meth:`initClass` accordingly to generate the Magpie test application. + Derived classes must implement :meth:`setUpClass` accordingly to generate the Magpie test application. """ @classmethod - def initClass(cls): + def setUpClass(cls): raise NotImplementedError def tearDown(self): @@ -404,7 +407,6 @@ def setup_test_values(cls): cls.test_group_name = "magpie-unittest-dummy-group" cls.test_user_name = "magpie-unittest-toto" - cls.test_user_group = get_constant("MAGPIE_USERS_GROUP") def setUp(self): self.check_requirements() @@ -536,15 +538,15 @@ def test_GetCurrentUserResourcesPermissions_Queries(self): body = utils.TestSetup.create_TestService(self, override_service_type=ServiceAPI.service_type) test_svc_res_id = body["service"]["resource_id"] test_res_type = Route.resource_type_name - body = utils.TestSetup.create_TestServiceResource(self, data_override={"resource_type": test_res_type}) + body = utils.TestSetup.create_TestServiceResource(self, override_data={"resource_type": test_res_type}) test_parent_res_id = body["resource"]["resource_id"] child_resource_name = self.test_resource_name + "-child" - data_override = { + override_data = { "resource_name": child_resource_name, "resource_type": test_res_type, "parent_id": test_parent_res_id } - body = utils.TestSetup.create_TestServiceResource(self, data_override) + body = utils.TestSetup.create_TestServiceResource(self, override_data) test_child_res_id = body["resource"]["resource_id"] anonym_usr = get_constant("MAGPIE_ANONYMOUS_USER") anonym_grp = get_constant("MAGPIE_ANONYMOUS_GROUP") @@ -617,7 +619,7 @@ def test_PostUserResourcesPermissions_Created(self): utils.TestSetup.delete_TestServiceResource(self, override_resource_name=resource_name) data = {"resource_name": resource_name} - body = utils.TestSetup.create_TestServiceResource(self, data_override=data) + body = utils.TestSetup.create_TestServiceResource(self, override_data=data) test_res_id = body["resource"]["resource_id"] # test permission creation @@ -641,7 +643,7 @@ def test_PostUserResourcesPermissions_Conflict(self): utils.TestSetup.delete_TestServiceResource(self, override_resource_name=resource_name) data = {"resource_name": resource_name} - body = utils.TestSetup.create_TestServiceResource(self, data_override=data) + body = utils.TestSetup.create_TestServiceResource(self, override_data=data) test_res_id = body["resource"]["resource_id"] path = "/users/{usr}/resources/{res}/permissions".format(res=test_res_id, usr=self.usr) @@ -978,7 +980,7 @@ def test_PostUsers_InvalidParameters(self): "user_name": self.test_user_name, "email": "{}@mail.com".format(self.test_user_name), "password": self.test_user_name, - "group_name": self.test_user_group, + "group_name": self.test_group_name, } for code, variant in [ (400, {"user_name": ""}), @@ -1214,7 +1216,8 @@ def test_PostUserGroup_conflict(self): @runner.MAGPIE_TEST_USERS def test_GetUserGroups(self): - utils.TestSetup.create_TestUser(self) # automatically adds user to "MAGPIE_USERS_GROUP" + users_group = get_constant("MAGPIE_USERS_GROUP") + utils.TestSetup.create_TestUser(self, override_group_name=users_group) utils.TestSetup.create_TestGroup(self) utils.TestSetup.assign_TestUserGroup(self) @@ -1224,7 +1227,7 @@ def test_GetUserGroups(self): body = utils.check_response_basic_info(resp, 200, expected_method="GET") utils.check_val_is_in("group_names", body) utils.check_val_type(body["group_names"], list) - expected_groups = {self.test_group_name, self.test_user_group} + expected_groups = {self.test_group_name, users_group} if LooseVersion(self.version) >= LooseVersion("1.4.0"): expected_groups.add(get_constant("MAGPIE_ANONYMOUS_GROUP")) utils.check_all_equal(body["group_names"], expected_groups, any_order=True) @@ -1767,12 +1770,12 @@ def test_PostServiceResources_ChildrenResource_ParentID(self): # create the child resource under the direct resource and validate response info child_resource_name = self.test_resource_name + "-children" - data_override = { + override_data = { "resource_name": child_resource_name, "resource_type": self.test_resource_type, "parent_id": test_resource_id } - body = utils.TestSetup.create_TestServiceResource(self, data_override) + body = utils.TestSetup.create_TestServiceResource(self, override_data) if LooseVersion(self.version) >= LooseVersion("0.6.3"): utils.check_val_is_in("resource", body) utils.check_val_type(body["resource"], dict) @@ -1950,11 +1953,11 @@ class Interface_MagpieUI_NoAuth(six.with_metaclass(ABCMeta, Base_Magpie_TestCase """ Interface class for unittests of Magpie UI. Test any operation that do not require user AuthN/AuthZ. - Derived classes must implement :meth:`initClass` accordingly to generate the Magpie test application. + Derived classes must implement :meth:`setUpClass` accordingly to generate the Magpie test application. """ @classmethod - def initClass(cls): + def setUpClass(cls): raise NotImplementedError @runner.MAGPIE_TEST_STATUS @@ -2028,7 +2031,7 @@ class Interface_MagpieUI_UsersAuth(six.with_metaclass(ABCMeta, Base_Magpie_TestC """ Interface class for unittests of Magpie UI. Test any operation that require at least logged user AuthN/AuthZ. - Derived classes must implement :meth:`initClass` accordingly to generate the Magpie test application. + Derived classes must implement :meth:`setUpClass` accordingly to generate the Magpie test application. """ def __init__(self, *args, **kwargs): @@ -2087,11 +2090,11 @@ class Interface_MagpieUI_AdminAuth(six.with_metaclass(ABCMeta, Base_Magpie_TestC Interface class for unittests of Magpie UI. Test any operation that require at least 'administrator' group AuthN/AuthZ. - Derived classes must implement :meth:`initClass` accordingly to generate the Magpie test application. + Derived classes must implement :meth:`setUpClass` accordingly to generate the Magpie test application. """ @classmethod - def initClass(cls): + def setUpClass(cls): raise NotImplementedError @classmethod diff --git a/tests/test_magpie_api.py b/tests/test_magpie_api.py index d8d1f7644..4e1d9c409 100644 --- a/tests/test_magpie_api.py +++ b/tests/test_magpie_api.py @@ -32,7 +32,7 @@ class TestCase_MagpieAPI_NoAuth_Local(ti.Interface_MagpieAPI_NoAuth, unittest.Te __test__ = True @classmethod - def initClass(cls): + def setUpClass(cls): cls.app = utils.get_test_magpie_app() cls.json_headers = utils.get_headers(cls.app, {"Accept": CONTENT_TYPE_JSON, "Content-Type": CONTENT_TYPE_JSON}) cls.cookies = None @@ -54,7 +54,7 @@ class TestCase_MagpieAPI_UsersAuth_Local(ti.Interface_MagpieAPI_UsersAuth, unitt __test__ = True @classmethod - def initClass(cls): + def setUpClass(cls): cls.app = utils.get_test_magpie_app() # admin login credentials for setup operations, use 'test' parameters for testing actual feature cls.grp = get_constant("MAGPIE_ADMIN_GROUP") @@ -68,7 +68,7 @@ def initClass(cls): cls.require = "cannot run tests without logged in user with '{}' permissions".format(cls.grp) cls.check_requirements() - cls.test_user_group = get_constant("MAGPIE_USERS_GROUP") + cls.test_group_name = get_constant("MAGPIE_USERS_GROUP") cls.test_user_name = "unittest-user_user-auth-username" cls.other_user_name = "unittest-other_user-auth-username" @@ -93,7 +93,7 @@ class TestCase_MagpieAPI_AdminAuth_Local(ti.Interface_MagpieAPI_AdminAuth, unitt __test__ = True @classmethod - def initClass(cls): + def setUpClass(cls): cls.app = utils.get_test_magpie_app() cls.grp = get_constant("MAGPIE_ADMIN_GROUP") cls.usr = get_constant("MAGPIE_TEST_ADMIN_USERNAME") @@ -123,7 +123,7 @@ class TestCase_MagpieAPI_NoAuth_Remote(ti.Interface_MagpieAPI_NoAuth, unittest.T __test__ = True @classmethod - def initClass(cls): + def setUpClass(cls): cls.url = get_constant("MAGPIE_TEST_REMOTE_SERVER_URL") cls.json_headers = utils.get_headers(cls.url, {"Accept": CONTENT_TYPE_JSON, "Content-Type": CONTENT_TYPE_JSON}) cls.cookies = None @@ -145,7 +145,7 @@ class TestCase_MagpieAPI_UsersAuth_Remote(ti.Interface_MagpieAPI_UsersAuth, unit __test__ = True @classmethod - def initClass(cls): + def setUpClass(cls): cls.url = get_constant("MAGPIE_TEST_REMOTE_SERVER_URL") @@ -162,7 +162,7 @@ class TestCase_MagpieAPI_AdminAuth_Remote(ti.Interface_MagpieAPI_AdminAuth, unit __test__ = True @classmethod - def initClass(cls): + def setUpClass(cls): cls.grp = get_constant("MAGPIE_ADMIN_GROUP") cls.usr = get_constant("MAGPIE_TEST_ADMIN_USERNAME") cls.pwd = get_constant("MAGPIE_TEST_ADMIN_PASSWORD") diff --git a/tests/utils.py b/tests/utils.py index 71dd90a47..f01f4c5ff 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -28,13 +28,14 @@ if TYPE_CHECKING: # pylint: disable=W0611,unused-import from tests.interfaces import Base_Magpie_TestCase # noqa: F401 - from typing import Any, Callable, Dict, Iterable, List, NoReturn, Optional, Type, Union # noqa: F401 + from typing import Any, Callable, Dict, Iterable, List, NoReturn, Optional, Tuple, Type, Union # noqa: F401 from magpie.typedefs import ( # noqa: F401 - AnyMagpieTestType, AnyHeadersType, AnyResponseType, HeadersType, JSON, - OptionalHeaderCookiesType, SettingsType, Str, TestAppOrUrlType + AnyCookiesType, AnyMagpieTestType, AnyHeadersType, AnyResponseType, CookiesType, HeadersType, JSON, + SettingsType, Str, TestAppOrUrlType ) - -OptionalStringType = six.string_types + tuple([type(None)]) # pylint: disable=C0103,invalid-name # noqa: 802 + # pylint: disable=C0103,invalid-name + OptionalHeaderCookiesType = Tuple[Optional[AnyHeadersType], Optional[AnyCookiesType]] + OptionalStringType = six.string_types + tuple([type(None)]) class RunOption(object): @@ -666,7 +667,18 @@ def check_resource_children(resource_dict, parent_resource_id, root_service_id): class TestSetup(object): - """Generic setup and validation methods across unittests""" + """Generic setup and validation methods across unittests + + All methods take as input an instance of a Test Suite derived from :class:`Base_Magpie_TestCase`. + Using this Test Suite, common arguments such as JSON headers and user session cookies are automatically extracted + and passed down to the relevant requests. + + Multiple parameters prefixed by ``test_`` are also automatically extracted from the referenced Test Suite. + For example, ``test_user_name`` will be retrieved from the Test Suite class when this information is required for + the corresponding test operation. It is possible to override this behaviour with corresponding arguments prefixed + by ``override`` keyword. For example, if ``override_user_name`` is provided, it will be used instead of + ``test_user_name`` from the Test Suite class. + """ # pylint: disable=C0103,invalid-name @staticmethod @@ -776,7 +788,7 @@ def get_AnyServiceOfTestServiceType(test_class): return list(services_dict.values())[0] @staticmethod - def create_TestServiceResource(test_class, data_override=None): + def create_TestServiceResource(test_class, override_data=None): app_or_url = get_app_or_url(test_class) TestSetup.create_TestService(test_class) path = "/services/{svc}/resources".format(svc=test_class.test_service_name) @@ -784,8 +796,8 @@ def create_TestServiceResource(test_class, data_override=None): "resource_name": test_class.test_resource_name, "resource_type": test_class.test_resource_type, } - if data_override: - data.update(data_override) + if override_data: + data.update(override_data) resp = test_request(app_or_url, "POST", path, headers=test_class.json_headers, cookies=test_class.cookies, json=data) @@ -917,13 +929,18 @@ def check_NonExistingTestUser(test_class, override_user_name=None): check_val_not_in(user_name, users) @staticmethod - def create_TestUser(test_class, override_data=None): + def create_TestUser(test_class, override_group_name=None, override_data=None): + # type: (Base_Magpie_TestCase, Optional[Str], Optional[JSON]) -> JSON + """Ensures that the test user exists. If it does, deletes him. Otherwise, skip. + + :raises AssertionError: if the request response does not match successful creation. + """ app_or_url = get_app_or_url(test_class) data = { "user_name": test_class.test_user_name, "email": "{}@mail.com".format(test_class.test_user_name), "password": test_class.test_user_name, - "group_name": test_class.test_user_group, + "group_name": override_group_name or test_class.test_group_name, } if override_data: data.update(override_data) @@ -934,6 +951,11 @@ def create_TestUser(test_class, override_data=None): @staticmethod def delete_TestUser(test_class, override_user_name=None): + # type: (Base_Magpie_TestCase, Optional[Str]) -> None + """Ensures that the test user does not exist. If it does, deletes him. Otherwise, skip. + + :raises AssertionError: if any request response does not match successful validation or removal from group. + """ app_or_url = get_app_or_url(test_class) users = TestSetup.get_RegisteredUsersList(test_class) user_name = override_user_name or test_class.test_user_name @@ -946,6 +968,11 @@ def delete_TestUser(test_class, override_user_name=None): @staticmethod def check_UserIsGroupMember(test_class, override_user_name=None, override_group_name=None): + # type: (Base_Magpie_TestCase, Optional[Str], Optional[Str]) -> None + """Ensures that the test user is a member of the test group. + + :raises AssertionError: if the request response does not match successful validation of membership to group. + """ app_or_url = get_app_or_url(test_class) usr_name = override_user_name or test_class.test_user_name grp_name = override_group_name or test_class.test_group_name @@ -956,6 +983,11 @@ def check_UserIsGroupMember(test_class, override_user_name=None, override_group_ @staticmethod def assign_TestUserGroup(test_class, override_user_name=None, override_group_name=None): + # type: (Base_Magpie_TestCase, Optional[Str], Optional[Str]) -> None + """Ensures that the test user is a member of the test group. If already a member, skips. Otherwise, adds him. + + :raises AssertionError: if any request response does not match successful validation or assignation to group. + """ app_or_url = get_app_or_url(test_class) usr_name = override_user_name or test_class.test_user_name grp_name = override_group_name or test_class.test_group_name @@ -972,6 +1004,11 @@ def assign_TestUserGroup(test_class, override_user_name=None, override_group_nam @staticmethod def get_RegisteredGroupsList(test_class): + # type: (Base_Magpie_TestCase) -> List[Str] + """Obtains existing group names. + + :raises AssertionError: if the request response does not match successful groups retrieval. + """ app_or_url = get_app_or_url(test_class) resp = test_request(app_or_url, "GET", "/groups", headers=test_class.json_headers, @@ -981,21 +1018,42 @@ def get_RegisteredGroupsList(test_class): @staticmethod def check_NonExistingTestGroup(test_class, override_group_name=None): + # type: (Base_Magpie_TestCase, Optional[Str]) -> None + """Validate that test group does not exist. + + :raises AssertionError: if the test group exists + """ groups = TestSetup.get_RegisteredGroupsList(test_class) group_name = override_group_name or test_class.test_group_name check_val_not_in(group_name, groups) @staticmethod - def create_TestGroup(test_class, override_group_name=None): + def create_TestGroup(test_class, # type: Base_Magpie_TestCase + override_group_name=None, # type: Optional[Str] + override_data=None, # type: Optional[JSON] + override_headers=None, # type: Optional[HeadersType] + override_cookies=None, # type: Optional[CookiesType] + ): # type: (...) -> JSON + """Create the test group. + + :raises AssertionError: if the request does not have expected response matching successful creation. + """ app_or_url = get_app_or_url(test_class) - data = {"group_name": override_group_name or test_class.test_group_name} + data = override_data or {} + if "group_name" not in data: + data = {"group_name": override_group_name or test_class.test_group_name} resp = test_request(app_or_url, "POST", "/groups", - headers=test_class.json_headers, - cookies=test_class.cookies, json=data) + headers=override_headers or test_class.json_headers, + cookies=override_cookies or test_class.cookies, json=data) return check_response_basic_info(resp, 201, expected_method="POST") @staticmethod def delete_TestGroup(test_class, override_group_name=None): + # type: (Base_Magpie_TestCase, Optional[Str]) -> None + """Delete the test group. + + :raises AssertionError: if the request does not have expected response matching successful deletion. + """ app_or_url = get_app_or_url(test_class) groups = TestSetup.get_RegisteredGroupsList(test_class) group_name = override_group_name or test_class.test_group_name