From 8e5ccd0461db66884e3ca67ece9a072b9fedfa32 Mon Sep 17 00:00:00 2001 From: davisagli Date: Wed, 20 Nov 2024 15:19:55 -0800 Subject: [PATCH] [fc] Repository: plone.restapi Branch: refs/heads/main Date: 2024-11-20T15:19:55-08:00 Author: Mikel Larreategi (erral) Commit: https://github.com/plone/plone.restapi/commit/64783c323b326012dded38c45a836e8948ed9601 fix tests (#1844) * fix tests * changelog Files changed: A news/1844.bugfix M src/plone/restapi/tests/test_serializer_summary.py --- last_commit.txt | 145 ++++-------------------------------------------- 1 file changed, 11 insertions(+), 134 deletions(-) diff --git a/last_commit.txt b/last_commit.txt index 6c3f68abbe..3836b6743e 100644 --- a/last_commit.txt +++ b/last_commit.txt @@ -1,143 +1,20 @@ -Repository: plone.app.event +Repository: plone.restapi -Branch: refs/heads/master -Date: 2024-09-12T15:18:54+02:00 +Branch: refs/heads/main +Date: 2024-11-20T15:19:55-08:00 Author: Mikel Larreategi (erral) -Commit: https://github.com/plone/plone.app.event/commit/7426601f1709d12747a3477b15c550e30afc6e5f +Commit: https://github.com/plone/plone.restapi/commit/64783c323b326012dded38c45a836e8948ed9601 -provide an IContentListingObject adapter +fix tests (#1844) -Files changed: -A news/410.feature -A plone/app/event/adapters.py -M plone/app/event/configure.zcml - -b'diff --git a/news/410.feature b/news/410.feature\nnew file mode 100644\nindex 00000000..1ad25924\n--- /dev/null\n+++ b/news/410.feature\n@@ -0,0 +1,2 @@\n+Provide an IContentListingObject adapter\n+[erral]\ndiff --git a/plone/app/event/adapters.py b/plone/app/event/adapters.py\nnew file mode 100644\nindex 00000000..2149dac4\n--- /dev/null\n+++ b/plone/app/event/adapters.py\n@@ -0,0 +1,5 @@\n+from plone.app.contentlisting.realobject import RealContentListingObject\n+\n+\n+class OcurrenceContentListingObject(RealContentListingObject):\n+ pass\ndiff --git a/plone/app/event/configure.zcml b/plone/app/event/configure.zcml\nindex e546895c..f19c0d05 100644\n--- a/plone/app/event/configure.zcml\n+++ b/plone/app/event/configure.zcml\n@@ -67,4 +67,11 @@\n name="plone.app.event"\n />\n \n+\n+ \n+\n \n' - -Repository: plone.app.event - - -Branch: refs/heads/master -Date: 2024-10-10T16:50:40+02:00 -Author: Mikel Larreategi (erral) -Commit: https://github.com/plone/plone.app.event/commit/b2844f1121f98f611a4907efa58ceb476b854e01 - -tests for content listing support - -Files changed: -M plone/app/event/adapters.py -M plone/app/event/configure.zcml -M plone/app/event/tests/test_recurrence.py - -b'diff --git a/plone/app/event/adapters.py b/plone/app/event/adapters.py\nindex 2149dac4..dc661691 100644\n--- a/plone/app/event/adapters.py\n+++ b/plone/app/event/adapters.py\n@@ -1,5 +1,22 @@\n from plone.app.contentlisting.realobject import RealContentListingObject\n+from plone.app.contentlisting.interfaces import IContentListingObject\n+from zope.interface import implementer\n \n \n+@implementer(IContentListingObject)\n class OcurrenceContentListingObject(RealContentListingObject):\n- pass\n+\n+ def __getattr__(self, name):\n+ """We\'ll override getattr so that we can defer name lookups to\n+ the real underlying objects without knowing the names of all\n+ attributes.\n+ """\n+ if name.startswith("_"):\n+ raise AttributeError(name)\n+ obj = self.getObject()\n+ # we need to override the behavior of RealContentListingObject\n+ # because Ocurrence objects rely on acquisition to show their title\n+ # and other attributes\n+ if hasattr(obj, name):\n+ return getattr(obj, name)\n+ raise AttributeError(name)\ndiff --git a/plone/app/event/configure.zcml b/plone/app/event/configure.zcml\nindex f19c0d05..273d58c9 100644\n--- a/plone/app/event/configure.zcml\n+++ b/plone/app/event/configure.zcml\n@@ -70,7 +70,7 @@\n \n \n \ndiff --git a/plone/app/event/tests/test_recurrence.py b/plone/app/event/tests/test_recurrence.py\nindex 21e5a1cd..3c8d25d5 100644\n--- a/plone/app/event/tests/test_recurrence.py\n+++ b/plone/app/event/tests/test_recurrence.py\n@@ -1,6 +1,6 @@\n from OFS.SimpleItem import SimpleItem\n from plone.app.event.base import get_events\n-from plone.app.event.base import RET_MODE_ACCESSORS\n+from plone.app.event.base import RET_MODE_ACCESSORS, RET_MODE_OBJECTS\n from plone.app.event.dx.traverser import OccurrenceTraverser\n from plone.app.event.recurrence import Occurrence\n from plone.app.event.testing import PAEvent_INTEGRATION_TESTING\n@@ -11,6 +11,7 @@\n from plone.app.event.testing import set_timezone\n from plone.app.event.tests.base_setup import AbstractSampleDataEvents\n from plone.app.event.tests.base_setup import patched_now\n+from plone.app.contentlisting.interfaces import IContentListingObject\n from plone.app.testing import setRoles\n from plone.app.testing import TEST_USER_ID\n from plone.app.testing import TEST_USER_PASSWORD\n@@ -352,3 +353,57 @@ def test_recurrence_occurrences_with_range_start_and_end(self):\n \n # Subsequent ones are IOccurrence objects\n self.assertTrue(IOccurrence.providedBy(result[1]))\n+\n+\n+class TestRecurrenceContentListingSupport(unittest.TestCase):\n+ """test that content listing objects are correctly serialized in plone.app.contentlisting objects"""\n+\n+ layer = PAEventDX_INTEGRATION_TESTING\n+\n+ def setUp(self):\n+ self.portal = self.layer["portal"]\n+ self.request = self.layer["request"]\n+\n+ set_browserlayer(self.request)\n+ set_env_timezone(TZNAME)\n+ set_timezone(TZNAME)\n+\n+ now = patched_now()\n+\n+ yesterday = now - datetime.timedelta(days=1)\n+\n+ setRoles(self.portal, TEST_USER_ID, ["Manager"])\n+ self.daily = createContentInContainer(\n+ self.portal,\n+ "plone.app.event.dx.event",\n+ id="daily",\n+ title="Daily Event",\n+ start=now,\n+ end=now + datetime.timedelta(hours=1),\n+ location="Vienna",\n+ recurrence="RRULE:FREQ=DAILY;COUNT=4",\n+ )\n+\n+ def test_recurrence_objects_adapted_to_content_listing_objects(self):\n+ res = get_events(self.portal, ret_mode=RET_MODE_OBJECTS, expand=True)\n+\n+ self.assertEqual(len(res), 4)\n+\n+ first_item = res[0]\n+ second_item = res[1]\n+\n+ first_content_listing_object = IContentListingObject(first_item)\n+ second_content_listing_object = IContentListingObject(second_item)\n+\n+ self.assertEqual(first_content_listing_object.Title(), first_item.Title())\n+ self.assertEqual(second_content_listing_object.Title(), second_item.Title())\n+\n+ self.assertEqual(first_content_listing_object.start, first_item.start)\n+ self.assertEqual(second_content_listing_object.start, second_item.start)\n+\n+ self.assertEqual(first_content_listing_object.end, first_item.end)\n+ self.assertEqual(second_content_listing_object.end, second_item.end)\n+\n+ self.assertTrue(\n+ first_content_listing_object.start < second_content_listing_object.start\n+ )\n' - -Repository: plone.app.event - - -Branch: refs/heads/master -Date: 2024-10-10T16:54:28+02:00 -Author: Mikel Larreategi (erral) -Commit: https://github.com/plone/plone.app.event/commit/a0820a904e15a76d8304f5737d5b9c6e685a779d - -lint - -Files changed: -M plone/app/event/tests/test_recurrence.py - -b'diff --git a/plone/app/event/tests/test_recurrence.py b/plone/app/event/tests/test_recurrence.py\nindex 3c8d25d5..d34a4b78 100644\n--- a/plone/app/event/tests/test_recurrence.py\n+++ b/plone/app/event/tests/test_recurrence.py\n@@ -370,8 +370,6 @@ def setUp(self):\n \n now = patched_now()\n \n- yesterday = now - datetime.timedelta(days=1)\n-\n setRoles(self.portal, TEST_USER_ID, ["Manager"])\n self.daily = createContentInContainer(\n self.portal,\n' - -Repository: plone.app.event - - -Branch: refs/heads/master -Date: 2024-10-10T16:54:56+02:00 -Author: Mikel Larreategi (erral) -Commit: https://github.com/plone/plone.app.event/commit/919e92ff80ec8650e9ce7f3196d76b7034657995 - -lint - -Files changed: -M plone/app/event/adapters.py -M plone/app/event/configure.zcml -M plone/app/event/tests/test_recurrence.py - -b'diff --git a/plone/app/event/adapters.py b/plone/app/event/adapters.py\nindex dc661691..4f3745c2 100644\n--- a/plone/app/event/adapters.py\n+++ b/plone/app/event/adapters.py\n@@ -1,10 +1,10 @@\n-from plone.app.contentlisting.realobject import RealContentListingObject\n from plone.app.contentlisting.interfaces import IContentListingObject\n+from plone.app.contentlisting.realobject import RealContentListingObject\n from zope.interface import implementer\n \n \n @implementer(IContentListingObject)\n-class OcurrenceContentListingObject(RealContentListingObject):\n+class OccurrenceContentListingObject(RealContentListingObject):\n \n def __getattr__(self, name):\n """We\'ll override getattr so that we can defer name lookups to\ndiff --git a/plone/app/event/configure.zcml b/plone/app/event/configure.zcml\nindex 273d58c9..edf0399a 100644\n--- a/plone/app/event/configure.zcml\n+++ b/plone/app/event/configure.zcml\n@@ -69,7 +69,7 @@\n \n \n \ndiff --git a/plone/app/event/tests/test_recurrence.py b/plone/app/event/tests/test_recurrence.py\nindex d34a4b78..34451906 100644\n--- a/plone/app/event/tests/test_recurrence.py\n+++ b/plone/app/event/tests/test_recurrence.py\n@@ -1,6 +1,8 @@\n from OFS.SimpleItem import SimpleItem\n+from plone.app.contentlisting.interfaces import IContentListingObject\n from plone.app.event.base import get_events\n-from plone.app.event.base import RET_MODE_ACCESSORS, RET_MODE_OBJECTS\n+from plone.app.event.base import RET_MODE_ACCESSORS\n+from plone.app.event.base import RET_MODE_OBJECTS\n from plone.app.event.dx.traverser import OccurrenceTraverser\n from plone.app.event.recurrence import Occurrence\n from plone.app.event.testing import PAEvent_INTEGRATION_TESTING\n@@ -11,7 +13,6 @@\n from plone.app.event.testing import set_timezone\n from plone.app.event.tests.base_setup import AbstractSampleDataEvents\n from plone.app.event.tests.base_setup import patched_now\n-from plone.app.contentlisting.interfaces import IContentListingObject\n from plone.app.testing import setRoles\n from plone.app.testing import TEST_USER_ID\n from plone.app.testing import TEST_USER_PASSWORD\n' - -Repository: plone.app.event - - -Branch: refs/heads/master -Date: 2024-10-10T16:55:17+02:00 -Author: Mikel Larreategi (erral) -Commit: https://github.com/plone/plone.app.event/commit/f1a14587db5a5f3289ff641f97e046d9bbe4db73 - -lint - -Files changed: -M plone/app/event/adapters.py - -b'diff --git a/plone/app/event/adapters.py b/plone/app/event/adapters.py\nindex 4f3745c2..95278b3a 100644\n--- a/plone/app/event/adapters.py\n+++ b/plone/app/event/adapters.py\n@@ -15,7 +15,7 @@ def __getattr__(self, name):\n raise AttributeError(name)\n obj = self.getObject()\n # we need to override the behavior of RealContentListingObject\n- # because Ocurrence objects rely on acquisition to show their title\n+ # because Occurrence objects rely on acquisition to show their title\n # and other attributes\n if hasattr(obj, name):\n return getattr(obj, name)\n' - -Repository: plone.app.event - - -Branch: refs/heads/master -Date: 2024-11-11T08:14:11+01:00 -Author: Mikel Larreategi (erral) -Commit: https://github.com/plone/plone.app.event/commit/7aa15fa8f3e7e143b38668a6298ead3fe00f7960 - -Update plone/app/event/adapters.py - -Co-authored-by: David Glick <david@glicksoftware.com> - -Files changed: -M plone/app/event/adapters.py - -b'diff --git a/plone/app/event/adapters.py b/plone/app/event/adapters.py\nindex 95278b3a..0c6a64b4 100644\n--- a/plone/app/event/adapters.py\n+++ b/plone/app/event/adapters.py\n@@ -17,6 +17,4 @@ def __getattr__(self, name):\n # we need to override the behavior of RealContentListingObject\n # because Occurrence objects rely on acquisition to show their title\n # and other attributes\n- if hasattr(obj, name):\n- return getattr(obj, name)\n- raise AttributeError(name)\n+ return getattr(obj, name)\n' - -Repository: plone.app.event - - -Branch: refs/heads/master -Date: 2024-11-12T07:59:29+01:00 -Author: Mikel Larreategi (erral) -Commit: https://github.com/plone/plone.app.event/commit/5b8ac8502b49d1ac4dda57e40e6282b87c59d939 - -Merge branch 'master' into erral-issue-410 - -Files changed: -A news/414.bugfix -A plone/app/event/tests/test_robot.py -M .pre-commit-config.yaml -M CHANGES.rst -M plone/app/event/dx/behaviors.py -M plone/app/event/testing.py -M plone/app/event/tests/robot/test_event_roundtrip.robot -M plone/app/event/tests/robot/variables.py -M setup.py -D news/407.bugfix -D plone/app/event/tests/INACTIVE_test_robot.py - -b'diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nindex 14603265..f70417dc 100644\n--- a/.pre-commit-config.yaml\n+++ b/.pre-commit-config.yaml\n@@ -16,7 +16,7 @@ repos:\n hooks:\n - id: isort\n - repo: https://github.com/psf/black\n- rev: 24.8.0\n+ rev: 24.10.0\n hooks:\n - id: black\n - repo: https://github.com/collective/zpretty\ndiff --git a/CHANGES.rst b/CHANGES.rst\nindex 6f079916..63ac10f4 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -8,6 +8,26 @@ Changelog\n \n .. towncrier release notes start\n \n+5.1.8 (2024-10-23)\n+------------------\n+\n+New features:\n+\n+\n+- Update robot framework tests to use `robotframework-browser` (`playwright` integration on robotframework).\n+ [1letter] (#408)\n+\n+\n+5.1.7 (2024-09-24)\n+------------------\n+\n+Bug fixes:\n+\n+\n+- If the name is None, display the mail. Otherwise, a person icon with no useful info is displayed.\n+ [yurj] (#407)\n+\n+\n 5.1.6 (2024-08-22)\n ------------------\n \ndiff --git a/news/407.bugfix b/news/407.bugfix\ndeleted file mode 100644\nindex 1b59deb7..00000000\n--- a/news/407.bugfix\n+++ /dev/null\n@@ -1,2 +0,0 @@\n-[yurj]\n-If the name is None, display the mail. Otherwise, a person icon with no useful info is displayed.\ndiff --git a/news/414.bugfix b/news/414.bugfix\nnew file mode 100644\nindex 00000000..244d3225\n--- /dev/null\n+++ b/news/414.bugfix\n@@ -0,0 +1,2 @@\n+fix import of TextLinesFieldWidget, correctness the rendering of EventAttendees TextLinesFieldWidget\n+[1letter]\ndiff --git a/plone/app/event/dx/behaviors.py b/plone/app/event/dx/behaviors.py\nindex d29addf2..f8595105 100644\n--- a/plone/app/event/dx/behaviors.py\n+++ b/plone/app/event/dx/behaviors.py\n@@ -51,7 +51,7 @@\n # Import fails for Plone < 6.1\n # version pin of plone.app.z3cform is set to plone.app.z3cform==4.3.2\n # TextLinesFieldWidget is introduced in plone.app.z3cform==4.4.0\n- from plone.app.z3cform.widgets.textlines import TextLinesFieldWidget\n+ from plone.app.z3cform.widgets.text import TextLinesFieldWidget\n except ImportError:\n from z3c.form.browser.textlines import TextLinesFieldWidget\n \ndiff --git a/plone/app/event/testing.py b/plone/app/event/testing.py\nindex e6e83ecf..ef5c3610 100644\n--- a/plone/app/event/testing.py\n+++ b/plone/app/event/testing.py\n@@ -1,5 +1,5 @@\n from plone.app.event.interfaces import IBrowserLayer\n-from plone.app.robotframework.testing import AUTOLOGIN_LIBRARY_FIXTURE\n+from plone.app.robotframework.testing import REMOTE_LIBRARY_BUNDLE_FIXTURE\n from plone.app.testing import FunctionalTesting\n from plone.app.testing import IntegrationTesting\n from plone.app.testing import PLONE_FIXTURE\n@@ -123,7 +123,7 @@ def setUpPloneSite(self, portal):\n PAEventDX_ROBOT_TESTING = FunctionalTesting(\n bases=(\n PAEventDX_FIXTURE,\n- AUTOLOGIN_LIBRARY_FIXTURE,\n+ REMOTE_LIBRARY_BUNDLE_FIXTURE,\n WSGI_SERVER_FIXTURE,\n ),\n name="plone.app.event.dx:Robot",\ndiff --git a/plone/app/event/tests/robot/test_event_roundtrip.robot b/plone/app/event/tests/robot/test_event_roundtrip.robot\nindex 884a4cb9..61df8455 100644\n--- a/plone/app/event/tests/robot/test_event_roundtrip.robot\n+++ b/plone/app/event/tests/robot/test_event_roundtrip.robot\n@@ -1,49 +1,41 @@\n *** Settings ***\n \n-Resource plone/app/robotframework/selenium.robot\n-Resource plone/app/robotframework/keywords.robot\n+Resource plone/app/robotframework/browser.robot\n \n-Library Remote ${PLONE_URL}/RobotRemote\n+Library Remote ${PLONE_URL}/RobotRemote\n \n-Test Setup Open test browser\n-Test Teardown Close all browsers\n+Test Setup Run Keywords Plone test setup\n+Test Teardown Run keywords Plone test teardown\n \n-Variables plone/app/event/tests/robot/variables.py\n+Variables variables.py\n \n \n-*** Variables ***\n-\n-\n-*** Test Cases ***\n+*** Test cases ***\n \n Scenario: Create and view an event\n- Given a site owner\n- and an event add form\n- Debug\n- When I select a date in calendar overlay\n- Then it should be filled in the form\n-\n- When I click on Recurrence Add\n- Then I should see the recurrence overlay\n+ Given a site owner\n+ and an event add form\n+ When I click on Recurrence Add\n+ Then I should see the recurrence overlay\n \n- When I select weekly repeat\n- Then I should see the recurrence overlay in weeekly repeat mode\n+ When I select weekly repeat\n+ Then I should see the recurrence overlay in weeekly repeat mode\n \n- When I fill 3 occurrences\n- Then I should see 3 occurrences in the overlay\n+ When I fill 3 occurrences\n+ Then I should see 3 occurrences in the overlay\n \n- When I click save in the overlay\n- Then the overlay should be closed\n- And I should see 3 occurrences in the form\n+ When I click save in the overlay\n+ Then the overlay should be closed\n+ and I should see 3 occurrences in the form\n \n- When I click save in the form\n- Then I should see the event detail view\n+ When I click save in the form\n+ Then I should see the event detail view\n \n- When I open an event occurrence\n- Then I should see the occurrence detail view\n+ When I open an event occurrence\n+ Then I should see the occurrence detail view\n \n- When I open the event listing\n- Then I should see the event listing view\n+ When I open the event listing\n+ Then I should see the event listing view\n \n \n *** Keywords ***\n@@ -51,115 +43,111 @@ Scenario: Create and view an event\n # Given\n \n a site owner\n- Enable autologin as Manager\n+ Enable autologin as Manager\n \n an event add form\n- Go to ${PLONE_URL}/++add++Event\n- Wait until page contains Add Event\n- Input text name=form.widgets.IDublinCore.title Testevent\n- Input text id=form-widgets-IDublinCore-description Test description\n- Input text id=form-widgets-IEventLocation-location Test location\n- Input text id=form-widgets-IEventAttendees-attendees Test attendee\n- Input text id=form-widgets-IEventContact-contact_name Test name\n- Input text id=form-widgets-IEventContact-contact_email test@email.com\n- Input text id=form-widgets-IEventContact-contact_phone +1234567890\n- Input text id=form-widgets-IEventContact-event_url http://test.url\n+ Go to ${PLONE_URL}/++add++Event\n+ Type text //input[@name="form.widgets.IDublinCore.title"] Testevent\n+ Type text //textarea[@id="form-widgets-IDublinCore-description"] Test description\n+ Type text //input[@id="form-widgets-IEventLocation-location"] Test location\n+ Type text //textarea[@id="form-widgets-IEventAttendees-attendees"] Test attendee\n+ Type text //input[@id="form-widgets-IEventContact-contact_name"] Test name\n+ Type text //input[@id="form-widgets-IEventContact-contact_email"] test@email.com\n+ Type text //input[@id="form-widgets-IEventContact-contact_phone"] +1234567890\n+ Type text //input[@id="form-widgets-IEventContact-event_url"] http://test.url\n+\n+ # we can\'t set safely the date in the test via native browser ui "date input" element\n+ # reason 1: different ui\'s, depending on language of system browser\n+ # 12 hours format with meridiem input (AM/PM) vs. 24 hours format\n+ # reason 2: shadow root (user-agent) can\'t access via css or xpath selectors\n+ #\n+ # temporarily solution: set value via javascript\n+\n+ Evaluate JavaScript //input[@name="form.widgets.IEventBasic.start"]\n+ ... (el, arg) => {\n+ ... el.setAttribute("value", arg)\n+ ... }\n+ ... all_elements=False\n+ ... arg=${EVENT_START_ISO}\n+\n+ Evaluate JavaScript //input[@name="form.widgets.IEventBasic.start"]\n+ ... (el,arg) => {\n+ ... el.setAttribute("value", arg)\n+ ... }\n+ ... all_elements=False\n+ ... arg=${EVENT_END_ISO}\n \n # When\n \n-I select a date in calendar overlay\n- Click Element xpath=//div[@data-fieldname="form.widgets.IEventBasic.start"]//input[contains(@class,"pattern-pickadate-date")]\n- Wait until page contains Sat\n-# For Javascript: Month 1 = February.\n- Select from list by label css=div[data-fieldname="form.widgets.IEventBasic.start"] .picker__select--month ${EVENT_START_MONTHNAME}\n- Select from list by label css=div[data-fieldname="form.widgets.IEventBasic.start"] select.picker__select--year ${EVENT_START_YEAR}\n- Click Element xpath=//div[@data-fieldname="form.widgets.IEventBasic.start"]//div[contains(@class, \'picker__day\')][contains(text(), "${EVENT_START_DAY}")]\n-# Select Times\n- Click Element xpath=//div[@data-fieldname="form.widgets.IEventBasic.start"]//input[contains(@class,"pattern-pickadate-time")]\n- Click Element xpath=//div[@data-fieldname="form.widgets.IEventBasic.start"]//div[contains(@class, \'picker--time\')]//li[contains(@class, \'picker__list-item\')][contains(text(), "${EVENT_START_HOUR}:00")]\n-\n-\n I click on Recurrence Add\n- Click Link css=a[name=\'riedit\']\n- Wait until page contains Repeat\n+ Click //a[@name="riedit"]\n \n I select weekly repeat\n- Select From List by label css=#rirtemplate weekly\n+ Select Options By //div[contains(@class,"modal-wrapper")]//select[@id="rirtemplate"] value weekly\n \n I fill ${NUM} occurrences\n- Input text name=rirangebyoccurrencesvalue ${NUM}\n- Focus css=.risavebutton\n+ Type Text //div[contains(@class,"modal-wrapper")]//form//input[@name="rirangebyoccurrencesvalue"] ${NUM}\n+ Keyboard Key press Tab\n \n I click save in the overlay\n- Click Button css=.risavebutton\n+ Click //div[contains(@class,"modal-wrapper")]//div[@class="modal-footer"]//button[contains(@class,"risavebutton")]\n \n I click save in the form\n- Click Button name=form.buttons.save\n+ Click //button[@name="form.buttons.save"]\n \n I open an event occurrence\n- Go to ${PLONE_URL}/testevent/2014-02-17\n+ ${url}= Get Property //*[@id="content-core"]/div/div/div/div[2]/div[1]/div/div/div[2]/p/span[2]/a href\n+ Go to ${url}\n \n I open the event listing\n- Go to ${PLONE_URL}/@@event_listing?mode=all\n-\n+ Go to ${PLONE_URL}/@@event_listing?mode=all\n \n # Then\n \n-it should be filled in the form\n- Textfield Value Should Be css=#formfield-form-widgets-IEventBasic-start input.pattern-pickadate-date ${EVENT_START_MONTHNAME} ${EVENT_START_DAY}, ${EVENT_START_YEAR}\n- Textfield Should Contain css=#formfield-form-widgets-IEventBasic-start input.pattern-pickadate-time ${EVENT_START_HOUR}:00\n- Textfield Value Should Be css=#formfield-form-widgets-IEventBasic-end input.pattern-pickadate-date ${EVENT_END_MONTHNAME} ${EVENT_END_DAY}, ${EVENT_END_YEAR}\n- Textfield Should Contain css=#formfield-form-widgets-IEventBasic-end input.pattern-pickadate-time ${EVENT_END_HOUR}:00\n-\n I should see the recurrence overlay\n- Page Should Contain Recurrence\n- Page Should Contain Selected dates\n- Page Should Contain Element //div[contains(@class, \'occurrence\') and contains(@class, \'start\')] 1\n- Page Should Contain Element //div[contains(@class, \'occurrence\') and contains(@class, \'rrule\')] 6\n+ Get Text //div[contains(@class,"modal-wrapper")]//form/div[@class="rioccurrencesactions"]/div/h6/strong should be Selected dates\n+ Get Element Count //div[contains(@class, \'occurrence\') and contains(@class, \'start\')] should be 1\n+ Get Element Count //div[contains(@class, \'occurrence\') and contains(@class, \'rrule\')] should be 6\n \n I should see the recurrence overlay in weeekly repeat mode\n- Page Should Contain Repeats every\n- Page Should Contain Sun\n- Page Should Contain Mon\n- Page Should Contain Tue\n- Page Should Contain Wed\n- Page Should Contain Thu\n- Page Should Contain Fri\n- Page Should Contain Sat\n-\n-the overlay should be closed\n- Page Should Not Contain class=.riform\n-\n-# About class matching with x-path, see:\n-# http://stackoverflow.com/questions/1604471/how-can-i-find-an-element-by-css-class-with-xpath\n+ Get Text //div[contains(@class,"modal-wrapper")]//form//div[@id="riweeklyinterval"] contains Repeat every\n+ Get Text //div[contains(@class,"modal-wrapper")]//form//div[@id="riweeklyweekdays"] contains Sun\n+ Get Text //div[contains(@class,"modal-wrapper")]//form//div[@id="riweeklyweekdays"] contains Mon\n+ Get Text //div[contains(@class,"modal-wrapper")]//form//div[@id="riweeklyweekdays"] contains Tue\n+ Get Text //div[contains(@class,"modal-wrapper")]//form//div[@id="riweeklyweekdays"] contains Wed\n+ Get Text //div[contains(@class,"modal-wrapper")]//form//div[@id="riweeklyweekdays"] contains Thu\n+ Get Text //div[contains(@class,"modal-wrapper")]//form//div[@id="riweeklyweekdays"] contains Fri\n+ Get Text //div[contains(@class,"modal-wrapper")]//form//div[@id="riweeklyweekdays"] contains Sat\n \n I should see ${NUM} occurrences in the overlay\n- Page Should Contain Element //div[contains(concat(\' \', normalize-space(@class), \' \'), \' rioccurrences \')]/div[contains(@class, \'occurrence\')] ${NUM}\n+ Get Element Count //div[contains(@class,"modal-wrapper")]//div[@class="rioccurrences"]/div[contains(@class, \'occurrence\')] should be ${NUM}\n+\n+the overlay should be closed\n+ Get Element Count //div[contains(@class,"modal-wrapper")]//*[contains(@class,"riform")] should be 0\n \n I should see ${NUM} occurrences in the form\n- Page Should Contain Element //div[contains(concat(\' \', normalize-space(@class), \' \'), \' ridisplay \')]/div[contains(concat(\' \', normalize-space(@class), \' \'), \' rioccurrences \')]/div[contains(@class, \'occurrence\')] ${NUM}\n+ Get Element Count //div[contains(@class,"ridisplay")]//div[@class="rioccurrences"]/div[contains(@class, \'occurrence\')] should be ${NUM}\n \n I should see the event detail view\n- Page Should Contain Testevent\n- Page Should Contain Test description\n- Page Should Contain All dates\n- Page Should Contain Test location\n- Page Should Contain Test name\n- Page Should Contain +1234567890\n- Page Should Contain Test attendee\n- Page Should Contain Visit external website\n- Page Should Contain iCal\n+ Get Text //*[@id="global_statusmessage"] contains Item created\n+ Get Text //article[@id="content"]/header contains Testevent\n+ Get Text //article[@id="content"]/header contains Test description\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains Test location\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains Test name\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains +1234567890\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains Test attendee\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains Visit external website\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains iCal\n \n I should see the occurrence detail view\n- Page Should Contain Testevent\n- Page Should Contain Test description\n- Page Should Contain All dates\n- Page Should Contain Test location\n- Page Should Contain Test name\n- Page Should Contain +1234567890\n- Page Should Contain Test attendee\n- Page Should Contain Visit external website\n- Page Should Contain iCal\n+ Get Text //article[@id="content"]/header contains Testevent\n+ Get Text //article[@id="content"]/header contains Test description\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains Test location\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains Test name\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains +1234567890\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains Test attendee\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains Visit external website\n+ Get Text //div[@id="content-core"]//div[contains(@class,"event-summary")] contains iCal\n \n I should see the event listing view\n- Page Should Contain Element //article[@class="vevent"] 3\n+ Get Element Count //article[contains(@class,"vevent")] should be 3\ndiff --git a/plone/app/event/tests/robot/variables.py b/plone/app/event/tests/robot/variables.py\nindex 4514b019..646e8704 100644\n--- a/plone/app/event/tests/robot/variables.py\n+++ b/plone/app/event/tests/robot/variables.py\n@@ -1,23 +1,10 @@\n-# setup dates\n from datetime import datetime\n from datetime import timedelta\n \n-import locale\n-\n \n # important for MONTHNAME\n-locale.setlocale(locale.LC_ALL, "en_US")\n-\n NOW = datetime.now() + timedelta(days=1)\n-EVENT_START_YEAR = NOW.strftime("%Y")\n-EVENT_START_MONTH = str(NOW.month - 1)\n-EVENT_START_MONTHNAME = NOW.strftime("%B")\n-EVENT_START_DAY = NOW.strftime("%d")\n-EVENT_START_HOUR = str(int(NOW.strftime("%I")))\n+EVENT_START_ISO = NOW.strftime("%Y-%m-%dT%H:00")\n \n END = NOW + timedelta(hours=1)\n-EVENT_END_YEAR = END.strftime("%Y")\n-EVENT_END_MONTH = str(END.month - 1)\n-EVENT_END_MONTHNAME = END.strftime("%B")\n-EVENT_END_DAY = END.strftime("%d")\n-EVENT_END_HOUR = str(int(END.strftime("%I")))\n+EVENT_END_ISO = END.strftime("%Y-%m-%dT%H:00")\ndiff --git a/plone/app/event/tests/INACTIVE_test_robot.py b/plone/app/event/tests/test_robot.py\nsimilarity index 97%\nrename from plone/app/event/tests/INACTIVE_test_robot.py\nrename to plone/app/event/tests/test_robot.py\nindex 83e5c391..223699c4 100644\n--- a/plone/app/event/tests/INACTIVE_test_robot.py\n+++ b/plone/app/event/tests/test_robot.py\n@@ -1,4 +1,3 @@\n-# -*- conding: utf-8 -*-\n from plone.app.event.testing import PAEventDX_ROBOT_TESTING\n from plone.app.testing import ROBOT_TEST_LEVEL\n from plone.testing import layered\ndiff --git a/setup.py b/setup.py\nindex e74c7daa..4e3d61c9 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -3,7 +3,7 @@\n from setuptools import setup\n \n \n-version = "5.1.7.dev0"\n+version = "5.1.9.dev0"\n \n \n long_description = "\\n\\n".join(\n' - -Repository: plone.app.event - - -Branch: refs/heads/master -Date: 2024-11-18T22:00:34-08:00 -Author: David Glick (davisagli) -Commit: https://github.com/plone/plone.app.event/commit/b816b2a9cb3e7876380e6429c7f97513320696e6 - -Merge pull request #411 from plone/erral-issue-410 - -provide an IContentListingObject adapter +* fix tests + +* changelog Files changed: -A news/410.feature -A plone/app/event/adapters.py -M plone/app/event/configure.zcml -M plone/app/event/tests/test_recurrence.py +A news/1844.bugfix +M src/plone/restapi/tests/test_serializer_summary.py -b'diff --git a/news/410.feature b/news/410.feature\nnew file mode 100644\nindex 00000000..1ad25924\n--- /dev/null\n+++ b/news/410.feature\n@@ -0,0 +1,2 @@\n+Provide an IContentListingObject adapter\n+[erral]\ndiff --git a/plone/app/event/adapters.py b/plone/app/event/adapters.py\nnew file mode 100644\nindex 00000000..0c6a64b4\n--- /dev/null\n+++ b/plone/app/event/adapters.py\n@@ -0,0 +1,20 @@\n+from plone.app.contentlisting.interfaces import IContentListingObject\n+from plone.app.contentlisting.realobject import RealContentListingObject\n+from zope.interface import implementer\n+\n+\n+@implementer(IContentListingObject)\n+class OccurrenceContentListingObject(RealContentListingObject):\n+\n+ def __getattr__(self, name):\n+ """We\'ll override getattr so that we can defer name lookups to\n+ the real underlying objects without knowing the names of all\n+ attributes.\n+ """\n+ if name.startswith("_"):\n+ raise AttributeError(name)\n+ obj = self.getObject()\n+ # we need to override the behavior of RealContentListingObject\n+ # because Occurrence objects rely on acquisition to show their title\n+ # and other attributes\n+ return getattr(obj, name)\ndiff --git a/plone/app/event/configure.zcml b/plone/app/event/configure.zcml\nindex e546895c..edf0399a 100644\n--- a/plone/app/event/configure.zcml\n+++ b/plone/app/event/configure.zcml\n@@ -67,4 +67,11 @@\n name="plone.app.event"\n />\n \n+\n+ \n+\n \ndiff --git a/plone/app/event/tests/test_recurrence.py b/plone/app/event/tests/test_recurrence.py\nindex 21e5a1cd..34451906 100644\n--- a/plone/app/event/tests/test_recurrence.py\n+++ b/plone/app/event/tests/test_recurrence.py\n@@ -1,6 +1,8 @@\n from OFS.SimpleItem import SimpleItem\n+from plone.app.contentlisting.interfaces import IContentListingObject\n from plone.app.event.base import get_events\n from plone.app.event.base import RET_MODE_ACCESSORS\n+from plone.app.event.base import RET_MODE_OBJECTS\n from plone.app.event.dx.traverser import OccurrenceTraverser\n from plone.app.event.recurrence import Occurrence\n from plone.app.event.testing import PAEvent_INTEGRATION_TESTING\n@@ -352,3 +354,55 @@ def test_recurrence_occurrences_with_range_start_and_end(self):\n \n # Subsequent ones are IOccurrence objects\n self.assertTrue(IOccurrence.providedBy(result[1]))\n+\n+\n+class TestRecurrenceContentListingSupport(unittest.TestCase):\n+ """test that content listing objects are correctly serialized in plone.app.contentlisting objects"""\n+\n+ layer = PAEventDX_INTEGRATION_TESTING\n+\n+ def setUp(self):\n+ self.portal = self.layer["portal"]\n+ self.request = self.layer["request"]\n+\n+ set_browserlayer(self.request)\n+ set_env_timezone(TZNAME)\n+ set_timezone(TZNAME)\n+\n+ now = patched_now()\n+\n+ setRoles(self.portal, TEST_USER_ID, ["Manager"])\n+ self.daily = createContentInContainer(\n+ self.portal,\n+ "plone.app.event.dx.event",\n+ id="daily",\n+ title="Daily Event",\n+ start=now,\n+ end=now + datetime.timedelta(hours=1),\n+ location="Vienna",\n+ recurrence="RRULE:FREQ=DAILY;COUNT=4",\n+ )\n+\n+ def test_recurrence_objects_adapted_to_content_listing_objects(self):\n+ res = get_events(self.portal, ret_mode=RET_MODE_OBJECTS, expand=True)\n+\n+ self.assertEqual(len(res), 4)\n+\n+ first_item = res[0]\n+ second_item = res[1]\n+\n+ first_content_listing_object = IContentListingObject(first_item)\n+ second_content_listing_object = IContentListingObject(second_item)\n+\n+ self.assertEqual(first_content_listing_object.Title(), first_item.Title())\n+ self.assertEqual(second_content_listing_object.Title(), second_item.Title())\n+\n+ self.assertEqual(first_content_listing_object.start, first_item.start)\n+ self.assertEqual(second_content_listing_object.start, second_item.start)\n+\n+ self.assertEqual(first_content_listing_object.end, first_item.end)\n+ self.assertEqual(second_content_listing_object.end, second_item.end)\n+\n+ self.assertTrue(\n+ first_content_listing_object.start < second_content_listing_object.start\n+ )\n' +b'diff --git a/news/1844.bugfix b/news/1844.bugfix\nnew file mode 100644\nindex 000000000..2cee040a3\n--- /dev/null\n+++ b/news/1844.bugfix\n@@ -0,0 +1,2 @@\n+Fix tests after #1839 and plone.app.event#411\n+[erral]\ndiff --git a/src/plone/restapi/tests/test_serializer_summary.py b/src/plone/restapi/tests/test_serializer_summary.py\nindex 794579241..9a7b7db45 100644\n--- a/src/plone/restapi/tests/test_serializer_summary.py\n+++ b/src/plone/restapi/tests/test_serializer_summary.py\n@@ -273,7 +273,10 @@ def test_dx_event_with_recurrence_new_version(self):\n tomorrow_str = tomorrow.strftime("%Y-%m-%d")\n ot = OccurrenceTraverser(self.event, self.request)\n ocurrence = ot.publishTraverse(self.request, tomorrow_str)\n+ self.request.form["metadata_fields"] = ["start"]\n summary = getMultiAdapter((ocurrence, self.request), ISerializeToJsonSummary)()\n-\n- self.assertEqual(summary["start"], tomorrow_str)\n- self.assertEqual(summary["Title"], ocurrence.Title())\n+ self.assertEqual(\n+ datetime.fromisoformat(summary["start"]).date().isoformat(),\n+ tomorrow.date().isoformat(),\n+ )\n+ self.assertEqual(summary["title"], ocurrence.Title())\n'