From 79cce5e89c62500e1879041387dabef4d8e7e1e2 Mon Sep 17 00:00:00 2001 From: Mikel Larreategi Date: Sat, 28 Oct 2023 23:24:29 +0200 Subject: [PATCH] backport #1465: @site and @navroot endpoints (#1702) * backport #1465: @site and @navroot endpoints * fix * black * fix * remove duplicated import * fixes * black * f-strings are not available in python2 * adapt for Plone 4.3 * adapt for Plone 4.3 * adapt for Plone 4.3 * adapt for Plone 4.3 * skip multilingual tests when not installed * skip multilingual tests when not installed * remove unneeded * make tests for Plone 5 * make tests for Plone 5 * make tests for Plone 5 --------- Co-authored-by: David Glick --- docs/source/endpoints/index.md | 61 ++++ docs/source/endpoints/navroot.md | 158 +++++++++++ docs/source/endpoints/site.md | 25 ++ docs/source/glossary.md | 67 +++++ docs/source/index.md | 43 +++ news/1464.feature | 1 + src/plone/restapi/services/configure.zcml | 2 + .../restapi/services/navroot/__init__.py | 0 .../restapi/services/navroot/configure.zcml | 23 ++ src/plone/restapi/services/navroot/get.py | 39 +++ src/plone/restapi/services/site/__init__.py | 0 .../restapi/services/site/configure.zcml | 14 + src/plone/restapi/services/site/get.py | 77 +++++ src/plone/restapi/testing.py | 7 +- .../tests/http-examples/collection.resp | 3 + .../http-examples/collection_fullobjects.resp | 12 + .../tests/http-examples/content_get.resp | 3 + .../http-examples/content_get_folder.resp | 3 + .../content_patch_representation.resp | 3 + .../tests/http-examples/content_post.resp | 3 + .../restapi/tests/http-examples/document.resp | 3 + .../restapi/tests/http-examples/event.resp | 3 + .../tests/http-examples/expansion.resp | 3 + .../http-examples/expansion_expanded.resp | 3 + .../expansion_expanded_full.resp | 3 + .../restapi/tests/http-examples/file.resp | 3 + .../restapi/tests/http-examples/folder.resp | 3 + .../restapi/tests/http-examples/image.resp | 3 + .../tests/http-examples/jwt_logged_in.resp | 3 + .../restapi/tests/http-examples/link.resp | 3 + .../navroot_lang_content_get.req | 3 + .../navroot_lang_content_get.resp | 91 ++++++ .../http-examples/navroot_lang_folder_get.req | 3 + .../navroot_lang_folder_get.resp | 91 ++++++ .../tests/http-examples/navroot_site_get.req | 3 + .../tests/http-examples/navroot_site_get.resp | 65 +++++ .../navroot_standard_site_content_get.req | 3 + .../navroot_standard_site_content_get.resp | 76 +++++ ...ot_standard_site_content_get_expansion.req | 3 + ...t_standard_site_content_get_expansion.resp | 149 ++++++++++ .../navroot_standard_site_get.req | 3 + .../navroot_standard_site_get.resp | 76 +++++ .../navroot_standard_site_get_expansion.req | 3 + .../navroot_standard_site_get_expansion.resp | 143 ++++++++++ .../restapi/tests/http-examples/newsitem.resp | 3 + .../http-examples/search_fullobjects.resp | 3 + .../restapi/tests/http-examples/site_get.req | 3 + .../restapi/tests/http-examples/site_get.resp | 22 ++ .../site_get_expand_lang_folder.req | 3 + .../site_get_expand_lang_folder.resp | 173 +++++++++++ .../site_get_expand_lang_folder_content.req | 3 + .../site_get_expand_lang_folder_content.resp | 165 +++++++++++ .../http-examples/site_get_expand_navroot.req | 3 + .../site_get_expand_navroot.resp | 121 ++++++++ .../restapi/tests/http-examples/siteroot.resp | 3 + .../translations_link_on_post.resp | 3 + .../workingcopy_baseline_get.resp | 110 +++---- .../http-examples/workingcopy_wc_get.resp | 184 ++++++++---- src/plone/restapi/tests/test_documentation.py | 134 ++++++--- .../restapi/tests/test_services_navroot.py | 268 ++++++++++++++++++ src/plone/restapi/tests/test_services_site.py | 57 ++++ 61 files changed, 2395 insertions(+), 149 deletions(-) create mode 100644 docs/source/endpoints/index.md create mode 100644 docs/source/endpoints/navroot.md create mode 100644 docs/source/endpoints/site.md create mode 100644 docs/source/glossary.md create mode 100644 docs/source/index.md create mode 100644 news/1464.feature create mode 100644 src/plone/restapi/services/navroot/__init__.py create mode 100644 src/plone/restapi/services/navroot/configure.zcml create mode 100644 src/plone/restapi/services/navroot/get.py create mode 100644 src/plone/restapi/services/site/__init__.py create mode 100644 src/plone/restapi/services/site/configure.zcml create mode 100644 src/plone/restapi/services/site/get.py create mode 100644 src/plone/restapi/tests/http-examples/navroot_lang_content_get.req create mode 100644 src/plone/restapi/tests/http-examples/navroot_lang_content_get.resp create mode 100644 src/plone/restapi/tests/http-examples/navroot_lang_folder_get.req create mode 100644 src/plone/restapi/tests/http-examples/navroot_lang_folder_get.resp create mode 100644 src/plone/restapi/tests/http-examples/navroot_site_get.req create mode 100644 src/plone/restapi/tests/http-examples/navroot_site_get.resp create mode 100644 src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.req create mode 100644 src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.resp create mode 100644 src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.req create mode 100644 src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.resp create mode 100644 src/plone/restapi/tests/http-examples/navroot_standard_site_get.req create mode 100644 src/plone/restapi/tests/http-examples/navroot_standard_site_get.resp create mode 100644 src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.req create mode 100644 src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.resp create mode 100644 src/plone/restapi/tests/http-examples/site_get.req create mode 100644 src/plone/restapi/tests/http-examples/site_get.resp create mode 100644 src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.req create mode 100644 src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.resp create mode 100644 src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.req create mode 100644 src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.resp create mode 100644 src/plone/restapi/tests/http-examples/site_get_expand_navroot.req create mode 100644 src/plone/restapi/tests/http-examples/site_get_expand_navroot.resp create mode 100644 src/plone/restapi/tests/test_services_navroot.py create mode 100644 src/plone/restapi/tests/test_services_site.py diff --git a/docs/source/endpoints/index.md b/docs/source/endpoints/index.md new file mode 100644 index 0000000000..239b6577ad --- /dev/null +++ b/docs/source/endpoints/index.md @@ -0,0 +1,61 @@ +--- +myst: + html_meta: + "description": "Usage of the Plone REST API." + "property=og:description": "Usage of the Plone REST API." + "property=og:title": "Usage of the Plone REST API" + "keywords": "Plone, plone.restapi, REST, API, Usage" +--- + +(restapi-endpoints)= + +# Endpoints + +This part of the documentation explains the endpoints of Plone REST API. + +```{toctree} +:caption: Table of Contents +:maxdepth: 2 + +addons +aliases +breadcrumbs +comments +content-types +content-rules +contextnavigation +controlpanels +copymove +database +email-notification +email-send +expansion +groups +history +linkintegrity +locking +navigation +navroot +actions +portrait +principals +querystring +querystringsearch +registry +relations +roles +searching +site +system +tiles +transactions +translations +tusupload +types +upgrade +users +userschema +vocabularies +workflow +workingcopy +``` diff --git a/docs/source/endpoints/navroot.md b/docs/source/endpoints/navroot.md new file mode 100644 index 0000000000..30fd610177 --- /dev/null +++ b/docs/source/endpoints/navroot.md @@ -0,0 +1,158 @@ +--- +html_meta: + "description": "Navigation root is a concept that provides a way to root catalog queries, searches, and breadcrumbs in Plone." + "property=og:description": "Navigation root is a concept that provides a way to root catalog queries, searches, and breadcrumbs in Plone." + "property=og:title": "Navigation Root" + "keywords": "Plone, plone.restapi, REST, API, site, navigation root" +--- + +(navigation-root-label)= + +# Navigation root + +Plone has a concept called {term}`navigation root` which provides a way to root catalog queries, searches, breadcrumbs, and so on in a given section of the site. +This feature is useful when working with subsites or multilingual sites, because it allows the site manager to restrict searches or navigation queries to a specific location in the site. + +This navigation root information is different depending on the context of the request. +For instance, in a default multilingual site when browsing the contents inside a language folder such as `www.domain.com/en`, the context is `en` and its navigation root will be `/en/`. +In a non-multilingual site, the context is the root of the site such as `www.domain.com` and the navigation root will be `/`. + +To get the information about the navigation root, the REST API has a `@navroot` contextual endpoint. +For instance, send a `GET` request to the `@navroot` endpoint at the root of the site: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/navroot_standard_site_get.req +``` + +The response will contain the navigation root information for the site: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/navroot_standard_site_get.resp +:language: http +``` + +If you request the `@navroot` of a given content item in the site: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.req +``` + +The response will contain the navigation root information in the context of that content item: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.resp +:language: http +``` + +In a multilingual site, the root of the site will work as usual: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/navroot_site_get.req +``` + +The response will contain the navigation root information of the root of the site: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/navroot_site_get.resp +:language: http +``` + +In a multilingual site where the language folder is the navigation root, the response has the language folder information: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/navroot_lang_folder_get.req +``` + +The response will contain the navigation root information for the language folder: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/navroot_lang_folder_get.resp +:language: http +``` + +In a multilingual site, if the navigation root is requested for content inside a language folder: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/navroot_lang_content_get.req +``` + +The response has the language folder information as a navigation root: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/navroot_lang_content_get.resp +:language: http +``` + +(navigation-root-expansion-label)= + +## Expansion + +This endpoint can be used with the {doc}`expansion` mechanism which allows getting more information about a content item in one query, avoiding unnecessary requests. + +If a simple `GET` request is made on the content item, a new entry will be shown on the `@components` entry with the URL of the `@navroot` endpoint. + +In a standard site when querying the site root: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.req +``` + +The response will contain information of the site root with the navigation expanded: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.resp +:language: http +``` + +When querying a content item inside the root: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.req +``` + +The response will contain the information of that content item with its navigation root information expanded: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.resp +:language: http +``` + +In a multilingual site, it works the same. +Use the request: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/site_get_expand_navroot.req +``` + +And the response will contain the navigation root information pointing to the root of the site: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/site_get_expand_navroot.resp +:language: http +``` + +It will also work with language root folders that are navigation roots: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.req +``` + +The response will contain the navigation root information expanded: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.resp +:language: http +``` + +And also for content inside the language root folders: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.req +``` + +The response will include the expanded information pointing to the language root: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.resp +:language: http +``` diff --git a/docs/source/endpoints/site.md b/docs/source/endpoints/site.md new file mode 100644 index 0000000000..40e76bf37c --- /dev/null +++ b/docs/source/endpoints/site.md @@ -0,0 +1,25 @@ +--- +html_meta: + "description": "Site endpoint for Plone REST API" + "property=og:title": "Site endpoint for Plone REST API" + "property=og:description": "Site endpoint for Plone REST API" + "keywords": "Plone, plone.restapi, REST, API, site, navigation root" +--- + +# Site + +The `@site` endpoint provides general site-wide information, such as the site title, logo, and other information. +It uses the `zope2.View` permission, which requires appropriate authorization. + +Send a `GET` request to the `@site` endpoint: + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/site_get.req +``` + +The response will contain the site information: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/site_get.resp +:language: http +``` diff --git a/docs/source/glossary.md b/docs/source/glossary.md new file mode 100644 index 0000000000..74adaaa75b --- /dev/null +++ b/docs/source/glossary.md @@ -0,0 +1,67 @@ +--- +myst: + html_meta: + "description": "plone.restapi Glossary" + "property=og:description": "plone.restapi Glossary" + "property=og:title": "Glossary" + "keywords": "Plone, plone.restapi, REST, API, Glossary" +--- + +# Glossary + +```{glossary} +:sorted: true + +REST + REST stands for [Representational State Transfer](https://en.wikipedia.org/wiki/Representational_state_transfer). It is a software architectural principle to create loosely coupled web APIs. + +workflow + A concept in Plone (and other CMS's) whereby a content object can be in a number of states (private, public, etcetera) and uses transitions to change between them (e.g. "publish", "approve", "reject", "retract"). See the [Plone docs on Workflow](https://5.docs.plone.org/working-with-content/collaboration-and-workflow/) + +HTTP-Request +HTTP Request +Request +Requests + The initial action performed by a web client to communicate with a server. The {term}`Request` is usually followed by a {term}`Response` by the server, either synchronous or asynchronous (which is more complex to handle on the user side) + +HTTP-Response +HTTP Response +Response + Answer of or action by the server that is executed or send to the client after the {term}`Request` is processed. + +HTTP-Header +HTTP Header +Header + The part of the communication of the client with the server that provides the initialisation of the communication of a {term}`Request`. + +HTTP-Verb +HTTP Verb +Verb + One of the basic actions that can be requested to be executed by the server (on an object) based on the {term}`Request`. + +Object URL + The target object of the {term}`Request` + +Authorization Header + Part of the {term}`Request` that is responsible for the authentication related to the right user or service to ask for a {term}`Response`. + +Accept Header + Part of the {term}`Request` that is responsible to define the expected type of data to be accepted by the client in the {term}`Response`. + +Authentication Method + Access restriction provided by the connection chain to the server exposed to the client. + +Basic Auth + A simple {term}`Authentication Method` referenced in the {term}`Authorization Header` that needs to be provided by the server. + +content rule + A content rule will automatically perform an action when a certain event, known as a {term}`trigger`, takes place. + +trigger + A trigger is an event in Plone that causes the execution of defined actions. + Example triggers include object modified, user logged in, and workflow state changed. + +navigation root + An object marked as a navigation root provides a way to root catalog queries, searches, breadcrumbs, and so on, into that object. + +``` diff --git a/docs/source/index.md b/docs/source/index.md new file mode 100644 index 0000000000..1560bc7bd4 --- /dev/null +++ b/docs/source/index.md @@ -0,0 +1,43 @@ +--- +myst: + html_meta: + "description": "A RESTful API for Plone." + "property=og:description": "A RESTful API for Plone." + "property=og:title": "REST API" + "keywords": "Plone, plone.restapi, REST, API" +--- + +% plone.restapi documentation master file, created by +% sphinx-quickstart on Mon Apr 28 13:04:12 2014. +% You can adapt this file completely to your liking, but it should at least +% contain the root `toctree` directive. + +# REST API + +A RESTful API for Plone. + +```{toctree} +:caption: Table of Contents +:maxdepth: 2 + +introduction +usage/index +endpoints/index +upgrade-guide +contributing/index +``` + +```{eval-rst} +.. include:: ../../README.rst +``` + +## Appendix and Glossary + +```{toctree} +http-status-codes +/glossary +``` + +## Index + +- {ref}`genindex` diff --git a/news/1464.feature b/news/1464.feature new file mode 100644 index 0000000000..5e52088d8b --- /dev/null +++ b/news/1464.feature @@ -0,0 +1 @@ +Added `@site` and `@navroot` endpoints. @erral diff --git a/src/plone/restapi/services/configure.zcml b/src/plone/restapi/services/configure.zcml index b9f4fac9db..0a526c7690 100644 --- a/src/plone/restapi/services/configure.zcml +++ b/src/plone/restapi/services/configure.zcml @@ -23,6 +23,7 @@ + @@ -30,6 +31,7 @@ + diff --git a/src/plone/restapi/services/navroot/__init__.py b/src/plone/restapi/services/navroot/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/plone/restapi/services/navroot/configure.zcml b/src/plone/restapi/services/navroot/configure.zcml new file mode 100644 index 0000000000..a9a8451388 --- /dev/null +++ b/src/plone/restapi/services/navroot/configure.zcml @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/src/plone/restapi/services/navroot/get.py b/src/plone/restapi/services/navroot/get.py new file mode 100644 index 0000000000..bb65295387 --- /dev/null +++ b/src/plone/restapi/services/navroot/get.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +from plone.restapi.interfaces import IExpandableElement, ISerializeToJson +from plone.restapi.services import Service +from zope.component import adapter +from zope.component import getMultiAdapter +from zope.interface import implementer +from zope.interface import Interface + + +@implementer(IExpandableElement) +@adapter(Interface, Interface) +class Navroot: + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self, expand=False): + result = {"navroot": {"@id": "{}/@navroot".format(self.context.absolute_url())}} + if not expand: + return result + + portal_state = getMultiAdapter( + (self.context, self.request), name="plone_portal_state" + ) + # We need to unset expansion here, otherwise we get infinite recursion + self.request.form["expand"] = "" + + result["navroot"]["navroot"] = getMultiAdapter( + (portal_state.navigation_root(), self.request), + ISerializeToJson, + )() + + return result + + +class NavrootGet(Service): + def reply(self): + navroot = Navroot(self.context, self.request) + return navroot(expand=True)["navroot"] diff --git a/src/plone/restapi/services/site/__init__.py b/src/plone/restapi/services/site/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/plone/restapi/services/site/configure.zcml b/src/plone/restapi/services/site/configure.zcml new file mode 100644 index 0000000000..76bc963b44 --- /dev/null +++ b/src/plone/restapi/services/site/configure.zcml @@ -0,0 +1,14 @@ + + + + + diff --git a/src/plone/restapi/services/site/get.py b/src/plone/restapi/services/site/get.py new file mode 100644 index 0000000000..fdff8d46f7 --- /dev/null +++ b/src/plone/restapi/services/site/get.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +from plone.registry.interfaces import IRegistry +from plone.restapi.interfaces import IExpandableElement +from plone.restapi.services import Service +from zope.component import adapter +from zope.component import getMultiAdapter +from zope.component import getUtility +from zope.interface import implementer +from zope.interface import Interface + +try: + from Products.CMFPlone.utils import getSiteLogo +except ImportError: + getSiteLogo = None +try: + from Products.CMFPlone.interfaces import IImagingSchema +except ImportError: + IImagingSchema = None +try: + from Products.CMFPlone.interfaces import ISiteSchema +except ImportError: + ISiteSchema = None + + +@implementer(IExpandableElement) +@adapter(Interface, Interface) +class Site: + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self, expand=False): + result = {"site": {"@id": "{}/@site".format(self.context.absolute_url())}} + if not expand: + return result + + portal_state = getMultiAdapter( + (self.context, self.request), name="plone_portal_state" + ) + registry = getUtility(IRegistry) + + if ISiteSchema is not None: + site_settings = registry.forInterface( + ISiteSchema, prefix="plone", check=False + ) + result["site"].update( + { + "plone.site_logo": site_settings.site_logo + and getSiteLogo() + or None, + "plone.robots_txt": site_settings.robots_txt, + } + ) + + if IImagingSchema is not None: + image_settings = registry.forInterface( + IImagingSchema, prefix="plone", check=False + ) + result["site"].update( + { + "plone.allowed_sizes": image_settings.allowed_sizes, + } + ) + + result["site"].update( + { + "plone.site_title": portal_state.portal_title(), + } + ) + + return result + + +class SiteGet(Service): + def reply(self): + site = Site(self.context, self.request) + return site(expand=True)["site"] diff --git a/src/plone/restapi/testing.py b/src/plone/restapi/testing.py index 9e35799b83..57530693e2 100644 --- a/src/plone/restapi/testing.py +++ b/src/plone/restapi/testing.py @@ -32,6 +32,7 @@ from zope.configuration import xmlconfig from zope.interface import implementer + import collective.MockMailHost import os import pkg_resources @@ -253,7 +254,8 @@ def setUpPloneSite(self, portal): PLONE_RESTAPI_DX_PAM_FIXTURE = PloneRestApiDXPAMLayer() PLONE_RESTAPI_DX_PAM_INTEGRATION_TESTING = IntegrationTesting( - bases=(PLONE_RESTAPI_DX_PAM_FIXTURE,), name="PloneRestApiDXPAMLayer:Integration" + bases=(PLONE_RESTAPI_DX_PAM_FIXTURE,), + name="PloneRestApiDXPAMLayer:Integration", ) PLONE_RESTAPI_DX_PAM_FUNCTIONAL_TESTING = FunctionalTesting( bases=(PLONE_RESTAPI_DX_PAM_FIXTURE, z2.ZSERVER_FIXTURE), @@ -339,7 +341,8 @@ def setUpPloneSite(self, portal): PLONE_RESTAPI_BLOCKS_FIXTURE = PloneRestApIBlocksLayer() PLONE_RESTAPI_BLOCKS_INTEGRATION_TESTING = IntegrationTesting( - bases=(PLONE_RESTAPI_BLOCKS_FIXTURE,), name="PloneRestApIBlocksLayer:Integration" + bases=(PLONE_RESTAPI_BLOCKS_FIXTURE,), + name="PloneRestApIBlocksLayer:Integration", ) PLONE_RESTAPI_BLOCKS_FUNCTIONAL_TESTING = FunctionalTesting( bases=(PLONE_RESTAPI_BLOCKS_FIXTURE, z2.ZSERVER_FIXTURE), diff --git a/src/plone/restapi/tests/http-examples/collection.resp b/src/plone/restapi/tests/http-examples/collection.resp index 8af2a37629..5b16ad41fb 100644 --- a/src/plone/restapi/tests/http-examples/collection.resp +++ b/src/plone/restapi/tests/http-examples/collection.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/collection/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/collection/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/collection/@types" }, diff --git a/src/plone/restapi/tests/http-examples/collection_fullobjects.resp b/src/plone/restapi/tests/http-examples/collection_fullobjects.resp index b924bf7145..80231930e4 100644 --- a/src/plone/restapi/tests/http-examples/collection_fullobjects.resp +++ b/src/plone/restapi/tests/http-examples/collection_fullobjects.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/collection/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/collection/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/collection/@types" }, @@ -71,6 +74,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/front-page/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/front-page/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/front-page/@types" }, @@ -142,6 +148,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/doc1/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/doc1/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/doc1/@types" }, @@ -214,6 +223,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/doc2/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/doc2/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/doc2/@types" }, diff --git a/src/plone/restapi/tests/http-examples/content_get.resp b/src/plone/restapi/tests/http-examples/content_get.resp index 561934faf5..f320965547 100644 --- a/src/plone/restapi/tests/http-examples/content_get.resp +++ b/src/plone/restapi/tests/http-examples/content_get.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/folder/my-document/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/folder/my-document/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/folder/my-document/@types" }, diff --git a/src/plone/restapi/tests/http-examples/content_get_folder.resp b/src/plone/restapi/tests/http-examples/content_get_folder.resp index 3366895925..c64dd798e6 100644 --- a/src/plone/restapi/tests/http-examples/content_get_folder.resp +++ b/src/plone/restapi/tests/http-examples/content_get_folder.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/folder/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/folder/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/folder/@types" }, diff --git a/src/plone/restapi/tests/http-examples/content_patch_representation.resp b/src/plone/restapi/tests/http-examples/content_patch_representation.resp index 6c88900792..f601f0d4d1 100644 --- a/src/plone/restapi/tests/http-examples/content_patch_representation.resp +++ b/src/plone/restapi/tests/http-examples/content_patch_representation.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/folder/my-document/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/folder/my-document/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/folder/my-document/@types" }, diff --git a/src/plone/restapi/tests/http-examples/content_post.resp b/src/plone/restapi/tests/http-examples/content_post.resp index febf385b50..542cc3c9e0 100644 --- a/src/plone/restapi/tests/http-examples/content_post.resp +++ b/src/plone/restapi/tests/http-examples/content_post.resp @@ -16,6 +16,9 @@ Location: http://localhost:55001/plone/folder/my-document "navigation": { "@id": "http://localhost:55001/plone/folder/my-document/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/folder/my-document/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/folder/my-document/@types" }, diff --git a/src/plone/restapi/tests/http-examples/document.resp b/src/plone/restapi/tests/http-examples/document.resp index 783586cada..0e23e1c1ae 100644 --- a/src/plone/restapi/tests/http-examples/document.resp +++ b/src/plone/restapi/tests/http-examples/document.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/front-page/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/front-page/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/front-page/@types" }, diff --git a/src/plone/restapi/tests/http-examples/event.resp b/src/plone/restapi/tests/http-examples/event.resp index b4765e4e69..aad5e18d0b 100644 --- a/src/plone/restapi/tests/http-examples/event.resp +++ b/src/plone/restapi/tests/http-examples/event.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/event/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/event/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/event/@types" }, diff --git a/src/plone/restapi/tests/http-examples/expansion.resp b/src/plone/restapi/tests/http-examples/expansion.resp index 783586cada..0e23e1c1ae 100644 --- a/src/plone/restapi/tests/http-examples/expansion.resp +++ b/src/plone/restapi/tests/http-examples/expansion.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/front-page/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/front-page/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/front-page/@types" }, diff --git a/src/plone/restapi/tests/http-examples/expansion_expanded.resp b/src/plone/restapi/tests/http-examples/expansion_expanded.resp index b554f1f8c2..acdbd61bdf 100644 --- a/src/plone/restapi/tests/http-examples/expansion_expanded.resp +++ b/src/plone/restapi/tests/http-examples/expansion_expanded.resp @@ -22,6 +22,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/front-page/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/front-page/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/front-page/@types" }, diff --git a/src/plone/restapi/tests/http-examples/expansion_expanded_full.resp b/src/plone/restapi/tests/http-examples/expansion_expanded_full.resp index e7b16baeaf..22fa73c0e6 100644 --- a/src/plone/restapi/tests/http-examples/expansion_expanded_full.resp +++ b/src/plone/restapi/tests/http-examples/expansion_expanded_full.resp @@ -138,6 +138,9 @@ Content-Type: application/json } ] }, + "navroot": { + "@id": "http://localhost:55001/plone/front-page/@navroot" + }, "types": [ { "@id": "http://localhost:55001/plone/@types/Collection", diff --git a/src/plone/restapi/tests/http-examples/file.resp b/src/plone/restapi/tests/http-examples/file.resp index 47556c6c91..30f8f8e02d 100644 --- a/src/plone/restapi/tests/http-examples/file.resp +++ b/src/plone/restapi/tests/http-examples/file.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/file/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/file/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/file/@types" }, diff --git a/src/plone/restapi/tests/http-examples/folder.resp b/src/plone/restapi/tests/http-examples/folder.resp index 5f6af7eeab..7984400c4f 100644 --- a/src/plone/restapi/tests/http-examples/folder.resp +++ b/src/plone/restapi/tests/http-examples/folder.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/folder/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/folder/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/folder/@types" }, diff --git a/src/plone/restapi/tests/http-examples/image.resp b/src/plone/restapi/tests/http-examples/image.resp index 12d9158fd7..dd2d91e4f2 100644 --- a/src/plone/restapi/tests/http-examples/image.resp +++ b/src/plone/restapi/tests/http-examples/image.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/image/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/image/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/image/@types" }, diff --git a/src/plone/restapi/tests/http-examples/jwt_logged_in.resp b/src/plone/restapi/tests/http-examples/jwt_logged_in.resp index 7e8dca4f6c..dd45f70974 100644 --- a/src/plone/restapi/tests/http-examples/jwt_logged_in.resp +++ b/src/plone/restapi/tests/http-examples/jwt_logged_in.resp @@ -14,6 +14,9 @@ Content-Type: application/json }, "navigation": { "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot" } }, "@id": "http://localhost:55001/plone/", diff --git a/src/plone/restapi/tests/http-examples/link.resp b/src/plone/restapi/tests/http-examples/link.resp index 7913206eab..3b5fc65eeb 100644 --- a/src/plone/restapi/tests/http-examples/link.resp +++ b/src/plone/restapi/tests/http-examples/link.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/link/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/link/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/link/@types" }, diff --git a/src/plone/restapi/tests/http-examples/navroot_lang_content_get.req b/src/plone/restapi/tests/http-examples/navroot_lang_content_get.req new file mode 100644 index 0000000000..a16879755c --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_lang_content_get.req @@ -0,0 +1,3 @@ +GET /plone/en/test-document/@navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/navroot_lang_content_get.resp b/src/plone/restapi/tests/http-examples/navroot_lang_content_get.resp new file mode 100644 index 0000000000..e02abd7099 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_lang_content_get.resp @@ -0,0 +1,91 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@id": "http://localhost:55001/plone/en/test-document/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/en/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/en/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/en/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/en/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/en/@navroot" + }, + "translations": { + "@id": "http://localhost:55001/plone/en/@translations" + }, + "types": { + "@id": "http://localhost:55001/plone/en/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/en/@workflow" + } + }, + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "UID": "00000000000000000000000000000001", + "allow_discussion": false, + "contributors": [], + "created": "1995-07-31T13:45:00", + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": true, + "expires": null, + "id": "en", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/en/assets", + "@type": "LIF", + "description": "", + "review_state": "published", + "title": "Assets" + }, + { + "@id": "http://localhost:55001/plone/en/test-document", + "@type": "Document", + "description": "", + "review_state": "private", + "title": "Test document" + } + ], + "items_total": 2, + "language": { + "title": "English", + "token": "en" + }, + "layout": "folder_listing", + "lock": {}, + "modified": "1995-07-31T17:30:00", + "next_item": { + "@id": "http://localhost:55001/plone/de", + "@type": "LRF", + "description": "", + "title": "Deutsch" + }, + "parent": { + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", + "title": "Plone site" + }, + "previous_item": {}, + "review_state": "published", + "rights": "", + "subjects": [], + "title": "English", + "version": "current" + } +} diff --git a/src/plone/restapi/tests/http-examples/navroot_lang_folder_get.req b/src/plone/restapi/tests/http-examples/navroot_lang_folder_get.req new file mode 100644 index 0000000000..5bbb15c017 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_lang_folder_get.req @@ -0,0 +1,3 @@ +GET /plone/en/@navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/navroot_lang_folder_get.resp b/src/plone/restapi/tests/http-examples/navroot_lang_folder_get.resp new file mode 100644 index 0000000000..bc30c5d934 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_lang_folder_get.resp @@ -0,0 +1,91 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@id": "http://localhost:55001/plone/en/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/en/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/en/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/en/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/en/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/en/@navroot" + }, + "translations": { + "@id": "http://localhost:55001/plone/en/@translations" + }, + "types": { + "@id": "http://localhost:55001/plone/en/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/en/@workflow" + } + }, + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "UID": "00000000000000000000000000000001", + "allow_discussion": false, + "contributors": [], + "created": "1995-07-31T13:45:00", + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": true, + "expires": null, + "id": "en", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/en/assets", + "@type": "LIF", + "description": "", + "review_state": "published", + "title": "Assets" + }, + { + "@id": "http://localhost:55001/plone/en/test-document", + "@type": "Document", + "description": "", + "review_state": "private", + "title": "Test document" + } + ], + "items_total": 2, + "language": { + "title": "English", + "token": "en" + }, + "layout": "folder_listing", + "lock": {}, + "modified": "1995-07-31T17:30:00", + "next_item": { + "@id": "http://localhost:55001/plone/de", + "@type": "LRF", + "description": "", + "title": "Deutsch" + }, + "parent": { + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", + "title": "Plone site" + }, + "previous_item": {}, + "review_state": "published", + "rights": "", + "subjects": [], + "title": "English", + "version": "current" + } +} diff --git a/src/plone/restapi/tests/http-examples/navroot_site_get.req b/src/plone/restapi/tests/http-examples/navroot_site_get.req new file mode 100644 index 0000000000..cc9c5ca1e8 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_site_get.req @@ -0,0 +1,3 @@ +GET /plone/@navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/navroot_site_get.resp b/src/plone/restapi/tests/http-examples/navroot_site_get.resp new file mode 100644 index 0000000000..5879b552e3 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_site_get.resp @@ -0,0 +1,65 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@id": "http://localhost:55001/plone/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot" + } + }, + "@id": "http://localhost:55001/plone/@navroot", + "@type": "Plone Site", + "blocks": {}, + "blocks_layout": {}, + "description": "", + "id": "plone", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "English" + }, + { + "@id": "http://localhost:55001/plone/de", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "Deutsch" + }, + { + "@id": "http://localhost:55001/plone/es", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "Espa\u00f1ol" + }, + { + "@id": "http://localhost:55001/plone/fr", + "@type": "LRF", + "description": "", + "review_state": null, + "title": "Fran\u00e7ais" + } + ], + "items_total": 4, + "parent": {}, + "title": "Plone site" + } +} diff --git a/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.req b/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.req new file mode 100644 index 0000000000..4611396f72 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.req @@ -0,0 +1,3 @@ +GET /plone/front-page/@navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.resp b/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.resp new file mode 100644 index 0000000000..0c374d5389 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get.resp @@ -0,0 +1,76 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@id": "http://localhost:55001/plone/front-page/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/@actions" + }, + "aliases": { + "@id": "http://localhost:55001/plone/@aliases" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot" + }, + "types": { + "@id": "http://localhost:55001/plone/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/@workflow" + } + }, + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "UID": "55c25ebc220d400393574f37d648727c", + "allow_discussion": null, + "contributors": [], + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "plone", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/front-page", + "@type": "Document", + "description": "Congratulations! You have successfully installed Plone.", + "review_state": "private", + "title": "Welcome to Plone", + "type_title": "Page" + } + ], + "items_total": 1, + "language": { + "title": "English", + "token": "en" + }, + "lock": { + "locked": false, + "stealable": true + }, + "parent": {}, + "relatedItems": [], + "review_state": null, + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Plone site", + "type_title": "Plone Site" + } +} diff --git a/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.req b/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.req new file mode 100644 index 0000000000..20266313b2 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.req @@ -0,0 +1,3 @@ +GET /plone/front-page?expand=navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.resp b/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.resp new file mode 100644 index 0000000000..abfbe7e93f --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_standard_site_content_get_expansion.resp @@ -0,0 +1,149 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/front-page/@actions" + }, + "aliases": { + "@id": "http://localhost:55001/plone/front-page/@aliases" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/front-page/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/front-page/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/front-page/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/front-page/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/@actions" + }, + "aliases": { + "@id": "http://localhost:55001/plone/@aliases" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot" + }, + "types": { + "@id": "http://localhost:55001/plone/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/@workflow" + } + }, + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "UID": "55c25ebc220d400393574f37d648727c", + "allow_discussion": null, + "contributors": [], + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "plone", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/front-page", + "@type": "Document", + "description": "Congratulations! You have successfully installed Plone.", + "review_state": "private", + "title": "Welcome to Plone", + "type_title": "Page" + } + ], + "items_total": 1, + "language": { + "title": "English", + "token": "en" + }, + "lock": { + "locked": false, + "stealable": true + }, + "parent": {}, + "relatedItems": [], + "review_state": null, + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Plone site", + "type_title": "Plone Site" + } + }, + "types": { + "@id": "http://localhost:55001/plone/front-page/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/front-page/@workflow" + } + }, + "@id": "http://localhost:55001/plone/front-page", + "@type": "Document", + "UID": "SomeUUID000000000000000000000001", + "allow_discussion": false, + "changeNote": "", + "contributors": [], + "created": "1995-07-31T13:45:00", + "creators": [ + "test_user_1_" + ], + "description": "Congratulations! You have successfully installed Plone.", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "front-page", + "is_folderish": false, + "language": "", + "layout": "document_view", + "lock": { + "locked": false, + "stealable": true + }, + "modified": "1995-07-31T17:30:00", + "next_item": {}, + "parent": { + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", + "title": "Plone site", + "type_title": "Plone Site" + }, + "previous_item": {}, + "relatedItems": [], + "review_state": "private", + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": { + "content-type": "text/plain", + "data": "

If you're seeing this instead of the web site you were expecting, the owner of this web site has just installed Plone. Do not contact the Plone Team or the Plone mailing lists about this.

", + "encoding": "utf-8" + }, + "title": "Welcome to Plone", + "type_title": "Page", + "version": "current", + "versioning_enabled": true, + "working_copy": null, + "working_copy_of": null +} diff --git a/src/plone/restapi/tests/http-examples/navroot_standard_site_get.req b/src/plone/restapi/tests/http-examples/navroot_standard_site_get.req new file mode 100644 index 0000000000..cc9c5ca1e8 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_standard_site_get.req @@ -0,0 +1,3 @@ +GET /plone/@navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/navroot_standard_site_get.resp b/src/plone/restapi/tests/http-examples/navroot_standard_site_get.resp new file mode 100644 index 0000000000..532ec7d6ca --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_standard_site_get.resp @@ -0,0 +1,76 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@id": "http://localhost:55001/plone/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/@actions" + }, + "aliases": { + "@id": "http://localhost:55001/plone/@aliases" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot" + }, + "types": { + "@id": "http://localhost:55001/plone/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/@workflow" + } + }, + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "UID": "55c25ebc220d400393574f37d648727c", + "allow_discussion": null, + "contributors": [], + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "plone", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/front-page", + "@type": "Document", + "description": "Congratulations! You have successfully installed Plone.", + "review_state": "private", + "title": "Welcome to Plone", + "type_title": "Page" + } + ], + "items_total": 1, + "language": { + "title": "English", + "token": "en" + }, + "lock": { + "locked": false, + "stealable": true + }, + "parent": {}, + "relatedItems": [], + "review_state": null, + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Plone site", + "type_title": "Plone Site" + } +} diff --git a/src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.req b/src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.req new file mode 100644 index 0000000000..36c802e247 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.req @@ -0,0 +1,3 @@ +GET /plone/?expand=navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.resp b/src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.resp new file mode 100644 index 0000000000..0a33c7475c --- /dev/null +++ b/src/plone/restapi/tests/http-examples/navroot_standard_site_get_expansion.resp @@ -0,0 +1,143 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/@actions" + }, + "aliases": { + "@id": "http://localhost:55001/plone/@aliases" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/@actions" + }, + "aliases": { + "@id": "http://localhost:55001/plone/@aliases" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot" + }, + "types": { + "@id": "http://localhost:55001/plone/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/@workflow" + } + }, + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "UID": "55c25ebc220d400393574f37d648727c", + "allow_discussion": null, + "contributors": [], + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "plone", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/front-page", + "@type": "Document", + "description": "Congratulations! You have successfully installed Plone.", + "review_state": "private", + "title": "Welcome to Plone", + "type_title": "Page" + } + ], + "items_total": 1, + "language": { + "title": "English", + "token": "en" + }, + "lock": { + "locked": false, + "stealable": true + }, + "parent": {}, + "relatedItems": [], + "review_state": null, + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Plone site", + "type_title": "Plone Site" + } + }, + "types": { + "@id": "http://localhost:55001/plone/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/@workflow" + } + }, + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "UID": "55c25ebc220d400393574f37d648727c", + "allow_discussion": null, + "contributors": [], + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "plone", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/front-page", + "@type": "Document", + "description": "Congratulations! You have successfully installed Plone.", + "review_state": "private", + "title": "Welcome to Plone", + "type_title": "Page" + } + ], + "items_total": 1, + "language": { + "title": "English", + "token": "en" + }, + "lock": { + "locked": false, + "stealable": true + }, + "parent": {}, + "relatedItems": [], + "review_state": null, + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Plone site", + "type_title": "Plone Site" +} diff --git a/src/plone/restapi/tests/http-examples/newsitem.resp b/src/plone/restapi/tests/http-examples/newsitem.resp index 7b13607f99..ddf4779998 100644 --- a/src/plone/restapi/tests/http-examples/newsitem.resp +++ b/src/plone/restapi/tests/http-examples/newsitem.resp @@ -15,6 +15,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/newsitem/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/newsitem/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/newsitem/@types" }, diff --git a/src/plone/restapi/tests/http-examples/search_fullobjects.resp b/src/plone/restapi/tests/http-examples/search_fullobjects.resp index 58edeb566a..a32e3555a4 100644 --- a/src/plone/restapi/tests/http-examples/search_fullobjects.resp +++ b/src/plone/restapi/tests/http-examples/search_fullobjects.resp @@ -18,6 +18,9 @@ Content-Type: application/json "navigation": { "@id": "http://localhost:55001/plone/doc1/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/doc1/@navroot" + }, "types": { "@id": "http://localhost:55001/plone/doc1/@types" }, diff --git a/src/plone/restapi/tests/http-examples/site_get.req b/src/plone/restapi/tests/http-examples/site_get.req new file mode 100644 index 0000000000..2c0e40f0e2 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/site_get.req @@ -0,0 +1,3 @@ +GET /plone/@site HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/site_get.resp b/src/plone/restapi/tests/http-examples/site_get.resp new file mode 100644 index 0000000000..e5f274d3de --- /dev/null +++ b/src/plone/restapi/tests/http-examples/site_get.resp @@ -0,0 +1,22 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@id": "http://localhost:55001/plone/@site", + "plone.allowed_sizes": [ + "huge 1600:65536", + "great 1200:65536", + "larger 1000:65536", + "large 800:65536", + "teaser 600:65536", + "preview 400:65536", + "mini 200:65536", + "thumb 128:128", + "tile 64:64", + "icon 32:32", + "listing 16:16" + ], + "plone.robots_txt": "Sitemap: {portal_url}/sitemap.xml.gz\n\n# Define access-restrictions for robots/spiders\n# http://www.robotstxt.org/wc/norobots.html\n\n\n\n# By default we allow robots to access all areas of our site\n# already accessible to anonymous users\n\nUser-agent: *\nDisallow:\n\n\n\n# Add Googlebot-specific syntax extension to exclude forms\n# that are repeated for each piece of content in the site\n# the wildcard is only supported by Googlebot\n# http://www.google.com/support/webmasters/bin/answer.py?answer=40367&ctx=sibling\n\nUser-Agent: Googlebot\nDisallow: /*?\nDisallow: /*atct_album_view$\nDisallow: /*folder_factories$\nDisallow: /*folder_summary_view$\nDisallow: /*login_form$\nDisallow: /*mail_password_form$\nDisallow: /@@search\nDisallow: /*search_rss$\nDisallow: /*sendto_form$\nDisallow: /*summary_view$\nDisallow: /*thumbnail_view$\nDisallow: /*view$\n", + "plone.site_logo": null, + "plone.site_title": "Plone site" +} diff --git a/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.req b/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.req new file mode 100644 index 0000000000..5eae3bdfb1 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.req @@ -0,0 +1,3 @@ +GET /plone/en?expand=navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.resp b/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.resp new file mode 100644 index 0000000000..d5c1a0f186 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder.resp @@ -0,0 +1,173 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/en/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/en/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/en/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/en/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/en/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/en/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/en/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/en/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/en/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/en/@navroot" + }, + "translations": { + "@id": "http://localhost:55001/plone/en/@translations" + }, + "types": { + "@id": "http://localhost:55001/plone/en/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/en/@workflow" + } + }, + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "UID": "00000000000000000000000000000001", + "allow_discussion": false, + "contributors": [], + "created": "1995-07-31T13:45:00", + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": true, + "expires": null, + "id": "en", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/en/assets", + "@type": "LIF", + "description": "", + "review_state": "published", + "title": "Assets" + }, + { + "@id": "http://localhost:55001/plone/en/test-document", + "@type": "Document", + "description": "", + "review_state": "private", + "title": "Test document" + } + ], + "items_total": 2, + "language": { + "title": "English", + "token": "en" + }, + "layout": "folder_listing", + "lock": {}, + "modified": "1995-07-31T17:30:00", + "next_item": { + "@id": "http://localhost:55001/plone/de", + "@type": "LRF", + "description": "", + "title": "Deutsch" + }, + "parent": { + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", + "title": "Plone site" + }, + "previous_item": {}, + "review_state": "published", + "rights": "", + "subjects": [], + "title": "English", + "version": "current" + } + }, + "translations": { + "@id": "http://localhost:55001/plone/en/@translations" + }, + "types": { + "@id": "http://localhost:55001/plone/en/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/en/@workflow" + } + }, + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "UID": "00000000000000000000000000000001", + "allow_discussion": false, + "contributors": [], + "created": "1995-07-31T13:45:00", + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": true, + "expires": null, + "id": "en", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/en/assets", + "@type": "LIF", + "description": "", + "review_state": "published", + "title": "Assets" + }, + { + "@id": "http://localhost:55001/plone/en/test-document", + "@type": "Document", + "description": "", + "review_state": "private", + "title": "Test document" + } + ], + "items_total": 2, + "language": { + "title": "English", + "token": "en" + }, + "layout": "folder_listing", + "lock": {}, + "modified": "1995-07-31T17:30:00", + "next_item": { + "@id": "http://localhost:55001/plone/de", + "@type": "LRF", + "description": "", + "title": "Deutsch" + }, + "parent": { + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", + "title": "Plone site" + }, + "previous_item": {}, + "review_state": "published", + "rights": "", + "subjects": [], + "title": "English", + "version": "current" +} diff --git a/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.req b/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.req new file mode 100644 index 0000000000..3574d72d7e --- /dev/null +++ b/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.req @@ -0,0 +1,3 @@ +GET /plone/en/test-document?expand=navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.resp b/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.resp new file mode 100644 index 0000000000..32745d5534 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/site_get_expand_lang_folder_content.resp @@ -0,0 +1,165 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/en/test-document/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/en/test-document/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/en/test-document/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/en/test-document/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/en/test-document/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/en/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/en/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/en/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/en/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/en/@navroot" + }, + "translations": { + "@id": "http://localhost:55001/plone/en/@translations" + }, + "types": { + "@id": "http://localhost:55001/plone/en/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/en/@workflow" + } + }, + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "UID": "00000000000000000000000000000001", + "allow_discussion": false, + "contributors": [], + "created": "1995-07-31T13:45:00", + "creators": [ + "admin" + ], + "description": "", + "effective": null, + "exclude_from_nav": true, + "expires": null, + "id": "en", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/en/assets", + "@type": "LIF", + "description": "", + "review_state": "published", + "title": "Assets" + }, + { + "@id": "http://localhost:55001/plone/en/test-document", + "@type": "Document", + "description": "", + "review_state": "private", + "title": "Test document" + } + ], + "items_total": 2, + "language": { + "title": "English", + "token": "en" + }, + "layout": "folder_listing", + "lock": {}, + "modified": "1995-07-31T17:30:00", + "next_item": { + "@id": "http://localhost:55001/plone/de", + "@type": "LRF", + "description": "", + "title": "Deutsch" + }, + "parent": { + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", + "title": "Plone site" + }, + "previous_item": {}, + "review_state": "published", + "rights": "", + "subjects": [], + "title": "English", + "version": "current" + } + }, + "translations": { + "@id": "http://localhost:55001/plone/en/test-document/@translations" + }, + "types": { + "@id": "http://localhost:55001/plone/en/test-document/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/en/test-document/@workflow" + } + }, + "@id": "http://localhost:55001/plone/en/test-document", + "@type": "Document", + "UID": "SomeUUID000000000000000000000001", + "allow_discussion": false, + "changeNote": "", + "contributors": [], + "created": "1995-07-31T13:45:00", + "creators": [ + "test_user_1_" + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "test-document", + "is_folderish": false, + "language": { + "title": "English", + "token": "en" + }, + "layout": "document_view", + "lock": { + "locked": false, + "stealable": true + }, + "modified": "1995-07-31T17:30:00", + "next_item": {}, + "parent": { + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "English" + }, + "previous_item": { + "@id": "http://localhost:55001/plone/en/assets", + "@type": "LIF", + "description": "", + "title": "Assets" + }, + "relatedItems": [], + "review_state": "private", + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Test document", + "version": "current", + "versioning_enabled": true +} diff --git a/src/plone/restapi/tests/http-examples/site_get_expand_navroot.req b/src/plone/restapi/tests/http-examples/site_get_expand_navroot.req new file mode 100644 index 0000000000..36c802e247 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/site_get_expand_navroot.req @@ -0,0 +1,3 @@ +GET /plone/?expand=navroot HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/site_get_expand_navroot.resp b/src/plone/restapi/tests/http-examples/site_get_expand_navroot.resp new file mode 100644 index 0000000000..b28d008a7a --- /dev/null +++ b/src/plone/restapi/tests/http-examples/site_get_expand_navroot.resp @@ -0,0 +1,121 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot", + "navroot": { + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/@actions" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot" + } + }, + "@id": "http://localhost:55001/plone/?expand=navroot", + "@type": "Plone Site", + "blocks": {}, + "blocks_layout": {}, + "description": "", + "id": "plone", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "English" + }, + { + "@id": "http://localhost:55001/plone/de", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "Deutsch" + }, + { + "@id": "http://localhost:55001/plone/es", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "Espa\u00f1ol" + }, + { + "@id": "http://localhost:55001/plone/fr", + "@type": "LRF", + "description": "", + "review_state": null, + "title": "Fran\u00e7ais" + } + ], + "items_total": 4, + "parent": {}, + "title": "Plone site" + } + } + }, + "@id": "http://localhost:55001/plone/?expand=navroot", + "@type": "Plone Site", + "blocks": {}, + "blocks_layout": {}, + "description": "", + "id": "plone", + "is_folderish": true, + "items": [ + { + "@id": "http://localhost:55001/plone/en", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "English" + }, + { + "@id": "http://localhost:55001/plone/de", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "Deutsch" + }, + { + "@id": "http://localhost:55001/plone/es", + "@type": "LRF", + "description": "", + "review_state": "published", + "title": "Espa\u00f1ol" + }, + { + "@id": "http://localhost:55001/plone/fr", + "@type": "LRF", + "description": "", + "review_state": null, + "title": "Fran\u00e7ais" + } + ], + "items_total": 4, + "parent": {}, + "title": "Plone site" +} diff --git a/src/plone/restapi/tests/http-examples/siteroot.resp b/src/plone/restapi/tests/http-examples/siteroot.resp index 4c00477092..a528d73376 100644 --- a/src/plone/restapi/tests/http-examples/siteroot.resp +++ b/src/plone/restapi/tests/http-examples/siteroot.resp @@ -14,6 +14,9 @@ Content-Type: application/json }, "navigation": { "@id": "http://localhost:55001/plone/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/@navroot" } }, "@id": "http://localhost:55001/plone", diff --git a/src/plone/restapi/tests/http-examples/translations_link_on_post.resp b/src/plone/restapi/tests/http-examples/translations_link_on_post.resp index f82e131dfe..836ce9429d 100644 --- a/src/plone/restapi/tests/http-examples/translations_link_on_post.resp +++ b/src/plone/restapi/tests/http-examples/translations_link_on_post.resp @@ -16,6 +16,9 @@ Location: http://localhost:55001/plone/de/mydocument "navigation": { "@id": "http://localhost:55001/plone/de/mydocument/@navigation" }, + "navroot": { + "@id": "http://localhost:55001/plone/de/mydocument/@navroot" + }, "translations": { "@id": "http://localhost:55001/plone/de/mydocument/@translations" }, diff --git a/src/plone/restapi/tests/http-examples/workingcopy_baseline_get.resp b/src/plone/restapi/tests/http-examples/workingcopy_baseline_get.resp index 92a8ab1818..bb6eb48071 100644 --- a/src/plone/restapi/tests/http-examples/workingcopy_baseline_get.resp +++ b/src/plone/restapi/tests/http-examples/workingcopy_baseline_get.resp @@ -5,80 +5,80 @@ Content-Type: application/json "@components": { "actions": { "@id": "http://localhost:55001/plone/document/@actions" - }, + }, "breadcrumbs": { "@id": "http://localhost:55001/plone/document/@breadcrumbs" - }, + }, "contextnavigation": { "@id": "http://localhost:55001/plone/document/@contextnavigation" - }, + }, "navigation": { "@id": "http://localhost:55001/plone/document/@navigation" - }, + }, "types": { "@id": "http://localhost:55001/plone/document/@types" - }, + }, "workflow": { "@id": "http://localhost:55001/plone/document/@workflow" } - }, - "@id": "http://localhost:55001/plone/document", - "@type": "Document", - "UID": "SomeUUID000000000000000000000001", - "allow_discussion": false, - "contributors": [], - "created": "1995-07-31T13:45:00", + }, + "@id": "http://localhost:55001/plone/document", + "@type": "Document", + "UID": "SomeUUID000000000000000000000001", + "allow_discussion": false, + "contributors": [], + "created": "1995-07-31T13:45:00", "creators": [ "test_user_1_" - ], - "description": "", - "effective": null, - "exclude_from_nav": false, - "expires": null, - "id": "document", - "is_folderish": false, - "language": "", - "layout": "document_view", + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "document", + "is_folderish": false, + "language": "", + "layout": "document_view", "lock": { - "created": "1995-07-31T17:30:00", - "creator": "admin", - "creator_name": "admin", - "creator_url": "http://localhost:55001/plone/author/admin", - "locked": true, - "name": "iterate.lock", - "stealable": false, - "time": 807201000.0, - "timeout": 4294967280, + "created": "1995-07-31T17:30:00", + "creator": "admin", + "creator_name": "admin", + "creator_url": "http://localhost:55001/plone/author/admin", + "locked": true, + "name": "iterate.lock", + "stealable": false, + "time": 807201000.0, + "timeout": 4294967280, "token": "0.3217605825198149-0.016714612599692202-00105A989226:1629895144.744" - }, - "modified": "1995-07-31T17:30:00", + }, + "modified": "1995-07-31T17:30:00", "next_item": { - "@id": "http://localhost:55001/plone/copy_of_document", - "@type": "Document", - "description": "", + "@id": "http://localhost:55001/plone/copy_of_document", + "@type": "Document", + "description": "", "title": "Test document" - }, + }, "parent": { - "@id": "http://localhost:55001/plone", - "@type": "Plone Site", - "description": "", + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", "title": "Plone site" - }, - "previous_item": {}, - "relatedItems": [], - "review_state": "private", - "rights": "", - "subjects": [], - "table_of_contents": null, - "text": null, - "title": "Test document", - "version": "current", + }, + "previous_item": {}, + "relatedItems": [], + "review_state": "private", + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Test document", + "version": "current", "working_copy": { - "@id": "http://localhost:55001/plone/copy_of_document", - "created": "1995-07-31T13:45:00", - "creator_name": "admin", - "creator_url": "http://localhost:55001/plone/author/admin", + "@id": "http://localhost:55001/plone/copy_of_document", + "created": "1995-07-31T13:45:00", + "creator_name": "admin", + "creator_url": "http://localhost:55001/plone/author/admin", "title": "Test document" - }, + }, "working_copy_of": null -} \ No newline at end of file +} diff --git a/src/plone/restapi/tests/http-examples/workingcopy_wc_get.resp b/src/plone/restapi/tests/http-examples/workingcopy_wc_get.resp index 9c4216f49b..cb7e871387 100644 --- a/src/plone/restapi/tests/http-examples/workingcopy_wc_get.resp +++ b/src/plone/restapi/tests/http-examples/workingcopy_wc_get.resp @@ -2,78 +2,142 @@ HTTP/1.1 200 OK Content-Type: application/json { - "@components": { - "actions": { - "@id": "http://localhost:55001/plone/copy_of_document/@actions" - }, - "breadcrumbs": { - "@id": "http://localhost:55001/plone/copy_of_document/@breadcrumbs" - }, - "contextnavigation": { - "@id": "http://localhost:55001/plone/copy_of_document/@contextnavigation" - }, - "navigation": { - "@id": "http://localhost:55001/plone/copy_of_document/@navigation" - }, - "types": { - "@id": "http://localhost:55001/plone/copy_of_document/@types" - }, - "workflow": { - "@id": "http://localhost:55001/plone/copy_of_document/@workflow" + "@components": { + "actions": { + "@id": "http://localhost:55001/plone/copy_of_document/@actions" + }, + "aliases": { + "@id": "http://localhost:55001/plone/copy_of_document/@aliases" + }, + "breadcrumbs": { + "@id": "http://localhost:55001/plone/copy_of_document/@breadcrumbs" + }, + "contextnavigation": { + "@id": "http://localhost:55001/plone/copy_of_document/@contextnavigation" + }, + "navigation": { + "@id": "http://localhost:55001/plone/copy_of_document/@navigation" + }, + "navroot": { + "@id": "http://localhost:55001/plone/copy_of_document/@navroot" + }, + "types": { + "@id": "http://localhost:55001/plone/copy_of_document/@types" + }, + "workflow": { + "@id": "http://localhost:55001/plone/copy_of_document/@workflow" + } + }, + "@id": "http://localhost:55001/plone/copy_of_document", + "@type": "Document", + "UID": "SomeUUID000000000000000000000002", + "allow_discussion": false, + "contributors": [], + "created": "1995-07-31T13:45:00", + "creators": [ + "test_user_1_" + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "copy_of_document", + "is_folderish": false, + "language": "", + "layout": "document_view", + "lock": { + "locked": false, + "stealable": true + }, + "modified": "1995-07-31T17:30:00", + "next_item": {}, + "parent": { + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", + "title": "Plone site", + "type_title": "Plone Site" + }, + "previous_item": { + "@id": "http://localhost:55001/plone/document", + "@type": "Document", + "description": "", + "title": "Test document", + "type_title": "Page" + }, + "relatedItems": [], + "review_state": "private", + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Test document", + "type_title": "Page", + "version": "current", + "working_copy": { + "@id": "http://localhost:55001/plone/copy_of_document", + "created": "1995-07-31T13:45:00", + "creator_name": "admin", + "creator_url": "http://localhost:55001/plone/author/admin", + "title": "Test document" + }, + "working_copy_of": { + "@id": "http://localhost:55001/plone/document", + "title": "Test document" } - }, - "@id": "http://localhost:55001/plone/copy_of_document", - "@type": "Document", - "UID": "SomeUUID000000000000000000000002", - "allow_discussion": false, - "contributors": [], - "created": "1995-07-31T13:45:00", + }, + "@id": "http://localhost:55001/plone/copy_of_document", + "@type": "Document", + "UID": "SomeUUID000000000000000000000002", + "allow_discussion": false, + "contributors": [], + "created": "1995-07-31T13:45:00", "creators": [ "test_user_1_" - ], - "description": "", - "effective": null, - "exclude_from_nav": false, - "expires": null, - "id": "copy_of_document", - "is_folderish": false, - "language": "", - "layout": "document_view", + ], + "description": "", + "effective": null, + "exclude_from_nav": false, + "expires": null, + "id": "copy_of_document", + "is_folderish": false, + "language": "", + "layout": "document_view", "lock": { - "locked": false, + "locked": false, "stealable": true - }, - "modified": "1995-07-31T17:30:00", - "next_item": {}, + }, + "modified": "1995-07-31T17:30:00", + "next_item": {}, "parent": { - "@id": "http://localhost:55001/plone", - "@type": "Plone Site", - "description": "", + "@id": "http://localhost:55001/plone", + "@type": "Plone Site", + "description": "", "title": "Plone site" - }, + }, "previous_item": { - "@id": "http://localhost:55001/plone/document", - "@type": "Document", - "description": "", + "@id": "http://localhost:55001/plone/document", + "@type": "Document", + "description": "", "title": "Test document" - }, - "relatedItems": [], - "review_state": "private", - "rights": "", - "subjects": [], - "table_of_contents": null, - "text": null, - "title": "Test document", - "version": "current", + }, + "relatedItems": [], + "review_state": "private", + "rights": "", + "subjects": [], + "table_of_contents": null, + "text": null, + "title": "Test document", + "version": "current", "working_copy": { - "@id": "http://localhost:55001/plone/copy_of_document", - "created": "1995-07-31T13:45:00", - "creator_name": "admin", - "creator_url": "http://localhost:55001/plone/author/admin", + "@id": "http://localhost:55001/plone/copy_of_document", + "created": "1995-07-31T13:45:00", + "creator_name": "admin", + "creator_url": "http://localhost:55001/plone/author/admin", "title": "Test document" - }, + }, "working_copy_of": { - "@id": "http://localhost:55001/plone/document", + "@id": "http://localhost:55001/plone/document", "title": "Test document" } } \ No newline at end of file diff --git a/src/plone/restapi/tests/test_documentation.py b/src/plone/restapi/tests/test_documentation.py index f4b40c675e..5912a1f0f3 100644 --- a/src/plone/restapi/tests/test_documentation.py +++ b/src/plone/restapi/tests/test_documentation.py @@ -8,7 +8,7 @@ from plone.app.discussion.interfaces import IConversation from plone.app.discussion.interfaces import IDiscussionSettings from plone.app.discussion.interfaces import IReplies -from plone.app.testing import applyProfile + from plone.app.testing import popGlobalRegistry from plone.app.testing import pushGlobalRegistry from plone.app.testing import setRoles @@ -32,9 +32,8 @@ from six.moves import range from zope.component import createObject from zope.component import getUtility -from zope.component.hooks import getSite from zope.interface import alsoProvides - +from zope.component.hooks import getSite import collections import json import os @@ -203,7 +202,8 @@ def setUp(self): self.browser = Browser(self.app) self.browser.handleErrors = False self.browser.addHeader( - "Authorization", "Basic %s:%s" % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) + "Authorization", + "Basic %s:%s" % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD), ) setRoles(self.portal, TEST_USER_ID, ["Manager"]) @@ -234,7 +234,6 @@ def setUp(self): super(TestDocumentation, self).setUp() self.document = self.create_document() alsoProvides(self.document, ITTWLockable) - transaction.commit() def tearDown(self): @@ -271,7 +270,8 @@ def test_documentation_content_crud(self): transaction.commit() response = self.api_session.post( - folder.absolute_url(), json={"@type": "Document", "title": "My Document"} + folder.absolute_url(), + json={"@type": "Document", "title": "My Document"}, ) save_request_and_response_for_docs("content_post", response) @@ -432,7 +432,11 @@ def test_documentation_search_options(self): self.portal.invokeFactory("Folder", id="folder1", title="Folder 1") self.portal.folder1.invokeFactory("Folder", id="folder2", title="Folder 2") transaction.commit() - query = {"sort_on": "path", "path.query": "/plone/folder1", "path.depth": "1"} + query = { + "sort_on": "path", + "path.query": "/plone/folder1", + "path.depth": "1", + } response = self.api_session.get("/@search", params=query) save_request_and_response_for_docs("search_options", response) @@ -453,7 +457,10 @@ def test_documentation_search_multiple_paths(self): def test_documentation_search_metadata_fields(self): self.portal.invokeFactory("Document", id="doc1", title="Lorem Ipsum") transaction.commit() - query = {"SearchableText": "lorem", "metadata_fields": ["modified", "created"]} + query = { + "SearchableText": "lorem", + "metadata_fields": ["modified", "created"], + } response = self.api_session.get("/@search", params=query) save_request_and_response_for_docs("search_metadata_fields", response) @@ -498,7 +505,8 @@ def test_documentation_registry_get(self): def test_documentation_registry_update(self): response = self.api_session.patch( - "/@registry/", json={"plone.app.querystring.field.path.title": "Value"} + "/@registry/", + json={"plone.app.querystring.field.path.title": "Value"}, ) save_request_and_response_for_docs("registry_update", response) @@ -782,7 +790,9 @@ def test_documentation_batching(self): ] for i in range(7): folder.invokeFactory( - "Document", id="doc-%s" % str(i + 1), title="Document %s" % str(i + 1) + "Document", + id="doc-%s" % str(i + 1), + title="Document %s" % str(i + 1), ) transaction.commit() @@ -860,7 +870,9 @@ def test_documentation_users_get(self): "location": "Cambridge, MA", } api.user.create( - email="noam.chomsky@example.com", username="noam", properties=properties + email="noam.chomsky@example.com", + username="noam", + properties=properties, ) transaction.commit() response = self.api_session.get("@users/noam") @@ -876,7 +888,9 @@ def test_documentation_users_anonymous_get(self): "location": "Cambridge, MA", } api.user.create( - email="noam.chomsky@example.com", username="noam", properties=properties + email="noam.chomsky@example.com", + username="noam", + properties=properties, ) transaction.commit() @@ -954,7 +968,9 @@ def test_documentation_users_filtered_get(self): "location": "Cambridge, MA", } api.user.create( - email="noam.chomsky@example.com", username="noam", properties=properties + email="noam.chomsky@example.com", + username="noam", + properties=properties, ) transaction.commit() response = self.api_session.get("@users", params={"query": "noa"}) @@ -1003,7 +1019,9 @@ def test_documentation_users_update(self): "location": "Cambridge, MA", } api.user.create( - email="noam.chomsky@example.com", username="noam", properties=properties + email="noam.chomsky@example.com", + username="noam", + properties=properties, ) transaction.commit() @@ -1061,7 +1079,9 @@ def test_documentation_users_delete(self): "location": "Cambridge, MA", } api.user.create( - email="noam.chomsky@example.com", username="noam", properties=properties + email="noam.chomsky@example.com", + username="noam", + properties=properties, ) transaction.commit() @@ -1161,7 +1181,10 @@ def test_documentation_groups_update(self): response = self.api_session.patch( "/@groups/ploneteam", - json={"email": "ploneteam2@plone.org", "users": {TEST_USER_ID: False}}, + json={ + "email": "ploneteam2@plone.org", + "users": {TEST_USER_ID: False}, + }, ) save_request_and_response_for_docs("groups_update", response) @@ -1211,7 +1234,10 @@ def test_documentation_navigation_tree(self): folder, u"Folder", id=u"subfolder2", title=u"SubFolder 2" ) thirdlevelfolder = createContentInContainer( - subfolder1, u"Folder", id=u"thirdlevelfolder", title=u"Third Level Folder" + subfolder1, + u"Folder", + id=u"thirdlevelfolder", + title=u"Third Level Folder", ) createContentInContainer( thirdlevelfolder, @@ -1242,7 +1268,10 @@ def test_documentation_contextnavigation(self): folder, u"Folder", id=u"subfolder2", title=u"SubFolder 2" ) thirdlevelfolder = createContentInContainer( - subfolder1, u"Folder", id=u"thirdlevelfolder", title=u"Third Level Folder" + subfolder1, + u"Folder", + id=u"thirdlevelfolder", + title=u"Third Level Folder", ) createContentInContainer( thirdlevelfolder, @@ -1289,7 +1318,12 @@ def test_documentation_copy_multiple(self): response = self.api_session.post( "/@copy", - json={"source": [self.document.absolute_url(), newsitem.absolute_url()]}, + json={ + "source": [ + self.document.absolute_url(), + newsitem.absolute_url(), + ] + }, ) save_request_and_response_for_docs("copy_multiple", response) @@ -1334,7 +1368,10 @@ def test_documentation_vocabularies_get_filtered_by_token(self): def test_documentation_sources_get(self): api.content.create( - container=self.portal, id="doc", type="DXTestDocument", title=u"DX Document" + container=self.portal, + id="doc", + type="DXTestDocument", + title=u"DX Document", ) transaction.commit() response = self.api_session.get("/doc/@sources/test_choice_with_source") @@ -1526,7 +1563,8 @@ def test_locking_lock(self): # Replace dynamic lock token with a static one response._content = re.sub( b'"token": "[^"]+"', - b'"token": "0.684672730996-0.25195226375-00105A989226:1477076400.000"', # noqa + b'"token":' + b' "0.684672730996-0.25195226375-00105A989226:1477076400.000"', # noqa response.content, ) save_request_and_response_for_docs("lock", response) @@ -1539,7 +1577,8 @@ def test_locking_lock_nonstealable_and_timeout(self): # Replace dynamic lock token with a static one response._content = re.sub( b'"token": "[^"]+"', - b'"token": "0.684672730996-0.25195226375-00105A989226:1477076400.000"', # noqa + b'"token":' + b' "0.684672730996-0.25195226375-00105A989226:1477076400.000"', # noqa response.content, ) save_request_and_response_for_docs("lock_nonstealable_timeout", response) @@ -1565,7 +1604,8 @@ def test_locking_refresh_lock(self): # Replace dynamic lock token with a static one response._content = re.sub( b'"token": "[^"]+"', - b'"token": "0.684672730996-0.25195226375-00105A989226:1477076400.000"', # noqa + b'"token":' + b' "0.684672730996-0.25195226375-00105A989226:1477076400.000"', # noqa response.content, ) save_request_and_response_for_docs("refresh_lock", response) @@ -1877,7 +1917,8 @@ def test_controlpanels_crud_dexterity(self): @unittest.skipUnless( - PAM_INSTALLED, "plone.app.multilingual is installed by default only in Plone 5" + PAM_INSTALLED, + "plone.app.multilingual is installed by default only in Plone 5", ) # NOQA class TestPAMDocumentation(TestDocumentationBase): @@ -1886,11 +1927,16 @@ class TestPAMDocumentation(TestDocumentationBase): def setUp(self): super(TestPAMDocumentation, self).setUp() - language_tool = api.portal.get_tool("portal_languages") - language_tool.addSupportedLanguage("en") - language_tool.addSupportedLanguage("es") - language_tool.addSupportedLanguage("de") - applyProfile(self.portal, "plone.app.multilingual:default") + # + # We manually set the UIDs for LRFs here because the static uuid + # generator is not applied for LRFs. + # When we have tried to apply it for LRFs we have had several + # utility registration problems. + # + setattr(self.portal.en, "_plone.uuid", "00000000000000000000000000000001") + setattr(self.portal.es, "_plone.uuid", "00000000000000000000000000000002") + setattr(self.portal.fr, "_plone.uuid", "00000000000000000000000000000003") + setattr(self.portal.de, "_plone.uuid", "00000000000000000000000000000004") en_id = self.portal["en"].invokeFactory( "Document", id="test-document", title="Test document" @@ -1902,9 +1948,6 @@ def setUp(self): self.es_content = self.portal["es"].get(es_id) transaction.commit() - def tearDown(self): - super(TestPAMDocumentation, self).tearDown() - def test_documentation_translations_post(self): response = self.api_session.post( "{}/@translations".format(self.en_content.absolute_url()), @@ -1929,6 +1972,7 @@ def test_documentation_translations_post_by_uid(self): def test_documentation_translations_get(self): ITranslationManager(self.en_content).register_translation("es", self.es_content) transaction.commit() + response = self.api_session.get( "{}/@translations".format(self.en_content.absolute_url()) ) @@ -1966,3 +2010,29 @@ def test_documentation_translation_locator(self): auth=(SITE_OWNER_NAME, SITE_OWNER_PASSWORD), ) save_request_and_response_for_docs("translation_locator", response) + + def test_site_navroot_get(self): + response = self.api_session.get("/@navroot") + save_request_and_response_for_docs("navroot_site_get", response) + + def test_site_navroot_language_folder_get(self): + response = self.api_session.get("/en/@navroot") + save_request_and_response_for_docs("navroot_lang_folder_get", response) + + def test_site_navroot_language_content_get(self): + response = self.api_session.get("/en/test-document/@navroot") + save_request_and_response_for_docs("navroot_lang_content_get", response) + + def test_site_expansion_navroot(self): + response = self.api_session.get("?expand=navroot") + save_request_and_response_for_docs("site_get_expand_navroot", response) + + def test_site_expansion_navroot_language_folder(self): + response = self.api_session.get("/en?expand=navroot") + save_request_and_response_for_docs("site_get_expand_lang_folder", response) + + def test_site_expansion_navroot_language_folder_content(self): + response = self.api_session.get("/en/test-document?expand=navroot") + save_request_and_response_for_docs( + "site_get_expand_lang_folder_content", response + ) diff --git a/src/plone/restapi/tests/test_services_navroot.py b/src/plone/restapi/tests/test_services_navroot.py new file mode 100644 index 0000000000..0e2e7b844b --- /dev/null +++ b/src/plone/restapi/tests/test_services_navroot.py @@ -0,0 +1,268 @@ +# -*- coding: utf-8 -*- +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from plone.restapi.testing import ( + PLONE_RESTAPI_DX_FUNCTIONAL_TESTING, + PLONE_RESTAPI_DX_PAM_FUNCTIONAL_TESTING, +) +from plone.restapi.testing import PAM_INSTALLED +from plone.restapi.testing import RelativeSession +from zope.component import getMultiAdapter +from zope.interface import alsoProvides +from plone.app.layout.navigation.interfaces import INavigationRoot + +import unittest +from plone import api +import transaction + + +class TestServicesNavroot(unittest.TestCase): + + layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING + + def setUp(self): + self.app = self.layer["app"] + self.portal = self.layer["portal"] + self.portal_url = self.portal.absolute_url() + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + + api.content.create( + container=self.portal, + id="news", + title="News", + type="Folder", + ) + api.content.create( + container=self.portal.news, + id="document", + title="Document", + type="Document", + ) + api.content.transition(obj=self.portal.news, transition="publish") + api.content.transition(obj=self.portal.news.document, transition="publish") + transaction.commit() + + self.api_session = RelativeSession(self.portal_url) + self.api_session.headers.update({"Accept": "application/json"}) + + def test_get_navroot(self): + response = self.api_session.get( + "/@navroot", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal, self.layer["request"]), name="plone_portal_state" + ) + + self.assertIn("navroot", response.json()) + self.assertEqual( + response.json()["navroot"]["title"], + portal_state.navigation_root_title(), + ) + self.assertEqual(response.json()["@id"], self.portal_url + "/@navroot") + + def test_get_navroot_non_multilingual_navigation_root(self): + """test that the navroot is computed correctly when a section + implements INavigationRoot + """ + alsoProvides(self.portal.news, INavigationRoot) + transaction.commit() + + response = self.api_session.get( + "/news/@navroot", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal.news, self.layer["request"]), + name="plone_portal_state", + ) + + self.assertIn("navroot", response.json()) + + self.assertEqual( + response.json()["navroot"]["title"], + portal_state.navigation_root_title(), + ) + self.assertEqual( + response.json()["navroot"]["@id"], + portal_state.navigation_root_url(), + ) + + def test_get_navroot_non_multilingual_navigation_root_content(self): + """test that the navroot is computed correctly in a content inside a section + that implements INavigationRoot + """ + alsoProvides(self.portal.news, INavigationRoot) + transaction.commit() + + response = self.api_session.get( + "/news/document/@navroot", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal.news, self.layer["request"]), + name="plone_portal_state", + ) + + self.assertIn("navroot", response.json()) + + self.assertEqual( + response.json()["navroot"]["title"], + portal_state.navigation_root_title(), + ) + self.assertEqual( + response.json()["navroot"]["@id"], + portal_state.navigation_root_url(), + ) + + +@unittest.skipUnless( + PAM_INSTALLED, "plone.app.multilingual is installed by default only in Plone 5" +) # NOQA +class TestServicesNavrootMultilingual(unittest.TestCase): + + layer = PLONE_RESTAPI_DX_PAM_FUNCTIONAL_TESTING + + def setUp(self): + self.app = self.layer["app"] + self.portal = self.layer["portal"] + self.portal_url = self.portal.absolute_url() + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + + api.content.create( + container=self.portal.en, + id="news", + title="News", + type="Folder", + ) + api.content.create( + container=self.portal.en.news, + id="document", + title="Document", + type="Document", + ) + api.content.transition(obj=self.portal.en.news, transition="publish") + api.content.transition(obj=self.portal.en.news.document, transition="publish") + + self.api_session = RelativeSession(self.portal_url) + self.api_session.headers.update({"Accept": "application/json"}) + + transaction.commit() + + def test_get_navroot_site(self): + response = self.api_session.get( + "/@navroot", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal, self.layer["request"]), name="plone_portal_state" + ) + self.assertIn("navroot", response.json()) + + self.assertEqual( + response.json()["navroot"]["title"], + portal_state.navigation_root_title(), + ) + self.assertEqual( + response.json()["@id"], + portal_state.navigation_root_url() + "/@navroot", + ) + + def test_get_navroot_language_folder(self): + response = self.api_session.get( + "/en/@navroot", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal.en, self.layer["request"]), name="plone_portal_state" + ) + self.assertIn("navroot", response.json()) + + self.assertEqual( + response.json()["navroot"]["title"], + portal_state.navigation_root_title(), + ) + self.assertEqual( + response.json()["@id"], + portal_state.navigation_root_url() + "/@navroot", + ) + + def test_get_navroot_language_content(self): + response = self.api_session.get( + "/en/news/@navroot", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal.en.news, self.layer["request"]), + name="plone_portal_state", + ) + self.assertIn("navroot", response.json()) + + self.assertEqual( + response.json()["navroot"]["title"], + portal_state.navigation_root_title(), + ) + self.assertEqual( + response.json()["navroot"]["@id"], + portal_state.navigation_root_url(), + ) + + def test_get_navroot_non_multilingual_navigation_root(self): + """test that the navroot is computed correctly when a section + implements INavigationRoot + """ + alsoProvides(self.portal.en.news, INavigationRoot) + transaction.commit() + + response = self.api_session.get( + "/en/news/@navroot", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal.en.news, self.layer["request"]), + name="plone_portal_state", + ) + self.assertIn("navroot", response.json()) + + self.assertEqual( + response.json()["navroot"]["title"], + portal_state.navigation_root_title(), + ) + self.assertEqual( + response.json()["navroot"]["@id"], + portal_state.navigation_root_url(), + ) + + def test_get_navroot_non_multilingual_navigation_root_content(self): + """test that the navroot is computed correctly in a content inside a section + that implements INavigationRoot + """ + alsoProvides(self.portal.en.news, INavigationRoot) + transaction.commit() + + response = self.api_session.get( + "/en/news/document/@navroot", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal.en.news, self.layer["request"]), + name="plone_portal_state", + ) + self.assertIn("navroot", response.json()) + + self.assertEqual( + response.json()["navroot"]["title"], + portal_state.navigation_root_title(), + ) + self.assertEqual( + response.json()["navroot"]["@id"], + portal_state.navigation_root_url(), + ) diff --git a/src/plone/restapi/tests/test_services_site.py b/src/plone/restapi/tests/test_services_site.py new file mode 100644 index 0000000000..145f81c0ac --- /dev/null +++ b/src/plone/restapi/tests/test_services_site.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from plone.restapi.testing import PLONE_RESTAPI_DX_FUNCTIONAL_TESTING +from plone.restapi.testing import RelativeSession +from zope.component import getMultiAdapter + +import unittest + +IS_PLONE4 = False + +try: + from Products.CMFPlone.interfaces import IImagingSchema # noqa + from Products.CMFPlone.interfaces import ISiteSchema # noqa +except ImportError: + IS_PLONE4 = True + + +class TestServicesSite(unittest.TestCase): + + layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING + + def setUp(self): + self.app = self.layer["app"] + self.portal = self.layer["portal"] + self.portal_url = self.portal.absolute_url() + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + + self.api_session = RelativeSession(self.portal_url) + self.api_session.headers.update({"Accept": "application/json"}) + + def test_get_site_title(self): + response = self.api_session.get( + "/@site", + ) + + self.assertEqual(response.status_code, 200) + portal_state = getMultiAdapter( + (self.portal, self.layer["request"]), name="plone_portal_state" + ) + self.assertEqual( + response.json()["plone.site_title"], portal_state.portal_title() + ) + + @unittest.skipIf( + IS_PLONE4, + "The information can only be extracted from the ISiteSchema and IImagingSchema values in registry, which are only available in Plone 5", + ) # NOQA + def test_get_site_other(self): + response = self.api_session.get( + "/@site", + ) + + self.assertEqual(response.status_code, 200) + self.assertIn("plone.site_logo", response.json()) + self.assertIn("plone.robots_txt", response.json()) + self.assertIn("plone.allowed_sizes", response.json())