Skip to content

Commit

Permalink
- add support for mixed entity names in one collection
Browse files Browse the repository at this point in the history
- add CMS files, sections, pages, layouts, partials
- add related unit tests
  • Loading branch information
mkudlej committed Mar 24, 2023
1 parent 9fb2dbd commit 99d4ee1
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 1 deletion.
51 changes: 51 additions & 0 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,3 +497,54 @@ def fields_definition(api, fields_definitions_params):
entity = api.fields_definitions.create(fields_definitions_params)
yield entity
cleanup(entity)


@pytest.fixture(scope="module")
def cms_file_data():
"""CMS file fixture data"""
return dict(path=f"/path{get_suffix()}", downloadable=True)


@pytest.fixture(scope="module")
def cms_file_files(active_docs_body):
"""CMS file fixture files.
File object can be used instead of file body 'active_docs_body',
see https://requests.readthedocs.io/en/latest/user/advanced/#post-multiple-multipart-encoded-files """
return {'attachment': (f"name-{get_suffix()}", active_docs_body, 'application/json', {'Expires': '0'})}


@pytest.fixture(scope="module")
def cms_file(api, cms_file_data, cms_file_files):
"""CMS file fixture"""
entity = api.cms_files.create(params={}, files=cms_file_files, data=cms_file_data)
yield entity
cleanup(entity)


@pytest.fixture(scope="module")
def cms_section_params(cms_file):
"""CMS section fixture params"""
return dict(title=f"title-{get_suffix()}", public=True, partial_path=f"/path-{get_suffix()}",
cms_file_ids=[cms_file['id']])


@pytest.fixture(scope="module")
def cms_section(api, cms_section_params):
"""CMS section fixture"""
entity = api.cms_sections.create(cms_section_params)
yield entity
cleanup(entity)


@pytest.fixture(scope="module")
def cms_partial_params():
"""CMS partial fixture params"""
return dict(type='partial', system_name=f"sname-{get_suffix()}", draft=f"draft-{get_suffix()}")


@pytest.fixture(scope="module")
def cms_partial(api, cms_partial_params):
"""CMS partial fixture"""
entity = api.cms_partials.create(cms_partial_params)
yield entity
cleanup(entity)
131 changes: 131 additions & 0 deletions tests/integration/test_integration_cms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
from tests.integration import asserts
from .asserts import assert_resource, assert_resource_params


# Files
def test_file_list(api, cms_file):
""" List all files. """
assert len(list(api.cms_files.list())) >= 1


def test_file_can_be_created(cms_file_data, cms_file):
""" Is file created properly? """
assert_resource(cms_file)
assert_resource_params(cms_file, cms_file_data)


def test_file_can_be_read(api, cms_file_data, cms_file):
""" It is possible to get file by ID? """
read = api.cms_files.read(cms_file.entity_id)
asserts.assert_resource(read)
asserts.assert_resource_params(read, cms_file_data)


def test_file_can_be_read_by_name(api, cms_file_data, cms_file):
""" It is possible to get file by name? """
file_path = cms_file['path']
read = api.cms_files[file_path]
asserts.assert_resource(read)
asserts.assert_resource_params(read, cms_file_data)


def test_file_can_be_updated(cms_file_data, cms_file):
""" Can be file object updated? """
updated_path = cms_file['path'] = cms_file['path'] + 'up'
cms_file.update()
assert cms_file['path'] == updated_path
updated = cms_file.read()
assert updated['path'] == updated_path
assert cms_file['path'] == updated_path


# Sections
# builtin

def test_builtin_section_list(api):
""" List all sections. """
assert len(list(api.cms_builtin_sections.list())) >= 1


def test_builtin_section_can_be_read(api):
""" It is possible to get section by ID? """
cms_section = next(api.cms_builtin_sections.list())
read = api.cms_sections.read(cms_section.entity_id)
asserts.assert_resource(read)

# user


def test_section_list(api, cms_section):
""" List all sections. """
assert len(list(api.cms_sections.list())) >= 1


def test_section_can_be_created(cms_section_params, cms_section):
""" Is section created properly? """
assert_resource(cms_section)
assert_resource_params(cms_section, cms_section_params)


def test_section_can_be_read(api, cms_section_params, cms_section):
""" It is possible to get section by ID? """
read = api.cms_sections.read(cms_section.entity_id)
asserts.assert_resource(read)
asserts.assert_resource_params(read, cms_section_params)


def test_section_can_be_updated(cms_section_params, cms_section):
""" Can be section object updated? """
updated_title = cms_section['title'] = cms_section['title'] + 'up'
cms_section.update()
assert cms_section['title'] == updated_title
updated = cms_section.read()
assert updated['title'] == updated_title
assert cms_section['title'] == updated_title

# Partials
# builtin


def test_builtin_partials_list(api):
""" List all sections. """
assert len(list(api.cms_builtin_partials.list())) >= 1


def test_builtin_partial_can_be_read(api):
""" It is possible to get partial by ID? """
cms_partial = next(api.cms_builtin_partials.list())
read = api.cms_builtin_partials.read(cms_partial.entity_id)
asserts.assert_resource(read)

# user


def test_partial_list(api, cms_partial):
""" List all user defined partials. """
assert len(list(api.cms_partials.list())) >= 1


def test_partial_can_be_created(cms_partial_params, cms_partial):
""" Is partial created properly? """
assert_resource(cms_partial)
assert_resource_params(cms_partial, cms_partial_params)


def test_partial_can_be_read(api, cms_partial_params, cms_partial):
""" It is possible to get partial by ID? """
read = api.cms_partials.read(cms_partial.entity_id)
asserts.assert_resource(read)
asserts.assert_resource_params(read, cms_partial_params)


def test_partial_can_be_updated(cms_partial_params, cms_partial):
""" Can be partial object updated? """
updated_draft = cms_partial['draft'] = cms_partial['draft'] + 'up'
cms_partial.update()
assert cms_partial['draft'] == updated_draft
updated = cms_partial.read()
assert updated['draft'] == updated_draft
assert cms_partial['draft'] == updated_draft

# # TODO pages, builtin_pages, layouts, template publishing
40 changes: 40 additions & 0 deletions threescale_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ def __init__(self, url: str, token: str,
self._invoices = resources.Invoices(self, instance_klass=resources.Invoice)
self._fields_definitions =\
resources.FieldsDefinitions(self, instance_klass=resources.FieldsDefinition)
self._cms_files = resources.CmsFiles(self, instance_klass=resources.CmsFile)
self._cms_sections = resources.CmsSections(self, instance_klass=resources.CmsSection)
self._cms_builtin_sections = resources.CmsBuiltinSections(self, instance_klass=resources.CmsSection)
self._cms_pages = resources.CmsPages(self, instance_klass=resources.CmsPage)
self._cms_builtin_pages = resources.CmsBuiltinPages(self, instance_klass=resources.CmsPage)
self._cms_layouts = resources.CmsLayouts(self, instance_klass=resources.CmsLayout)
self._cms_builtin_partials = resources.CmsBuiltinPartials(self, instance_klass=resources.CmsPartial)
self._cms_partials = resources.CmsPartials(self, instance_klass=resources.CmsPartial)

if wait >= 0:
self.wait_for_tenant()
Expand Down Expand Up @@ -255,6 +263,38 @@ def invoices(self) -> resources.Invoices:
def fields_definitions(self) -> resources.FieldsDefinitions:
return self._fields_definitions

@property
def cms_files(self) -> resources.CmsFiles:
return self._cms_files

@property
def cms_sections(self) -> resources.CmsSections:
return self._cms_sections

@property
def cms_builtin_sections(self) -> resources.CmsBuiltinSections:
return self._cms_builtin_sections

@property
def cms_pages(self) -> resources.CmsPages:
return self._cms_pages

@property
def cms_builtin_pages(self) -> resources.CmsBuiltinPages:
return self._cms_builtin_pages

@property
def cms_layouts(self) -> resources.CmsLayouts:
return self._cms_layouts

@property
def cms_partials(self) -> resources.CmsPartials:
return self._cms_partials

@property
def cms_builtin_partials(self) -> resources.CmsBuiltinPartials:
return self._cms_builtin_partials


class RestApiClient:
def __init__(self, url: str, token: str, throws: bool = True, ssl_verify: bool = True):
Expand Down
113 changes: 113 additions & 0 deletions threescale_api/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,94 @@ def __init__(self, *args, entity_name='fields_definition',
def url(self) -> str:
return self.threescale_client.admin_api_url + '/fields_definitions'


class CmsClient(DefaultClient):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def _list(self, **kwargs):
if "page" in kwargs.get("params", {}):
return super()._list(**kwargs)

pagenum = 1

kwargs = kwargs.copy()
if "params" not in kwargs:
kwargs["params"] = {}

kwargs["params"]["page"] = pagenum
kwargs["params"]["per_page"] = 100

page = super()._list(**kwargs)

while len(page):
for i in page:
yield i
pagenum += 1
kwargs["params"]["page"] = pagenum
page = super()._list(**kwargs)

def __iter__(self):
return self._list()


class CmsFiles(CmsClient):
def __init__(self, *args, entity_name='file', entity_collection='files', **kwargs):
super().__init__(*args, entity_name=entity_name,
entity_collection=entity_collection, **kwargs)

@property
def url(self) -> str:
return self.threescale_client.admin_api_url + '/cms/files'


class CmsSections(CmsClient):
def __init__(self, *args, entity_name='section', entity_collection='sections', **kwargs):
super().__init__(*args, entity_name=entity_name,
entity_collection=entity_collection, **kwargs)

@property
def url(self) -> str:
return self.threescale_client.admin_api_url + '/cms/sections'

class CmsBuiltinSections(CmsSections):
def __init__(self, *args, entity_name='builtin_section', entity_collection='sections', **kwargs):
super().__init__(*args, entity_name=entity_name,
entity_collection=entity_collection, **kwargs)


class CmsTemplates(CmsClient):
def __init__(self, *args, entity_collection='templates', **kwargs):
super().__init__(*args, entity_collection=entity_collection, **kwargs)

@property
def url(self) -> str:
return self.threescale_client.admin_api_url + '/cms/templates'


class CmsPages(CmsTemplates):
def __init__(self, *args, entity_name='page', **kwargs):
super().__init__(*args, entity_name=entity_name, **kwargs)


class CmsBuiltinPages(CmsTemplates):
def __init__(self, *args, entity_name='builtin_page', **kwargs):
super().__init__(*args, entity_name=entity_name, **kwargs)


class CmsLayouts(CmsTemplates):
def __init__(self, *args, entity_name='layout', **kwargs):
super().__init__(*args, entity_name=entity_name, **kwargs)


class CmsPartials(CmsTemplates):
def __init__(self, *args, entity_name='partial', **kwargs):
super().__init__(*args, entity_name=entity_name, **kwargs)


class CmsBuiltinPartials(CmsTemplates):
def __init__(self, *args, entity_name='builtin_partial', **kwargs):
super().__init__(*args, entity_name=entity_name, **kwargs)
# Resources


Expand Down Expand Up @@ -1462,3 +1550,28 @@ def __init__(self, entity_name='name', **kwargs):
class DevPortalAuthProvider(DefaultResource):
def __init__(self, entity_name='name', **kwargs):
super().__init__(entity_name=entity_name, **kwargs)


class CmsFile(DefaultResource):
def __init__(self, entity_name='path', **kwargs):
super().__init__(entity_name=entity_name, **kwargs)


class CmsSection(DefaultResource):
def __init__(self, entity_name='id', **kwargs):
super().__init__(entity_name=entity_name, **kwargs)


class CmsPage(DefaultResource):
def __init__(self, entity_name='system_name', **kwargs):
super().__init__(entity_name=entity_name, **kwargs)


class CmsLayout(DefaultResource):
def __init__(self, entity_name='system_name', **kwargs):
super().__init__(entity_name=entity_name, **kwargs)


class CmsPartial(DefaultResource):
def __init__(self, entity_name='system_name', **kwargs):
super().__init__(entity_name=entity_name, **kwargs)
2 changes: 1 addition & 1 deletion threescale_api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def extract_response(response: requests.Response, entity: str = None,
if collection and collection in extracted:
extracted = extracted.get(collection)
if isinstance(extracted, list):
return [value.get(entity) for value in extracted]
return [value.get(entity) for value in extracted if entity in value]
if entity in extracted.keys():
return extracted.get(entity)
return extracted
Expand Down

0 comments on commit 99d4ee1

Please sign in to comment.