Skip to content

Commit

Permalink
Provide a JsonCompatible adapter for RichTextValue objects
Browse files Browse the repository at this point in the history
  • Loading branch information
erral committed Feb 13, 2023
1 parent 0ba390d commit 127d596
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 18 deletions.
2 changes: 2 additions & 0 deletions news/1583.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Provide a JsonCompatible adapter for RichTextValue objects
[erral]
1 change: 1 addition & 0 deletions src/plone/restapi/serializer/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
<adapter factory=".converters.persistent_list_converter" />
<adapter factory=".converters.persistent_mapping_converter" />
<adapter factory=".converters.python_datetime_converter" />
<adapter factory=".converters.richtextvalue_converter" />
<adapter factory=".converters.RichtextDXContextConverter" />
<adapter factory=".converters.set_converter" />
<adapter factory=".converters.bytes_converter" />
Expand Down
15 changes: 12 additions & 3 deletions src/plone/restapi/serializer/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ def json_compatible(value, context=None):
used for converting values that may be None.
"""
if context is not None:
adapter = queryMultiAdapter((value, context), IContextawareJsonCompatible)
adapter = queryMultiAdapter(
(value, context), IContextawareJsonCompatible
)
if adapter:
return adapter()
else:
Expand All @@ -78,8 +80,9 @@ def default_converter(value):
return value

raise TypeError(
"No converter for making"
" {!r} ({}) JSON compatible.".format(value, type(value))
"No converter for making {!r} ({}) JSON compatible.".format(
value, type(value)
)
)


Expand Down Expand Up @@ -173,6 +176,12 @@ def timedelta_converter(value):
return json_compatible(value.total_seconds())


@adapter(IRichTextValue)
@implementer(IJsonCompatible)
def richtextvalue_converter(value):
return json_compatible(value.output)


@adapter(IRichTextValue, IDexterityContent)
@implementer(IContextawareJsonCompatible)
class RichtextDXContextConverter:
Expand Down
18 changes: 18 additions & 0 deletions src/plone/restapi/tests/test_converters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-

import unittest
from plone.app.textfield import RichTextValue
from plone.restapi.interfaces import IJsonCompatible
from plone.restapi.testing import PLONE_RESTAPI_DX_INTEGRATION_TESTING


class TestConverters(unittest.TestCase):

layer = PLONE_RESTAPI_DX_INTEGRATION_TESTING

def test_richtextvalue_converter(self):
"""test that a RichTextValue is converted to a proper HTML"""
html = "<p>This is a demo HTML</p>"
value = RichTextValue(html, "text/html", "text/html")
json_compatible_value = IJsonCompatible(value)
self.assertEqual(json_compatible_value, html)
72 changes: 57 additions & 15 deletions src/plone/restapi/tests/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ class ITaggedValuesSchema(model.Schema):

field_mode_default = schema.TextLine(title="ModeInput", description="")

parametrized_widget_field = schema.TextLine(title="Parametrized widget field")
parametrized_widget_field = schema.TextLine(
title="Parametrized widget field"
)
form.widget(
"parametrized_widget_field", a_param="some_value", defaultFactory=lambda: "Foo"
"parametrized_widget_field",
a_param="some_value",
defaultFactory=lambda: "Foo",
)

not_parametrized_widget_field = schema.TextLine(
Expand Down Expand Up @@ -116,7 +120,9 @@ def test_get_jsonschema_for_fti_non_dx(self):
def test_get_jsonschema_for_portal_type(self):
portal = self.portal
request = self.request
jsonschema = get_jsonschema_for_portal_type("Document", portal, request)
jsonschema = get_jsonschema_for_portal_type(
"Document", portal, request
)
self.assertEqual(jsonschema["title"], "Page")
self.assertEqual(jsonschema["type"], "object")
self.assertIn("title", list(jsonschema["properties"]))
Expand Down Expand Up @@ -154,7 +160,9 @@ def test_get_jsonschema_with_hidden_field(self):
self.assertEqual(
"display", jsonschema["properties"]["field_mode_display"]["mode"]
)
self.assertEqual("input", jsonschema["properties"]["field_mode_input"]["mode"])
self.assertEqual(
"input", jsonschema["properties"]["field_mode_input"]["mode"]
)

def test_get_jsonschema_with_widget_params(self):
ttool = getToolByName(self.portal, "portal_types")
Expand All @@ -163,9 +171,9 @@ def test_get_jsonschema_with_widget_params(self):
)
self.assertEqual(
"some_value",
jsonschema["properties"]["parametrized_widget_field"]["widgetOptions"][
"a_param"
],
jsonschema["properties"]["parametrized_widget_field"][
"widgetOptions"
]["a_param"],
)

def test_do_not_fail_with_non_parametrized_widget(self):
Expand All @@ -186,9 +194,9 @@ def test_resolve_callable_widget_params(self):

self.assertEqual(
"Foo",
jsonschema["properties"]["parametrized_widget_field"]["widgetOptions"].get(
"defaultFactory"
),
jsonschema["properties"]["parametrized_widget_field"][
"widgetOptions"
].get("defaultFactory"),
)

def test_get_jsonschema_with_language_independent_fields(self):
Expand Down Expand Up @@ -254,7 +262,9 @@ def uppercased_title_default(context):
description="My great field",
defaultFactory=uppercased_title_default,
)
adapter = getMultiAdapter((field, folder, self.request), IJsonSchemaProvider)
adapter = getMultiAdapter(
(field, folder, self.request), IJsonSchemaProvider
)

self.assertEqual(
{
Expand Down Expand Up @@ -459,7 +469,11 @@ def test_decimal(self):

def test_int(self):
field = schema.Int(
title="My field", description="My great field", min=0, max=100, default=50
title="My field",
description="My great field",
min=0,
max=100,
default=50,
)
adapter = getMultiAdapter(
(field, self.portal, self.request), IJsonSchemaProvider
Expand Down Expand Up @@ -613,7 +627,9 @@ def test_collection(self):
)

# Test Tuple
field = schema.Tuple(title="My field", value_type=schema.Int(), default=(1, 2))
field = schema.Tuple(
title="My field", value_type=schema.Int(), default=(1, 2)
)
adapter = getMultiAdapter(
(field, self.portal, self.request), IJsonSchemaProvider
)
Expand Down Expand Up @@ -742,9 +758,33 @@ def test_richtext(self):
adapter.get_schema(),
)

def test_richtext_with_default(self):
field = RichText(
title="My field",
description="My great field",
default="<p>Some default value</p>",
)
adapter = getMultiAdapter(
(field, self.portal, self.request), IJsonSchemaProvider
)

self.assertEqual(
{
"type": "string",
"title": "My field",
"factory": "Rich Text",
"description": "My great field",
"widget": "richtext",
"default": "<p>Some default value</p>",
},
adapter.get_schema(),
)

def test_date(self):
field = schema.Date(
title="My field", description="My great field", default=date(2016, 1, 1)
title="My field",
description="My great field",
default=date(2016, 1, 1),
)
adapter = getMultiAdapter(
(field, self.portal, self.request), IJsonSchemaProvider
Expand Down Expand Up @@ -781,7 +821,9 @@ def test_datetime(self):

def test_jsonfield(self):
field = JSONField(
title="My field", description="My great field", widget="my_widget_name"
title="My field",
description="My great field",
widget="my_widget_name",
)
adapter = getMultiAdapter(
(field, self.portal, self.request), IJsonSchemaProvider
Expand Down

0 comments on commit 127d596

Please sign in to comment.