diff --git a/.editorconfig b/.editorconfig index 919b41166..5b3c112c3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,5 @@ # Generated from: -# https://github.com/plone/meta/tree/master/config/default +# https://github.com/plone/meta/tree/main/config/default # See the inline comments on how to expand/tweak this configuration file # # EditorConfig Configuration file, for more details see: @@ -13,7 +13,8 @@ root = true -[*] # For All Files +[*] +# Default settings for all files. # Unix-style newlines with a newline ending every file end_of_line = lf insert_final_newline = true @@ -29,13 +30,15 @@ max_line_length = off # 4 space indentation indent_size = 4 -[*.{yml,zpt,pt,dtml,zcml}] +[*.{yml,zpt,pt,dtml,zcml,html,xml}] # 2 space indentation indent_size = 2 -[*.{json,jsonl,js,jsx,ts,tsx,css,less,scss,html}] # Frontend development +[*.{json,jsonl,js,jsx,ts,tsx,css,less,scss}] +# Frontend development # 2 space indentation indent_size = 2 +max_line_length = 80 [{Makefile,.gitmodules}] # Tab indentation (no size specified, but view as 4 spaces) diff --git a/.flake8 b/.flake8 index 7ef4f64d9..38918f42f 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ # Generated from: -# https://github.com/plone/meta/tree/master/config/default +# https://github.com/plone/meta/tree/main/config/default # See the inline comments on how to expand/tweak this configuration file [flake8] doctests = 1 diff --git a/.github/workflows/meta.yml b/.github/workflows/meta.yml index 4748f0f48..c9848bcbc 100644 --- a/.github/workflows/meta.yml +++ b/.github/workflows/meta.yml @@ -1,5 +1,5 @@ # Generated from: -# https://github.com/plone/meta/tree/master/config/default +# https://github.com/plone/meta/tree/main/config/default # See the inline comments on how to expand/tweak this configuration file name: Meta on: @@ -13,16 +13,63 @@ on: - main workflow_dispatch: +## +# To set environment variables for all jobs, add in .meta.toml: +# [github] +# env = """ +# debug: 1 +# image-name: 'org/image' +# image-tag: 'latest' +# """ +## + jobs: qa: - uses: plone/meta/.github/workflows/qa.yml@master + uses: plone/meta/.github/workflows/qa.yml@main test: - uses: plone/meta/.github/workflows/test.yml@master + uses: plone/meta/.github/workflows/test.yml@main coverage: - uses: plone/meta/.github/workflows/coverage.yml@master + uses: plone/meta/.github/workflows/coverage.yml@main dependencies: - uses: plone/meta/.github/workflows/dependencies.yml@master - release-ready: - uses: plone/meta/.github/workflows/release_ready.yml@master + uses: plone/meta/.github/workflows/dependencies.yml@main + release_ready: + uses: plone/meta/.github/workflows/release_ready.yml@main circular: - uses: plone/meta/.github/workflows/circular.yml@master + uses: plone/meta/.github/workflows/circular.yml@main + +## +# To modify the list of default jobs being created add in .meta.toml: +# [github] +# jobs = [ +# "qa", +# "test", +# "coverage", +# "dependencies", +# "release_ready", +# "circular", +# ] +## + +## +# To request that some OS level dependencies get installed +# when running tests/coverage jobs, add in .meta.toml: +# [github] +# os_dependencies = "git libxml2 libxslt" +## + +## +# To test against a specific matrix of python versions +# when running tests jobs, add in .meta.toml: +# [github] +# py_versions = "['3.12', '3.11']" +## + + +## +# Specify additional jobs in .meta.toml: +# [github] +# extra_lines = """ +# another: +# uses: org/repo/.github/workflows/file.yml@main +# """ +## diff --git a/.gitignore b/.gitignore index 81594fde9..486392f69 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,18 @@ # Generated from: -# https://github.com/plone/meta/tree/master/config/default +# https://github.com/plone/meta/tree/main/config/default # See the inline comments on how to expand/tweak this configuration file # python related *.egg-info *.pyc *.pyo +# translation related +*.mo + # tools related build/ .coverage +.*project coverage.xml dist/ docs/_build @@ -31,6 +35,7 @@ lib64 parts/ pyvenv.cfg var/ +local.cfg # mxdev /instance/ diff --git a/.meta.toml b/.meta.toml index d3ded7c05..20de39039 100644 --- a/.meta.toml +++ b/.meta.toml @@ -1,10 +1,13 @@ # Generated from: -# https://github.com/plone/meta/tree/master/config/default +# https://github.com/plone/meta/tree/main/config/default # See the inline comments on how to expand/tweak this configuration file [meta] template = "default" -commit-id = "7723aeaf" +commit-id = "a89af8f2" [pyproject] codespell_ignores = "oder,ist,crate" -dependencies_ignores = "['ZServer', 'plone.app.event', 'Products.CFMPlone',]" +dependencies_ignores = "['ZServer', 'plone.app.event', 'Products.CMFPlone',]" + +[tox] +constraints_file = "https://dist.plone.org/release/6.1-dev/constraints.txt" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5ef2b8196..14603265d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ # Generated from: -# https://github.com/plone/meta/tree/master/config/default +# https://github.com/plone/meta/tree/main/config/default # See the inline comments on how to expand/tweak this configuration file ci: autofix_prs: false @@ -7,20 +7,20 @@ ci: repos: - repo: https://github.com/asottile/pyupgrade - rev: v3.4.0 + rev: v3.17.0 hooks: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 24.8.0 hooks: - id: black - repo: https://github.com/collective/zpretty - rev: 3.1.0a2 + rev: 3.1.0 hooks: - id: zpretty @@ -32,11 +32,19 @@ repos: # """ ## - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 7.1.1 hooks: - id: flake8 + +## +# Add extra configuration options in .meta.toml: +# [pre_commit] +# flake8_extra_lines = """ +# _your own configuration lines_ +# """ +## - repo: https://github.com/codespell-project/codespell - rev: v2.2.4 + rev: v2.3.0 hooks: - id: codespell additional_dependencies: @@ -58,15 +66,25 @@ repos: hooks: - id: pyroma - repo: https://github.com/mgedmin/check-python-versions - rev: "0.21.2" + rev: "0.22.0" hooks: - id: check-python-versions args: ['--only', 'setup.py,pyproject.toml'] - repo: https://github.com/collective/i18ndude - rev: "6.0.0" + rev: "6.2.1" hooks: - id: i18ndude + +## +# Add extra configuration options in .meta.toml: +# [pre_commit] +# i18ndude_extra_lines = """ +# _your own configuration lines_ +# """ +## + + ## # Add extra configuration options in .meta.toml: # [pre_commit] diff --git a/CHANGES.rst b/CHANGES.rst index 61f1f758d..deafacf09 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,86 @@ Changelog .. towncrier release notes start +4.0.0 (2024-09-03) +------------------ + +Breaking changes: + + +- Do not enable plone.allowdiscussion by default, it is a core add-on now. + This is for Plone 6.1, so is a breaking change. + [@jensens] (#665) + + +3.0.9 (2024-06-07) +------------------ + +Bug fixes: + + +- No longer set ``portal_properties.site_properties.visible_ids`` on site creation. + The ``portal_properties`` tools is deprecated, ``visible_ids`` was not set as real property, and usage of ``visible_ids`` was largely removed in Plone 5.0 already. + You already can no longer set ``visible ids`` in the Editing control panel, nor in the member preferences. + The only remaining use for ``visible_ids``, if set to true, was to show the page ids on the 'select default page' form. + [maurits] (#125) + + +3.0.8 (2024-05-30) +------------------ + +Bug fixes: + + +- Support using the file template on objects that have no file attributes. [ale-rt] (#688) +- Fixed p.a.widgets `moved` DeprecationWarning [jensens] (#690) + + +3.0.7 (2024-04-25) +------------------ + +Bug fixes: + + +- Fix ILeadImageBehavior and IRichTextBehavior interfaces were the name change was forgotten. + [thet] (#681) + + +3.0.6 (2024-03-15) +------------------ + +Bug fixes: + + +- Fix folder listing template when `plone.eventlocation` behavior is disabled for Events. + [petschki] (#679) + + +Internal: + + +- Update configuration files. + [plone devs] (6e36bcc4) + + +3.0.5 (2023-10-25) +------------------ + +Bug fixes: + + +- Fix link_redirect_view, respect vhm vs none-vhm url schemes @1letter (#671) + + +3.0.4 (2023-10-07) +------------------ + +Internal: + + +- Update configuration files. + [plone devs] (7723aeaf) + + 3.0.3 (2023-05-22) ------------------ @@ -437,7 +517,7 @@ Bug fixes: New features: -- Support ILeadImage behavior when display collection album view. +- Support ILeadImageBehavior when display collection album view. [rodfersou] (#524) - Add more log-messages during migration from AT to DX. [pbauer] (#526) @@ -516,7 +596,7 @@ Bug fixes: Breaking changes: -- ILeadImage and IRichText behaviors now have proper "Marker"-Interfaces. +- ILeadImageBehavior and IRichTextBehavior behaviors now have proper "Marker"-Interfaces. As this was only possible by renaming the schema adapter to *Behavior* to not break with implementations inside the collective, the FTI-behavior-definition has changed: @@ -770,7 +850,7 @@ New features: Bug fixes: -- Add translation namesspace and i18n:translate to the dexterity schema +- Add translation namespace and i18n:translate to the dexterity schema definitions for the content types that have extra field defined on top of the behavior composition. Otherwise no translations can be picked up. [fredvd] diff --git a/dependabot.yml b/dependabot.yml new file mode 100644 index 000000000..bbd3ab050 --- /dev/null +++ b/dependabot.yml @@ -0,0 +1,11 @@ +# Generated from: +# https://github.com/plone/meta/tree/main/config/default +# See the inline comments on how to expand/tweak this configuration file +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every week + interval: "weekly" diff --git a/docs/README.rst b/docs/README.rst index c734665e9..84ad8b02a 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -79,7 +79,7 @@ You have several options: - + @@ -91,7 +91,7 @@ You have several options: your.package.content:folder.xml - + @@ -122,7 +122,7 @@ You have several options: -You could alternatively override the peroperty ``model_file`` of the type-definition with a empty string and use the property ``schema`` to provide your custom python-schema. +You could alternatively override the property ``model_file`` of the type-definition with a empty string and use the property ``schema`` to provide your custom python-schema. For more complex features you should always consider create custom behaviors and/or write your own content-types since that will most likely give you more flexibility and less problem when you want to upgrade to a newer version in the future. diff --git a/news/3813.bugfix b/news/3813.bugfix new file mode 100644 index 000000000..7b6bc3f35 --- /dev/null +++ b/news/3813.bugfix @@ -0,0 +1,2 @@ +Port robot tests to playwright. +[gforcada] diff --git a/news/7723aeaf.internal b/news/7723aeaf.internal deleted file mode 100644 index c08f53991..000000000 --- a/news/7723aeaf.internal +++ /dev/null @@ -1,2 +0,0 @@ -Update configuration files. -[plone devs] diff --git a/plone/app/contenttypes/behaviors/collection.py b/plone/app/contenttypes/behaviors/collection.py index 2e97c06ab..ee64cdb9b 100644 --- a/plone/app/contenttypes/behaviors/collection.py +++ b/plone/app/contenttypes/behaviors/collection.py @@ -1,5 +1,5 @@ from plone.app.contenttypes import _ -from plone.app.z3cform.widget import QueryStringFieldWidget +from plone.app.z3cform.widgets.querystring import QueryStringFieldWidget from plone.autoform import directives as form from plone.autoform.interfaces import IFormFieldProvider from plone.base.interfaces.syndication import IFeed diff --git a/plone/app/contenttypes/behaviors/richtext.py b/plone/app/contenttypes/behaviors/richtext.py index adc38d5f5..840311c66 100644 --- a/plone/app/contenttypes/behaviors/richtext.py +++ b/plone/app/contenttypes/behaviors/richtext.py @@ -2,7 +2,7 @@ from plone.app.contenttypes import _ from plone.app.dexterity.textindexer import searchable from plone.app.textfield import RichText as RichTextField -from plone.app.z3cform.widget import RichTextFieldWidget +from plone.app.z3cform.widgets.richtext import RichTextFieldWidget from plone.autoform import directives as form from plone.autoform.interfaces import IFormFieldProvider from plone.autoform.view import WidgetsView diff --git a/plone/app/contenttypes/behaviors/viewlets.py b/plone/app/contenttypes/behaviors/viewlets.py index eb38dbb25..8fe6a8def 100644 --- a/plone/app/contenttypes/behaviors/viewlets.py +++ b/plone/app/contenttypes/behaviors/viewlets.py @@ -1,4 +1,4 @@ -from plone.app.contenttypes.behaviors.leadimage import ILeadImage +from plone.app.contenttypes.behaviors.leadimage import ILeadImageBehavior from plone.app.layout.viewlets import ViewletBase @@ -6,5 +6,5 @@ class LeadImageViewlet(ViewletBase): """A simple viewlet which renders leadimage""" def update(self): - self.context = ILeadImage(self.context) - self.available = True if self.context.image else False + behavior = ILeadImageBehavior(self.context) + self.available = True if behavior.image else False diff --git a/plone/app/contenttypes/browser/configure.zcml b/plone/app/contenttypes/browser/configure.zcml index ae3464175..b3e2c7ba3 100644 --- a/plone/app/contenttypes/browser/configure.zcml +++ b/plone/app/contenttypes/browser/configure.zcml @@ -97,7 +97,7 @@ -
+ + +
-
- -
+
+ +
- + - + -
- Filename -
+
+ Filename +
- + -
+
-
- Download -
+
+ Download +
+ + + + +

+ There is no file uploaded. +

+
diff --git a/plone/app/contenttypes/browser/templates/full_view_item.pt b/plone/app/contenttypes/browser/templates/full_view_item.pt index 208207d2f..e17e57900 100644 --- a/plone/app/contenttypes/browser/templates/full_view_item.pt +++ b/plone/app/contenttypes/browser/templates/full_view_item.pt @@ -57,7 +57,6 @@ dummy python: plone_layout.mark_view(view); portal_url portal_state/portal_url; checkPermission nocall: context/portal_membership/checkPermission; - site_properties context/portal_properties/site_properties; ">
diff --git a/plone/app/contenttypes/browser/templates/listing.pt b/plone/app/contenttypes/browser/templates/listing.pt index 9e2d7553f..9ad3df226 100644 --- a/plone/app/contenttypes/browser/templates/listing.pt +++ b/plone/app/contenttypes/browser/templates/listing.pt @@ -93,7 +93,7 @@ - — diff --git a/plone/app/contenttypes/indexers.py b/plone/app/contenttypes/indexers.py index a4e495178..973dfe83b 100644 --- a/plone/app/contenttypes/indexers.py +++ b/plone/app/contenttypes/indexers.py @@ -1,6 +1,6 @@ from Acquisition import aq_base from logging import getLogger -from plone.app.contenttypes.behaviors.richtext import IRichText +from plone.app.contenttypes.behaviors.richtext import IRichTextBehavior from plone.app.contenttypes.interfaces import ICollection from plone.app.contenttypes.interfaces import IDocument from plone.app.contenttypes.interfaces import IFile @@ -40,7 +40,7 @@ def _unicode_save_string_concat(*args): def SearchableText(obj): text = "" - richtext = IRichText(obj, None) + richtext = IRichTextBehavior(obj, None) if richtext: textvalue = richtext.text if IRichTextValue.providedBy(textvalue): diff --git a/plone/app/contenttypes/profiles/default/types/Collection.xml b/plone/app/contenttypes/profiles/default/types/Collection.xml index 05c04bab9..9b0e322dc 100644 --- a/plone/app/contenttypes/profiles/default/types/Collection.xml +++ b/plone/app/contenttypes/profiles/default/types/Collection.xml @@ -36,7 +36,6 @@ > - diff --git a/plone/app/contenttypes/profiles/default/types/Document.xml b/plone/app/contenttypes/profiles/default/types/Document.xml index 76da466b6..d72793d5d 100644 --- a/plone/app/contenttypes/profiles/default/types/Document.xml +++ b/plone/app/contenttypes/profiles/default/types/Document.xml @@ -35,7 +35,6 @@ purge="false" > - diff --git a/plone/app/contenttypes/profiles/default/types/File.xml b/plone/app/contenttypes/profiles/default/types/File.xml index a9b9211b0..e99741593 100644 --- a/plone/app/contenttypes/profiles/default/types/File.xml +++ b/plone/app/contenttypes/profiles/default/types/File.xml @@ -38,7 +38,6 @@ - diff --git a/plone/app/contenttypes/profiles/default/types/Folder.xml b/plone/app/contenttypes/profiles/default/types/Folder.xml index e42362888..4d37fbcad 100644 --- a/plone/app/contenttypes/profiles/default/types/Folder.xml +++ b/plone/app/contenttypes/profiles/default/types/Folder.xml @@ -36,7 +36,6 @@ > - diff --git a/plone/app/contenttypes/profiles/default/types/Image.xml b/plone/app/contenttypes/profiles/default/types/Image.xml index 90b223c8f..cc069e93a 100644 --- a/plone/app/contenttypes/profiles/default/types/Image.xml +++ b/plone/app/contenttypes/profiles/default/types/Image.xml @@ -37,7 +37,6 @@ - diff --git a/plone/app/contenttypes/profiles/default/types/Link.xml b/plone/app/contenttypes/profiles/default/types/Link.xml index 33fa21f45..581f98dde 100644 --- a/plone/app/contenttypes/profiles/default/types/Link.xml +++ b/plone/app/contenttypes/profiles/default/types/Link.xml @@ -34,7 +34,6 @@ - diff --git a/plone/app/contenttypes/profiles/default/types/News_Item.xml b/plone/app/contenttypes/profiles/default/types/News_Item.xml index 0ddebb6f3..a706f5c94 100644 --- a/plone/app/contenttypes/profiles/default/types/News_Item.xml +++ b/plone/app/contenttypes/profiles/default/types/News_Item.xml @@ -37,7 +37,6 @@ - diff --git a/plone/app/contenttypes/setuphandlers.py b/plone/app/contenttypes/setuphandlers.py index f1b881450..d312d862f 100644 --- a/plone/app/contenttypes/setuphandlers.py +++ b/plone/app/contenttypes/setuphandlers.py @@ -9,7 +9,6 @@ from plone.base.utils import unrestricted_construct_instance from plone.dexterity.fti import IDexterityFTI from plone.dexterity.utils import createContent -from plone.i18n.normalizer.interfaces import IURLNormalizer from plone.portlets.interfaces import ILocalPortletAssignmentManager from plone.portlets.interfaces import IPortletManager from plone.registry.interfaces import IRegistry @@ -131,25 +130,6 @@ def _setup_calendar(portal, locale): portal_calendar.firstweekday = first -def _setup_visible_ids(portal, target_language, locale): - portal_properties = getToolByName(portal, "portal_properties") - site_properties = portal_properties.site_properties - - # See if we have a URL normalizer - normalizer = queryUtility(IURLNormalizer, name=target_language) - if normalizer is None: - normalizer = queryUtility(IURLNormalizer) - - # If we get a script other than Latn we enable visible_ids - if locale.id.script is not None: - if locale.id.script.lower() != "latn": - site_properties.visible_ids = True - - # If we have a normalizer it is safe to disable the visible ids - if normalizer is not None: - site_properties.visible_ids = False - - def _setup_constrains(container, allowed_types): behavior = ISelectableConstrainTypes(container) behavior.setConstrainTypesMode(constrains.ENABLED) @@ -361,7 +341,6 @@ def setup_various(context): portal = getSite() target_language, is_combined_language, locale = _get_locales_info(portal) _setup_calendar(portal, locale) - _setup_visible_ids(portal, target_language, locale) # install explicitly the plone.app.event if HAS_EVENT: diff --git a/plone/app/contenttypes/tests/robot/keywords.txt b/plone/app/contenttypes/tests/robot/keywords.txt index 2f204e59b..2706a278e 100644 --- a/plone/app/contenttypes/tests/robot/keywords.txt +++ b/plone/app/contenttypes/tests/robot/keywords.txt @@ -34,11 +34,10 @@ a event a file [Arguments] ${title} Go to ${PLONE_URL}/++add++File - Wait until page contains Add File - Input text name=form.widgets.title ${title} + Fill text name=form.widgets.title ${title} Choose File name=form.widgets.file ${PATH_TO_TEST_FILES}/file.pdf - Wait For Then Click Element css=#form-buttons-save - Wait until page contains Item created + Click css=#form-buttons-save + Get text body contains Item created a folder [Arguments] ${title} @@ -48,11 +47,10 @@ a folder a image [Arguments] ${title} Go to ${PLONE_URL}/++add++Image - Wait until page contains Add Image - Input text name=form.widgets.title ${title} + Fill text name=form.widgets.title ${title} Choose File name=form.widgets.image ${PATH_TO_TEST_FILES}/image.png - Wait For Then Click Element css=#form-buttons-save - Wait until page contains Item created error=Image could not be created. + Click css=#form-buttons-save + Get text body contains Item created a link [Arguments] ${title} @@ -63,10 +61,9 @@ a link a news item [Arguments] ${title} Go to ${PLONE_URL}/++add++News Item - Wait until page contains Add News Item - Input text name=form.widgets.IDublinCore.title ${title} - Wait For Then Click Element css=#form-buttons-save - Wait until page contains Item created + Fill text css=[name="form.widgets.IDublinCore.title"] ${title} + Click css=#form-buttons-save + Get text body contains Item created # ---------------------------------------------------------------------------- @@ -75,17 +72,15 @@ a news item the content area should contain [Arguments] ${text} - Element Should Contain id=content ${text} + Get text id=content contains ${text} the content area should not contain [Arguments] ${text} - Element Should Not Contain id=content ${text} + Get Text id=content != ${text} the collection should contain [Arguments] ${title} - Wait until page contains element xpath=//*[@id='content-core'] - Page should contain element //*[@id='content-core']//article//a[contains(text(), '${title}')] limit=1 - + Get Element //*[@id='content-core']//article//a[contains(text(), '${title}')] the collection should not contain [Arguments] ${title} @@ -101,34 +96,22 @@ fill date field Click Element xpath=//div[@data-fieldname="${fieldid}"]//div[contains(@class, 'picker__day')][contains(text(), "${day}")] I set the criteria ${type} in row ${number} to the option '${label}' - [Documentation] A couple of times we shift the focus so the input sticks, and wait a bit, - ... to make the test more stable. ${criteria_row} = Convert to String .querystring-criteria-wrapper:nth-child(${number}) - Wait until page contains element css=${criteria_row} .querystring-criteria-${type} .select2-choice - Click Element css=${criteria_row} .querystring-criteria-${type} .select2-choice - Sleep 1.5 - Set Focus To Element css=body - Wait until element is visible css=#select2-drop input - Input Text css=#select2-drop input ${label} - Sleep 1.5 - Set Focus To Element css=body - Wait until element is visible css=#select2-drop .select2-match - Click Element css=#select2-drop .select2-match - Sleep 1.5 - Set Focus To Element css=body + Click css=${criteria_row} .querystring-criteria-${type} .select2-choice + Fill Text css=#select2-drop input ${label} + Click xpath=//*[@id="select2-drop"]//*[@class="select2-match"] I set the criteria ${type} in row ${number} to the options '${label}' - ${criteria_row} = Convert to String .querystring-criteria-wrapper:nth-child(${number}) - Wait until page contains element css=${criteria_row} .querystring-criteria-${type} .select2-choices - Click Element css=${criteria_row} .querystring-criteria-${type} .select2-choices - Wait until page contains element css=.select2-input.select2-focused - Input text css=.select2-input.select2-focused ${label}\n -# Click Element xpath=//div[@class='select2-result-label']/descendant-or-self::*[contains(text(), '${label}')] + ${criteria_row} = Convert to String .querystring-criteria-wrapper:nth-child(1) + Click css=${criteria_row} .querystring-criteria-value .select2-choices + Fill text css=.select2-input.select2-focused ${label}\n + Click css=.select2-highlighted + Get text css=${criteria_row} .select2-search-choice contains ${label} + [Documentation] Chrome needs some more time + Sleep .1s I set the criteria ${type} in row ${number} to the text '${label}' ${criteria_row} = Convert to String .querystring-criteria-wrapper:nth-child(${number}) - Input text css=${criteria_row} .querystring-criteria-value input ${label}\t - [Documentation] Shift the focus so the input sticks, and wait a bit - Sleep 1.5 - Set Focus To Element css=.querystring-sortreverse - Sleep 1.5 + Fill text css=${criteria_row} .querystring-criteria-value input ${label} + Click css=.autotoc-level-1.active + Sleep 1s diff --git a/plone/app/contenttypes/tests/robot/test_collection_creator_criterion.robot b/plone/app/contenttypes/tests/robot/test_collection_creator_criterion.robot index b957e8699..885336548 100644 --- a/plone/app/contenttypes/tests/robot/test_collection_creator_criterion.robot +++ b/plone/app/contenttypes/tests/robot/test_collection_creator_criterion.robot @@ -1,18 +1,7 @@ -# ============================================================================ -# Tests for the Collection Creator Criterion -# ============================================================================ -# -# $ bin/robot-server --reload-path src/plone.app.contenttypes plone.app.contenttypes.testing.PLONE_APP_CONTENTTYPES_ROBOT_TESTING -# -# $ bin/robot src/plone.app.contenttypes/plone/app/contenttypes/tests/robot/test_collection_creator_criterion.robot -# -# ============================================================================ - -*** Settings ***************************************************************** - -Resource plone/app/robotframework/keywords.robot -Resource plone/app/robotframework/saucelabs.robot -Resource plone/app/robotframework/selenium.robot +*** Settings *** + +Resource plone/app/robotframework/browser.robot +Resource plone/app/robotframework/user.robot Resource keywords.txt Library Remote ${PLONE_URL}/RobotRemote @@ -20,7 +9,6 @@ Library Remote ${PLONE_URL}/RobotRemote Test Setup Run Keywords Plone test setup Test Teardown Run keywords Plone test teardown - *** Test cases *************************************************************** Scenario: Test Creator Criterions @@ -49,11 +37,10 @@ a test user document I set the collection's creator criterion to the current logged in user Go to ${PLONE_URL}/my-collection/edit - Wait until page contains Edit Collection + Get Text body contains Edit Collection I set the criteria index in row 1 to the option 'Creator' I set the criteria operator in row 1 to the option 'Current' - Sleep 1 - Click Button Save - Wait until page contains Changes saved + Click "Save" + Get Text body contains Changes saved diff --git a/plone/app/contenttypes/tests/robot/test_collection_location_criterion.robot b/plone/app/contenttypes/tests/robot/test_collection_location_criterion.robot index eb2dc7522..2ce5421f5 100644 --- a/plone/app/contenttypes/tests/robot/test_collection_location_criterion.robot +++ b/plone/app/contenttypes/tests/robot/test_collection_location_criterion.robot @@ -1,18 +1,6 @@ -# ============================================================================ -# Tests for the Collection Location Criterion -# ============================================================================ -# -# $ bin/robot-server --reload-path src/plone.app.contenttypes plone.app.contenttypes.testing.PLONE_APP_CONTENTTYPES_ROBOT_TESTING -# -# $ bin/robot src/plone.app.contenttypes/plone/app/contenttypes/tests/robot/test_collection_location_criterion.robot -# -# ============================================================================ - -*** Settings ***************************************************************** - -Resource plone/app/robotframework/keywords.robot -Resource plone/app/robotframework/saucelabs.robot -Resource plone/app/robotframework/selenium.robot +*** Settings *** + +Resource plone/app/robotframework/browser.robot Resource keywords.txt Variables variables.py @@ -21,11 +9,9 @@ Test Setup Run Keywords Plone test setup Test Teardown Run keywords Plone test teardown -*** Test cases *************************************************************** +*** Test cases *** Scenario: Test Relative Location Criterion - [Documentation] This sometimes fails with: - ... Element locator 'css=#select2-drop input' did not match any elements after 30 seconds Given I am logged in as site owner And a document Document outside Folder And a folder 'my-folder' with a document 'Document within Folder' @@ -36,9 +22,6 @@ Scenario: Test Relative Location Criterion Scenario: Test Absolute Location Criterion - [Documentation] This sometimes fails with: - ... Element locator 'css=#select2-drop input' did not match any elements after 30 seconds - ... Or with: Element 'id=content' should not contain text 'Document outside Folder' but it did. Given I am logged in as site owner And a document Document outside Folder And a folder 'my-folder' with a document 'Document within Folder' @@ -52,14 +35,14 @@ Scenario: Test Absolute Location Criterion a folder '${folder-id}' with a document '${document-title}' Go to ${PLONE_URL}/++add++Folder - Wait until page contains element name=form.widgets.IDublinCore.title - Input text name=form.widgets.IDublinCore.title ${folder-id} - Click Button Save + # Wait until page contains element name=form.widgets.IDublinCore.title + Fill text xpath=//*[@name="form.widgets.IDublinCore.title"] ${folder-id} + Click "Save" Go to ${PLONE_URL}/${folder-id}/++add++Document - Wait until page contains element name=form.widgets.IDublinCore.title - Input text name=form.widgets.IDublinCore.title ${document-title} - Click Button Save - Wait until page contains Item created + # Wait until page contains element name=form.widgets.IDublinCore.title + Fill text xpath=//*[@name="form.widgets.IDublinCore.title"] ${document-title} + Click "Save" + # Wait until page contains Item created I set the collection's location criterion to Advanced Mode I set the criteria operator in row 1 to the option 'Advanced Mode' @@ -67,7 +50,7 @@ I set the collection's location criterion to Advanced Mode I set the collection's relative location criterion to [Arguments] ${criterion} Go to ${PLONE_URL}/my-collection/edit - Wait until page contains Edit Collection + # Wait until page contains Edit Collection I set the criteria index in row 1 to the option 'Location' @@ -76,13 +59,13 @@ I set the collection's relative location criterion to I set the criteria operator in row 1 to the option 'Relative path' I set the criteria value in row 1 to the text '${criterion}' - Click Button Save - Wait until page contains Changes saved + Click "Save" + # Wait until page contains Changes saved I set the collection's absolute location criterion to [Arguments] ${criterion} Go to ${PLONE_URL}/my-collection/edit - Wait until page contains Edit Collection + # Wait until page contains Edit Collection I set the criteria index in row 1 to the option 'Location' @@ -91,5 +74,5 @@ I set the collection's absolute location criterion to I set the criteria operator in row 1 to the option 'Absolute path' I set the criteria value in row 1 to the text '${criterion}' - Click Button Save - Wait until page contains Changes saved + Click "Save" + # Wait until page contains Changes saved diff --git a/plone/app/contenttypes/tests/robot/test_collection_review_state_criterion.robot b/plone/app/contenttypes/tests/robot/test_collection_review_state_criterion.robot index 719d7f975..bd4b7fe20 100644 --- a/plone/app/contenttypes/tests/robot/test_collection_review_state_criterion.robot +++ b/plone/app/contenttypes/tests/robot/test_collection_review_state_criterion.robot @@ -1,25 +1,15 @@ -# ============================================================================ -# Tests for the Collection Type Criterion -# ============================================================================ -# -# $ bin/robot-server --reload-path src/plone.app.contenttypes plone.app.contenttypes.testing.PLONE_APP_CONTENTTYPES_ROBOT_TESTING -# -# $ bin/robot src/plone.app.contenttypes/plone/app/contenttypes/tests/robot/test_collection_review_state_criterion.robot -# -# ============================================================================ - -*** Settings ***************************************************************** - -Resource plone/app/robotframework/keywords.robot -Resource plone/app/robotframework/saucelabs.robot -Resource plone/app/robotframework/selenium.robot +*** Settings *** + +Resource plone/app/robotframework/browser.robot Resource keywords.txt +Variables variables.py + Test Setup Run Keywords Plone test setup Test Teardown Run keywords Plone test teardown -*** Test cases *************************************************************** +*** Test cases *** Scenario: Test Review state Criterion Given I am logged in as site owner @@ -45,12 +35,9 @@ a private document I set the collection's review state criterion to [Arguments] ${criterion} Go to ${PLONE_URL}/my-collection/edit - Wait until page contains Edit Collection I set the criteria index in row 1 to the option 'Review state' I set the criteria operator in row 1 to the option 'Any' I set the criteria value in row 1 to the options '${criterion}' - Sleep 1 - Click Button Save - Wait until page contains Changes saved + Click "Save" diff --git a/plone/app/contenttypes/tests/robot/test_collection_short_name_criterion.robot b/plone/app/contenttypes/tests/robot/test_collection_short_name_criterion.robot index cf09f2775..97246a9fe 100644 --- a/plone/app/contenttypes/tests/robot/test_collection_short_name_criterion.robot +++ b/plone/app/contenttypes/tests/robot/test_collection_short_name_criterion.robot @@ -1,25 +1,15 @@ -# ============================================================================ -# Tests for the Collection Short Name Criterion -# ============================================================================ -# -# $ bin/robot-server --reload-path src/plone.app.contenttypes plone.app.contenttypes.testing.PLONE_APP_CONTENTTYPES_ROBOT_TESTING -# -# $ bin/robot src/plone.app.contenttypes/plone/app/contenttypes/tests/robot/test_collection_short_name_criterion.robot -# -# ============================================================================ - -*** Settings ***************************************************************** - -Resource plone/app/robotframework/keywords.robot -Resource plone/app/robotframework/saucelabs.robot -Resource plone/app/robotframework/selenium.robot +*** Settings *** + +Resource plone/app/robotframework/browser.robot Resource keywords.txt +Variables variables.py + Test Setup Run Keywords Plone test setup Test Teardown Run keywords Plone test teardown -*** Test cases *************************************************************** +*** Test cases *** Test Short name (id) Criterion Given I am logged in as site owner @@ -36,12 +26,19 @@ Test Short name (id) Criterion I set the collection short name (id) criterion to [Arguments] ${criterion} Go to ${PLONE_URL}/my-collection/edit - Wait until page contains Edit Collection I set the criteria index in row 1 to the option 'Short name' - I set the criteria operator in row 1 to the option 'Is' + #I set the criteria operator in row 1 to the option 'Is' + + ${criteria_row} = Convert to String .querystring-criteria-wrapper:nth-child(1) + Click css=${criteria_row} .querystring-criteria-operator .select2-choice + Fill Text css=#select2-drop input Is + Click css=.select2-highlighted + + I set the criteria value in row 1 to the text '${criterion}' + [Documentation] Chrome needs some more time + Sleep .1s - Sleep 1 - Click Button Save - Wait until page contains Changes saved + Click "Save" + Get text body contains Changes saved diff --git a/plone/app/contenttypes/tests/robot/test_collection_type_criterion.robot b/plone/app/contenttypes/tests/robot/test_collection_type_criterion.robot index d7a2bbf61..774a798d9 100644 --- a/plone/app/contenttypes/tests/robot/test_collection_type_criterion.robot +++ b/plone/app/contenttypes/tests/robot/test_collection_type_criterion.robot @@ -1,25 +1,14 @@ -# ============================================================================ -# Tests for the Collection Type Criterion -# ============================================================================ -# -# $ bin/robot-server --reload-path src/plone.app.contenttypes plone.app.contenttypes.testing.PLONE_APP_CONTENTTYPES_ROBOT_TESTING -# -# $ bin/robot src/plone.app.contenttypes/plone/app/contenttypes/tests/robot/test_collection_type_criterion.robot -# -# ============================================================================ - -*** Settings ***************************************************************** - -Resource plone/app/robotframework/keywords.robot -Resource plone/app/robotframework/saucelabs.robot -Resource plone/app/robotframework/selenium.robot +*** Settings *** + +Resource plone/app/robotframework/browser.robot Resource keywords.txt +Variables variables.py + Test Setup Run Keywords Plone test setup Test Teardown Run keywords Plone test teardown - -*** Test cases *************************************************************** +*** Test cases *** Test Type Criterion Given I am logged in as site owner @@ -36,12 +25,10 @@ Test Type Criterion I set the collection's type criterion to [Arguments] ${criterion} Go to ${PLONE_URL}/my-collection/edit - Wait until page contains Edit Collection I set the criteria index in row 1 to the option 'Type' I set the criteria operator in row 1 to the option 'Any' I set the criteria value in row 1 to the options '${criterion}' - Sleep 1 - Click Button Save - Wait until page contains Changes saved + Click "Save" + Get text body contains Changes saved diff --git a/plone/app/contenttypes/tests/robot/test_folderlisting.robot b/plone/app/contenttypes/tests/robot/test_folderlisting.robot index a64f535d6..2cfb53fa7 100644 --- a/plone/app/contenttypes/tests/robot/test_folderlisting.robot +++ b/plone/app/contenttypes/tests/robot/test_folderlisting.robot @@ -1,18 +1,13 @@ *** Settings *** -Resource plone/app/robotframework/keywords.robot -Resource plone/app/robotframework/saucelabs.robot -Resource plone/app/robotframework/selenium.robot +Resource plone/app/robotframework/browser.robot Resource keywords.txt Variables variables.py - Test Setup Run Keywords Setup Testcontent Plone test setup Test Teardown Run keywords Plone test teardown -*** Variables *** - *** Test cases *** Scenario: Test folder listing view @@ -101,7 +96,7 @@ Listing should list contained content in detail the content area should contain this is a test document the content area should contain Test News Item the content area should contain this is a test news item - Page Should Contain Element //img[@title="Test News Item"] 2 + Get Element Count //img[@title="Test News Item"] == 2 the content area should contain Test Event the content area should contain this is a test event the content area should contain Test Collection @@ -111,29 +106,29 @@ Listing should list contained content in detail the content area should contain Test File the content area should contain file.pdf the content area should contain Test Image - Page Should Contain Element //img[@title="Test Image"] 3 + Get Element Count //img[@title="Test Image"] == 2 the content area should contain Test Album the content area should contain Test Album Image 1 - Page Should Contain Element //img[@title="Test Album Image 1"] 2 + Get Element Count //img[@title="Test Album Image 1"] == 2 the content area should contain Test Album Image 2 - Page Should Contain Element //img[@title="Test Album Image 2"] 2 + Get Element Count //img[@title="Test Album Image 2"] == 2 the content area should contain Test Album Image 3 - Page Should Contain Element //img[@title="Test Album Image 3"] 2 + Get Element Count //img[@title="Test Album Image 3"] == 2 the content area should contain Test Sub Album the content area should contain Test Sub Album Image 1 - Page Should Contain Element //img[@title="Test Sub Album Image 1"] 1 + Get Element Count //img[@title="Test Sub Album Image 1"] == 1 the content area should contain Test Sub Album Image 2 - Page Should Contain Element //img[@title="Test Sub Album Image 2"] 1 + Get Element Count //img[@title="Test Sub Album Image 2"] == 1 the content area should contain Test Sub Album Image 3 - Page Should Contain Element //img[@title="Test Sub Album Image 3"] 1 + Get Element Count //img[@title="Test Sub Album Image 3"] == 1 Album should list contained images and albums the content area should contain Test Album Image 1 - Page Should Contain Element //img[@title="Test Album Image 1"] 2 + Get Element Count //img[@title="Test Album Image 1"] == 1 the content area should contain Test Album Image 2 - Page Should Contain Element //img[@title="Test Album Image 2"] 2 + Get Element Count //img[@title="Test Album Image 2"] == 1 the content area should contain Test Album Image 3 - Page Should Contain Element //img[@title="Test Album Image 3"] 2 + Get Element Count //img[@title="Test Album Image 3"] == 1 the content area should contain Test Sub Album @@ -159,7 +154,7 @@ Listing should list all content in detail the content area should contain this is a test document the content area should contain Test News Item the content area should contain this is a test news item - Page Should Contain Element //img[@title="Test News Item"] 2 + Get Element Count //img[@title="Test News Item"] == 2 the content area should contain Test Event the content area should contain this is a test event the content area should contain Test Collection @@ -169,39 +164,39 @@ Listing should list all content in detail the content area should contain Test File the content area should contain file.pdf the content area should contain Test Image - Page Should Contain Element //img[@title="Test Image"] 3 + Get Element Count //img[@title="Test Image"] == 2 the content area should contain Test Album the content area should contain Test Album Image 1 - Page Should Contain Element //img[@title="Test Album Image 1"] 2 + Get Element Count //img[@title="Test Album Image 1"] == 2 the content area should contain Test Album Image 2 - Page Should Contain Element //img[@title="Test Album Image 2"] 2 + Get Element Count //img[@title="Test Album Image 2"] == 2 the content area should contain Test Album Image 3 - Page Should Contain Element //img[@title="Test Album Image 3"] 2 + Get Element Count //img[@title="Test Album Image 3"] == 2 the content area should contain Test Sub Album the content area should contain Test Sub Album Image 1 - Page Should Contain Element //img[@title="Test Sub Album Image 1"] 2 + Get Element Count //img[@title="Test Sub Album Image 1"] == 2 the content area should contain Test Sub Album Image 2 - Page Should Contain Element //img[@title="Test Sub Album Image 2"] 2 + Get Element Count //img[@title="Test Sub Album Image 2"] == 2 the content area should contain Test Sub Album Image 3 - Page Should Contain Element //img[@title="Test Sub Album Image 3"] 2 + Get Element Count //img[@title="Test Sub Album Image 3"] == 2 Album should list all images and albums the content area should contain Test Image - Page Should Contain Element //div[contains(@class, "card-image")]//img[@title="Test Image"] 1 + Get Element Count //div[contains(@class, "card-image")]//img[@title="Test Image"] == 1 the content area should contain Test News Item - Page Should Contain Element //div[contains(@class, "card-image")]//img[@title="Test News Item"] 1 + Get Element Count //div[contains(@class, "card-image")]//img[@title="Test News Item"] == 1 the content area should contain Test Album Image 1 - Page Should Contain Element //div[contains(@class, "card-image")]//img[@title="Test Album Image 1"] 1 + Get Element Count //div[contains(@class, "card-image")]//img[@title="Test Album Image 1"] == 1 the content area should contain Test Album Image 2 - Page Should Contain Element //div[contains(@class, "card-image")]//img[@title="Test Album Image 2"] 1 + Get Element Count //div[contains(@class, "card-image")]//img[@title="Test Album Image 2"] == 1 the content area should contain Test Album Image 3 - Page Should Contain Element //div[contains(@class, "card-image")]//img[@title="Test Album Image 3"] 1 + Get Element Count //div[contains(@class, "card-image")]//img[@title="Test Album Image 3"] == 1 the content area should contain Test Sub Album Image 1 - Page Should Contain Element //div[contains(@class, "card-image")]//img[@title="Test Sub Album Image 1"] 1 + Get Element Count //div[contains(@class, "card-image")]//img[@title="Test Sub Album Image 1"] == 1 the content area should contain Test Sub Album Image 2 - Page Should Contain Element //div[contains(@class, "card-image")]//img[@title="Test Sub Album Image 2"] 1 + Get Element Count //div[contains(@class, "card-image")]//img[@title="Test Sub Album Image 2"] == 1 the content area should contain Test Sub Album Image 3 - Page Should Contain Element //div[contains(@class, "card-image")]//img[@title="Test Sub Album Image 3"] 1 + Get Element Count //div[contains(@class, "card-image")]//img[@title="Test Sub Album Image 3"] == 1 the content area should contain Test Album the content area should contain Test Sub Album @@ -230,8 +225,6 @@ I go to I disable dropdown navigation Go to ${PLONE_URL}/@@navigation-controlpanel - Input Text name=form.widgets.navigation_depth 1 - Set Focus To Element css=#form-buttons-save - Wait Until Element Is Visible css=#form-buttons-save - Click Button Save - Wait until page contains Changes saved + Fill Text css=[name="form.widgets.navigation_depth"] 1 + Click "Save" + Get Text body contains Changes saved diff --git a/plone/app/contenttypes/tests/test_event.py b/plone/app/contenttypes/tests/test_event.py index 2ce969116..528059a99 100644 --- a/plone/app/contenttypes/tests/test_event.py +++ b/plone/app/contenttypes/tests/test_event.py @@ -91,24 +91,24 @@ def setUp(self): def test_add_event(self): self.browser.open(self.portal_url) self.browser.getLink("Event").click() - self.browser.getControl( - name="form.widgets.IDublinCore.title" - ).value = "My event" - self.browser.getControl( - name="form.widgets.IDublinCore.description" - ).value = "This is my event." - self.browser.getControl( - name="form.widgets.IRichTextBehavior.text" - ).value = "Lorem Ipsum" - self.browser.getControl( - name="form.widgets.IEventBasic.start" - ).value = "2013-01-01" - self.browser.getControl( - name="form.widgets.IEventBasic.end" - ).value = "2013-01-12" - self.browser.getControl( - name="form.widgets.IShortName.id" - ).value = "my-special-event" + self.browser.getControl(name="form.widgets.IDublinCore.title").value = ( + "My event" + ) + self.browser.getControl(name="form.widgets.IDublinCore.description").value = ( + "This is my event." + ) + self.browser.getControl(name="form.widgets.IRichTextBehavior.text").value = ( + "Lorem Ipsum" + ) + self.browser.getControl(name="form.widgets.IEventBasic.start").value = ( + "2013-01-01" + ) + self.browser.getControl(name="form.widgets.IEventBasic.end").value = ( + "2013-01-12" + ) + self.browser.getControl(name="form.widgets.IShortName.id").value = ( + "my-special-event" + ) self.browser.getControl("Save").click() self.assertTrue(self.browser.url.endswith("my-special-event/view")) diff --git a/plone/app/contenttypes/tests/test_folder.py b/plone/app/contenttypes/tests/test_folder.py index 440eb6c2c..47c048f55 100644 --- a/plone/app/contenttypes/tests/test_folder.py +++ b/plone/app/contenttypes/tests/test_folder.py @@ -1,3 +1,5 @@ +from datetime import datetime +from datetime import timedelta from plone.app.contenttypes.browser.folder import FolderView from plone.app.contenttypes.interfaces import IFolder from plone.app.contenttypes.testing import ( # noqa @@ -232,3 +234,26 @@ def test_list_item_wout_title(self): # And also in tabular view self.browser.open(self.folder_url + "/tabular_view") self.assertIn("doc_wout_title", self.browser.contents) + + def test_event_wout_location(self): + # deactivate "plone.eventlocation" from Event behaviors + event_fti = self.portal.portal_types.get("Event") + if not event_fti: + return + event_behaviors = list(event_fti.behaviors) + event_behaviors.remove("plone.eventlocation") + event_fti.behaviors = tuple(event_behaviors) + + self.folder.invokeFactory( + "Event", + id="event_wout_location", + title="Event without location", + start=datetime.now() + timedelta(days=1), + ) + + import transaction + + transaction.commit() + + self.browser.open(self.folder_url + "/listing_view") + self.assertIn("Event without location", self.browser.contents) diff --git a/plone/app/contenttypes/tests/test_link.py b/plone/app/contenttypes/tests/test_link.py index dd306c274..dabdd9a81 100644 --- a/plone/app/contenttypes/tests/test_link.py +++ b/plone/app/contenttypes/tests/test_link.py @@ -1,4 +1,5 @@ from datetime import datetime +from plone.app.contenttypes.browser.link_redirect_view import normalize_uid_from_path from plone.app.contenttypes.interfaces import ILink from plone.app.contenttypes.testing import ( # noqa PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING, @@ -230,6 +231,117 @@ def test_ftp_type(self): self.assertTrue(view()) self._assert_redirect(self.link.remoteUrl) + def test_normalize_uid_from_path(self): + url = None + uid, fragment = normalize_uid_from_path(url) + self.assertIsNone(uid) + self.assertIsNone(fragment) + + url = "http://nohost" + uid, fragment = normalize_uid_from_path(url) + self.assertIsNone(uid) + self.assertIsNone(fragment) + + url = "http://nohost/test1" + uid, fragment = normalize_uid_from_path(url) + self.assertIsNone(uid) + self.assertIsNone(fragment) + + url = "http://nohost/test1/resolveuid" + uid, fragment = normalize_uid_from_path(url) + self.assertIsNone(uid) + self.assertIsNone(fragment) + + url = "http://nohost/test1/resolveuid/" + uid, fragment = normalize_uid_from_path(url) + self.assertIsNone(uid) + self.assertIsNone(fragment) + + url = "http://nohost/test1/resolveuid123/" + uid, fragment = normalize_uid_from_path(url) + self.assertIsNone(uid) + self.assertIsNone(fragment) + + url = "http://nohost/test1/resolveuid/123" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "http://nohost/test1/resolveuid/123#my-id" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertEqual(fragment, "#my-id") + + url = "http://nohost/test1/resolveuid/123/" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "http://nohost/test1/resolveuid/123#my-id/" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertEqual(fragment, "#my-id") + + url = "http://nohost/test1/resolveuid/123/test" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "resolveuid/123" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "resolveuid/123#my-id" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertEqual(fragment, "#my-id") + + url = "resolveuid/123/" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "resolveuid/123#my-id/" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertEqual(fragment, "#my-id") + + url = "resolveuid/123/abc" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "/resolveuid/123" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "/resolveuid/123#my-id" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertEqual(fragment, "#my-id") + + url = "/resolveuid/123/" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "/resolveuid/123#my-id/" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertEqual(fragment, "#my-id") + + url = "/resolveuid/123/abc" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertIsNone(fragment) + + url = "/resolveUid/123#my-id" + uid, fragment = normalize_uid_from_path(url) + self.assertEqual(uid, "123") + self.assertEqual(fragment, "#my-id") + def _publish(self, obj): portal_workflow = getToolByName(self.portal, "portal_workflow") portal_workflow.doActionFor(obj, "publish") @@ -267,15 +379,15 @@ def test_add_link(self): self.browser.open(self.portal_url) self.browser.getLink("Link").click() self.browser.getControl(name="form.widgets.IDublinCore.title").value = "My link" - self.browser.getControl( - name="form.widgets.IDublinCore.description" - ).value = "This is my link." - self.browser.getControl( - name="form.widgets.IShortName.id" - ).value = "my-special-link" - self.browser.getControl( - name="form.widgets.remoteUrl.external" - ).value = "https://plone.org" + self.browser.getControl(name="form.widgets.IDublinCore.description").value = ( + "This is my link." + ) + self.browser.getControl(name="form.widgets.IShortName.id").value = ( + "my-special-link" + ) + self.browser.getControl(name="form.widgets.remoteUrl.external").value = ( + "https://plone.org" + ) self.browser.getControl("Save").click() self.assertTrue(self.browser.url.endswith("my-special-link/view")) @@ -374,5 +486,22 @@ def test_resolve_uid_to_absolute_target(self): ) doc1 = self.portal["doc1"] uid = IUUID(doc1) + + portal_state = getMultiAdapter( + (self.link, self.request), name="plone_portal_state" + ) + portal_url = portal_state.portal_url() + + # check an internal link self.link.remoteUrl = f"${{portal_url}}/resolveuid/{uid}" - self.assertEqual(view.absolute_target_url(), "http://nohost/doc1") + self.assertEqual(view.absolute_target_url(), f"{portal_url}/doc1") + + # check an internal link with fragment + self.link.remoteUrl = f"${{portal_url}}/resolveuid/{uid}#autotoc-item-autotoc-1" + self.assertEqual( + view.absolute_target_url(), f"{portal_url}/doc1#autotoc-item-autotoc-1" + ) + + # check not resolvable uid + self.link.remoteUrl = "/resolveuid/abc123" + self.assertEqual(view.absolute_target_url(), "/resolveuid/abc123") diff --git a/plone/app/contenttypes/tests/test_news_item.py b/plone/app/contenttypes/tests/test_news_item.py index 9bab672be..09ff40def 100644 --- a/plone/app/contenttypes/tests/test_news_item.py +++ b/plone/app/contenttypes/tests/test_news_item.py @@ -112,16 +112,16 @@ def setUp(self): def test_add_news_item(self): self.browser.open(self.portal_url) self.browser.getLink("News Item").click() - self.browser.getControl( - name="form.widgets.IDublinCore.title" - ).value = "My news item" - self.browser.getControl( - name="form.widgets.IDublinCore.description" - ).value = "This is my news item." + self.browser.getControl(name="form.widgets.IDublinCore.title").value = ( + "My news item" + ) + self.browser.getControl(name="form.widgets.IDublinCore.description").value = ( + "This is my news item." + ) self.browser.getControl(name="form.widgets.IShortName.id").value = "" - self.browser.getControl( - name="form.widgets.IRichTextBehavior.text" - ).value = "Lorem Ipsum" + self.browser.getControl(name="form.widgets.IRichTextBehavior.text").value = ( + "Lorem Ipsum" + ) self.browser.getControl("Save").click() self.assertTrue(self.browser.url.endswith("my-news-item/view")) @@ -132,12 +132,12 @@ def test_add_news_item(self): def test_add_news_item_with_shortname(self): self.browser.open(self.portal_url) self.browser.getLink("News Item").click() - self.browser.getControl( - name="form.widgets.IDublinCore.title" - ).value = "My news item" - self.browser.getControl( - name="form.widgets.IShortName.id" - ).value = "my-special-news" + self.browser.getControl(name="form.widgets.IDublinCore.title").value = ( + "My news item" + ) + self.browser.getControl(name="form.widgets.IShortName.id").value = ( + "my-special-news" + ) self.browser.getControl("Save").click() self.assertTrue(self.browser.url.endswith("my-special-news/view")) diff --git a/pyproject.toml b/pyproject.toml index e4468843b..35e47cbbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,9 @@ # Generated from: -# https://github.com/plone/meta/tree/master/config/default +# https://github.com/plone/meta/tree/main/config/default # See the inline comments on how to expand/tweak this configuration file +[build-system] +requires = ["setuptools>=68.2"] + [tool.towncrier] directory = "news/" filename = "CHANGES.rst" @@ -37,14 +40,38 @@ directory = "tests" name = "Tests" showcontent = true +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# towncrier_extra_lines = """ +# extra_configuration +# """ +## + [tool.isort] profile = "plone" +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# isort_extra_lines = """ +# extra_configuration +# """ +## + [tool.black] target-version = ["py38"] +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# black_extra_lines = """ +# extra_configuration +# """ +## + [tool.codespell] -ignore-words-list = "discreet,oder,ist,crate" +ignore-words-list = "discreet,assertin,oder,ist,crate" skip = "*.po," ## # Add extra configuration options in .meta.toml: @@ -102,19 +129,20 @@ ignore-packages = ['ZServer', 'plone.app.event', 'Products.CMFPlone',] # "gitpython = ['git']", # "pygithub = ['github']", # ] -# """ ## [tool.check-manifest] ignore = [ ".editorconfig", + ".flake8", ".meta.toml", ".pre-commit-config.yaml", - "tox.ini", - ".flake8", + "dependabot.yml", "mx.ini", + "tox.ini", ] + ## # Add extra configuration options in .meta.toml: # [pyproject] @@ -122,6 +150,11 @@ ignore = [ # "*.map.js", # "*.pyc", # """ +# check_manifest_extra_lines = """ +# ignore-bad-ideas = [ +# "some/test/file/PKG-INFO", +# ] +# """ ## diff --git a/setup.py b/setup.py index 03e62fdf0..2b47eed8e 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ import os -version = "3.0.3" +version = "4.0.1.dev0" def read(*rnames): @@ -24,16 +24,15 @@ def read(*rnames): "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Plone", - "Framework :: Plone :: 6.0", + "Framework :: Plone :: 6.1", "Framework :: Plone :: Core", "Framework :: Zope :: 5", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ], keywords="plone content types dexterity", author="Plone Foundation", @@ -44,7 +43,7 @@ def read(*rnames): namespace_packages=["plone", "plone.app"], include_package_data=True, zip_safe=False, - python_requires=">=3.8", + python_requires=">=3.10", install_requires=[ "setuptools", "plone.app.contentmenu", @@ -59,7 +58,6 @@ def read(*rnames): "plone.app.lockingbehavior", "plone.behavior >= 1.3.0", "plone.app.z3cform>=1.1.0", - "zope.deprecation", "plone.base", "Products.BTreeFolder2", "Products.GenericSetup", @@ -72,7 +70,6 @@ def read(*rnames): "plone.autoform", "plone.event", "plone.folder", - "plone.i18n", "plone.indexer", "plone.memoize", "plone.portlets", @@ -81,7 +78,7 @@ def read(*rnames): "plone.supermodel", "plone.z3cform", "z3c.form", - "zope.contentprovider", + "Zope", ], extras_require={ "test": [ @@ -91,7 +88,6 @@ def read(*rnames): "plone.testing", "plone.browserlayer", "plone.uuid", - "zope.viewlet", "robotsuite", ], }, diff --git a/tox.ini b/tox.ini index 030fd7492..c0b0ad2bf 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ # Generated from: -# https://github.com/plone/meta/tree/master/config/default +# https://github.com/plone/meta/tree/main/config/default # See the inline comments on how to expand/tweak this configuration file [tox] # We need 4.4.0 for constrain_package_deps. @@ -32,6 +32,21 @@ commands = echo "Unrecognized environment name {envname}" false +## +# Add extra configuration options in .meta.toml: +# [tox] +# testenv_options = """ +# basepython = /usr/bin/python3.8 +# """ +## + +[testenv:init] +description = Prepare environment +skip_install = true +commands = + echo "Initial setup complete" + + [testenv:format] description = automatically reformat code skip_install = true @@ -56,9 +71,9 @@ description = check if the package defines all its dependencies skip_install = true deps = build - z3c.dependencychecker==2.11 + z3c.dependencychecker==2.14.3 commands = - python -m build --sdist --no-isolation + python -m build --sdist dependencychecker [testenv:dependencies-graph] @@ -77,11 +92,35 @@ description = run the distribution tests use_develop = true skip_install = false constrain_package_deps = true -set_env = ROBOT_BROWSER=headlesschrome +set_env = + ROBOT_BROWSER=headlesschrome + +## +# Specify extra test environment variables in .meta.toml: +# [tox] +# test_environment_variables = """ +# PIP_EXTRA_INDEX_URL=https://my-pypi.my-server.com/ +# """ +# +# Set constrain_package_deps .meta.toml: +# [tox] +# constrain_package_deps = "false" +## deps = zope.testrunner - -c https://dist.plone.org/release/6.0-dev/constraints.txt + -c https://dist.plone.org/release/6.1-dev/constraints.txt + +## +# Specify additional deps in .meta.toml: +# [tox] +# test_deps_additional = "-esources/plonegovbr.portal_base[test]" +# +# Specify a custom constraints file in .meta.toml: +# [tox] +# constraints_file = "https://my-server.com/constraints.txt" +## commands = + rfbrowser init zope-testrunner --all --test-path={toxinidir} -s plone.app.contenttypes {posargs} extras = test @@ -100,14 +139,27 @@ description = get a test coverage report use_develop = true skip_install = false constrain_package_deps = true -set_env = ROBOT_BROWSER=headlesschrome +set_env = + ROBOT_BROWSER=headlesschrome + +## +# Specify extra test environment variables in .meta.toml: +# [tox] +# test_environment_variables = """ +# PIP_EXTRA_INDEX_URL=https://my-pypi.my-server.com/ +# """ +## deps = coverage zope.testrunner - -c https://dist.plone.org/release/6.0-dev/constraints.txt + -c https://dist.plone.org/release/6.1-dev/constraints.txt + commands = + rfbrowser init coverage run --branch --source plone.app.contenttypes {envbindir}/zope-testrunner --quiet --all --test-path={toxinidir} -s plone.app.contenttypes {posargs} coverage report -m --format markdown + coverage xml + coverage html extras = test @@ -119,25 +171,39 @@ deps = twine build towncrier - -c https://dist.plone.org/release/6.0-dev/constraints.txt + -c https://dist.plone.org/release/6.1-dev/constraints.txt + commands = # fake version to not have to install the package # we build the change log as news entries might break # the README that is displayed on PyPI towncrier build --version=100.0.0 --yes - python -m build --sdist --no-isolation + python -m build --sdist twine check dist/* [testenv:circular] description = ensure there are no cyclic dependencies use_develop = true skip_install = false +# Here we must always constrain the package deps to what is already installed, +# otherwise we simply get the latest from PyPI, which may not work. +constrain_package_deps = true +set_env = + +## +# Specify extra test environment variables in .meta.toml: +# [tox] +# test_environment_variables = """ +# PIP_EXTRA_INDEX_URL=https://my-pypi.my-server.com/ +# """ +## allowlist_externals = sh deps = pipdeptree pipforester - -c https://dist.plone.org/release/6.0-dev/constraints.txt + -c https://dist.plone.org/release/6.1-dev/constraints.txt + commands = # Generate the full dependency tree sh -c 'pipdeptree -j > forest.json' @@ -151,6 +217,6 @@ commands = # Add extra configuration options in .meta.toml: # [tox] # extra_lines = """ -# my_other_environment +# _your own configuration lines_ # """ ##