diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index e9c8716..b70c0b3 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -522,9 +522,11 @@ def cms_file(api, cms_file_data, cms_file_files): @pytest.fixture(scope="module") -def cms_section_params(): +def cms_section_params(api): """CMS section fixture params""" - return {"title": f"title-{get_suffix()}", "public": True, "partial_path": f"/path-{get_suffix()}"} + parent_id = api.cms_sections.list()[0]['id'] + return {"title": f"title-{get_suffix()}", "public": True, + "partial_path": f"/path-{get_suffix()}", "parent_id": parent_id} @pytest.fixture(scope="module") @@ -550,10 +552,10 @@ def cms_partial(api, cms_partial_params): @pytest.fixture(scope="module") -def cms_layout_params(cms_section): +def cms_layout_params(): """CMS layout fixture params""" return {"system_name": f"sname-{get_suffix()}", "draft": f"draft-{get_suffix()}", - "title": f"title-{get_suffix()}", "liquid_enabled": True, "section_id": cms_section['id']} + "title": f"title-{get_suffix()}", "liquid_enabled": True} @pytest.fixture(scope="module") def cms_layout(api, cms_layout_params): diff --git a/tests/integration/test_integration_cms.py b/tests/integration/test_integration_cms.py index 2249bcf..890e13f 100644 --- a/tests/integration/test_integration_cms.py +++ b/tests/integration/test_integration_cms.py @@ -1,3 +1,5 @@ +""" Test CMS API """ + import pytest from tests.integration import asserts from threescale_api import errors @@ -35,7 +37,7 @@ def test_file_can_be_updated(cms_file_data, cms_file): """ Can be file object updated? """ updated_path = cms_file['path'] + 'up' cms_file['path'] = cms_file['path'] + 'up' - # TODO https://issues.redhat.com/browse/THREESCALE-9571 + # https://issues.redhat.com/browse/THREESCALE-9571 for item in "created_at", "updated_at", "url", "title", "content_type": cms_file.pop(item) cms_file.update() @@ -70,7 +72,7 @@ def test_section_can_be_updated(cms_section_params, cms_section): """ Can be section object updated? """ updated_title = cms_section['title'] + 'up' cms_section['title'] = cms_section['title'] + 'up' - # TODO https://issues.redhat.com/browse/THREESCALE-9571 + # https://issues.redhat.com/browse/THREESCALE-9571 for item in "created_at", "updated_at": cms_section.pop(item) cms_section.update() @@ -80,14 +82,11 @@ def test_section_can_be_updated(cms_section_params, cms_section): assert cms_section['title'] == updated_title -# # bug!!! TODO https://issues.redhat.com/browse/THREESCALE-9572 -# def test_builtin_section_delete(api): -# """It is not possible to delete section partial.""" -# with pytest.raises(errors.ApiClientError) as exc_info: -# api.cms_sections.list()[0].delete() -# assert exc_info.value.code == 423 -# # TODO -# # assert exc_info.value.code == 400 +def test_builtin_section_delete(api): + """It is not possible to delete section partial.""" + with pytest.raises(errors.ApiClientError) as exc_info: + api.cms_sections.list()[0].delete() + assert exc_info.value.code == 422 # Partials @@ -109,16 +108,17 @@ def test_builtin_partial_delete(api): """It is not possible to delete builtin partial.""" with pytest.raises(errors.ApiClientError) as exc_info: api.cms_builtin_partials.list()[0].delete() - assert exc_info.value.code == 423 - # TODO https://issues.redhat.com/browse/THREESCALE-9572 - # assert exc_info.value.code == 400 + assert exc_info.value.code == 422 # user def test_partial_list(api, cms_partial): """ List all user defined partials. """ - assert len(api.cms_partials.list()) >= 1 + parts_list = api.cms_partials.list() + assert len(parts_list) >= 1 + assert all('draft' in part.entity.keys() and 'published' in part.entity.keys() + for part in parts_list) def test_partial_can_be_created(cms_partial_params, cms_partial): @@ -138,7 +138,7 @@ def test_partial_can_be_updated(cms_partial_params, cms_partial): """ Can be partial object updated? """ updated_draft = cms_partial['draft'] + 'up' cms_partial['draft'] = cms_partial['draft'] + 'up' - # TODO https://issues.redhat.com/browse/THREESCALE-9571 + # https://issues.redhat.com/browse/THREESCALE-9571 for item in "created_at", "updated_at", "published": cms_partial.pop(item) cms_partial.update() @@ -153,8 +153,7 @@ def test_partial_publish(cms_partial): assert cms_partial.entity.get('published', None) is None draft = cms_partial['draft'] cms_partial = cms_partial.publish() - # assert draft == cms_partial['draft'] bug - # assert cms_partial['published'] == cms_partial['draft'] bug + assert cms_partial['draft'] == None assert draft == cms_partial['published'] @@ -178,9 +177,7 @@ def test_builtin_page_delete(api): """It is not possible to delete builtin page.""" with pytest.raises(errors.ApiClientError) as exc_info: api.cms_builtin_pages.list()[0].delete() - assert exc_info.value.code == 423 - # TODO https://issues.redhat.com/browse/THREESCALE-9572 - # assert exc_info.value.code == 400 + assert exc_info.value.code == 422 # user @@ -208,7 +205,7 @@ def test_page_can_be_updated(cms_page_params, cms_page): """ Can be page object updated? """ updated_draft = cms_page['draft'] + 'up' cms_page['draft'] = cms_page['draft'] + 'up' - # TODO https://issues.redhat.com/browse/THREESCALE-9571 + # https://issues.redhat.com/browse/THREESCALE-9571 for item in "created_at", "updated_at", "hidden", "published": cms_page.pop(item) cms_page.update() @@ -223,8 +220,6 @@ def test_page_publish(cms_page): assert cms_page.entity.get('published', None) is None draft = cms_page['draft'] cms_page = cms_page.publish() - # assert draft == cms_page['draft'] bug - # assert cms_page['published'] == cms_page['draft'] bug assert draft == cms_page['published'] @@ -253,7 +248,7 @@ def test_layout_can_be_updated(cms_layout_params, cms_layout): """ Can be layout object updated? """ updated_draft = cms_layout['draft'] + 'up' cms_layout['draft'] = cms_layout['draft'] + 'up' - # TODO https://issues.redhat.com/browse/THREESCALE-9571 + # https://issues.redhat.com/browse/THREESCALE-9571 for item in "created_at", "updated_at", "published": cms_layout.pop(item) cms_layout.update() @@ -268,6 +263,32 @@ def test_layout_publish(cms_layout): assert cms_layout.entity.get('published', None) is None draft = cms_layout['draft'] cms_layout = cms_layout.publish() - # assert draft == cms_layout['draft'] bug - # assert cms_layout['published'] == cms_layout['draft'] bug assert draft == cms_layout['published'] + +# filters +def test_section_filter(api, cms_section): + """ Test section filtering """ + assert all(sec['parent_id'] == cms_section['parent_id'] + for sec in api.cms_sections.select_by(parent_id=cms_section['parent_id'])) + assert api.cms_sections.select_by(title=cms_section['title'])[0] == cms_section + +def test_files_filter(api, cms_file, cms_section): + """ Test files filtering """ + assert api.cms_files.select_by(section_id=cms_section['id'])[0] == cms_file + assert api.cms_files.select_by(path=cms_file['path'])[0] == cms_file + +# https://issues.redhat.com/browse/THREESCALE-9191?focusedId=22406548&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-22406548 +#def test_partial_filter(api, cms_partial, cms_section): +# """ Test partial filtering """ +# assert api.cms_partials.select_by(section_id=cms_section['id'])[0] == cms_partial +# assert api.cms_partials.select_by(system_name=cms_partial['system_name'])[0] == cms_partial + +#def test_layout_filter(api, cms_layout, cms_section): +# """ Test layout filtering """ +# assert api.cms_layouts.select_by(section_id=cms_section['id'])[0] == cms_layout +# assert api.cms_layouts.select_by(title=cms_layout['title'])[0] == cms_layout + +def test_page_filter(api, cms_section, cms_page): + """ Test page filtering """ + assert api.cms_pages.select_by(section_id=cms_section['id'])[0] == cms_page + assert api.cms_pages.select_by(title=cms_page['title'])[0] == cms_page diff --git a/threescale_api/resources.py b/threescale_api/resources.py index 2c1c938..828e2ad 100644 --- a/threescale_api/resources.py +++ b/threescale_api/resources.py @@ -910,8 +910,39 @@ def _extract_resource(self, response, collection) -> Union[List, Dict]: extracted = extracted.get(self._entity_collection) return extracted + def select_by(self, **params): + """Select by params - logical "and" Usage example: select_by(role='admin') + Filtering by some params can be done on the backend. + Filters for each class are stored in class variable FILTERS. + Filters are removed because they are not part of function "predicate". + ------------------------------------- + | Endpoint | Filters | + ------------------------------------- + | Sections #index | parent_id | + | Files #index | section_id | + | Templates #index | type, section_id | + ------------------------------------- + Args: + **params: params used for selection + Returns: List of resources + """ + log.debug("[SELECT] By params: %s", params) + + filters = {fil: params.pop(fil) for fil in self.FILTERS if fil in params} + + def predicate(item): + for (key, val) in params.items(): + if item[key] != val: + return False + return True + if filters: + return self.select(predicate=predicate, params=filters) + return self.select(predicate=predicate) + class CmsFiles(CmsClient): + FILTERS = ['parent_id'] + """ Client for files. """ def __init__(self, *args, entity_name='file', entity_collection='collection', **kwargs): super().__init__(*args, entity_name=entity_name, @@ -923,6 +954,8 @@ def url(self) -> str: class CmsSections(CmsClient): + FILTERS = ['section_id'] + """ Client for sections. """ def __init__(self, *args, entity_name='section', entity_collection='collection', **kwargs): super().__init__(*args, entity_name=entity_name, @@ -934,6 +967,8 @@ def url(self) -> str: class CmsTemplates(CmsClient): + FILTERS = ['type'] # , 'section_id'] + """ Client for templates. """ def __init__(self, *args, entity_collection='collection', **kwargs): super().__init__(*args, entity_collection=entity_collection, **kwargs) @@ -957,13 +992,28 @@ def list(self, **kwargs) -> List['DefaultResource']: Returns(List['DefaultResource]): List of resources """ log.info(self._log_message("[LIST] List", args=kwargs)) - instance = self.select_by(type=self._entity_name, **kwargs) + kwargs.setdefault("params", {}) + kwargs["params"].setdefault("content", "true") + kwargs["params"].setdefault("type", self._entity_name) + instance = self._list(**kwargs) return instance + def select(self, predicate, **kwargs) -> List['DefaultResource']: + """Select resource s based on the predicate + Args: + predicate: Predicate + **kwargs: Optional args + Returns: List of resources + """ + kwargs.setdefault("params", {}) + kwargs["params"].setdefault("content", "true") + kwargs["params"].setdefault("type", self._entity_name) + return [item for item in self._list(**kwargs) if predicate(item)] + def create(self, params: dict = None, *args, **kwargs) -> 'DefaultResource': params.update({'type': self._entity_name}) - return super().create(params=params, **kwargs) + return super().create(params=params, *args, **kwargs) class CmsPages(CmsTemplates):