Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ on:
python-version:
required: false
type: string
default: "3.12"
default: "3.13"
plone-version:
required: false
type: string
default: "6.1.2"
default: "6.2.0"
outputs:
backend:
description: "Flag reporting if we should run the backend jobs"
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.13", "3.12", "3.11", "3.10"]
plone-version: ["6.1-latest", "6.0-latest"]
python-version: ["3.14", "3.13", "3.12", "3.11", "3.10"]
plone-version: ["6.2-latest", "6.1-latest", "6.0-latest"]
exclude:
# Python 3.14 requires Plone 6.2 or newer
- python-version: "3.14"
plone-version: "6.1-latest"
- python-version: "3.14"
plone-version: "6.0-latest"
with:
python-version: ${{ matrix.python-version }}
plone-version: ${{ matrix.plone-version }}
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ BACKEND_FOLDER=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
ifdef PLONE_VERSION
PLONE_VERSION := $(PLONE_VERSION)
else
PLONE_VERSION := 6.1.2
PLONE_VERSION := 6.2.0
endif

PLONE_SITE_ID?=Plone
Expand Down
1 change: 1 addition & 0 deletions news/20.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added support for Plone 6.2 and Python 3.14. @ericof
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ classifiers = [
"Framework :: Plone",
"Framework :: Plone :: 6.0",
"Framework :: Plone :: 6.1",
"Framework :: Plone :: 6.2",
"Framework :: Plone :: Addon",
"Framework :: Zope",
"Framework :: Zope :: 5",
Expand All @@ -28,6 +29,7 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
dependencies = [
"Products.CMFPlone>=6.0.0",
Expand All @@ -44,7 +46,7 @@ test = [
"plone.app.testing",
"plone.restapi[test]",
"pytest-cov",
"pytest-plone>=1.0.0a1",
"pytest-plone>=1.0.0",
"zest-releaser[recommended]>=9.5.0",
"zestreleaser-towncrier>=1.3.0",
]
Expand Down
7 changes: 0 additions & 7 deletions tests/behaviors/conftest.py

This file was deleted.

17 changes: 2 additions & 15 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,8 @@ def roles_vocab():


@pytest.fixture()
def additional_profiles() -> list[str]:
"""List of additional profiles to apply on top of the default testing profile."""
return [
"collective.person:demo",
]


@pytest.fixture()
def portal(integration, roles_vocab, additional_profiles):
def portal(integration, roles_vocab):
portal = integration["portal"]
setup_tool = api.portal.get_tool("portal_setup")
for profile in additional_profiles:
setup_tool.runAllImportStepsFromProfile(profile)
with api.env.adopt_user(SITE_OWNER_NAME):
# Set registry for roles
api.portal.set_registry_record("person.roles", roles_vocab)
Expand Down Expand Up @@ -85,9 +74,7 @@ def persons_payload() -> list:
def persons(portal, persons_payload) -> dict:
"""Create Person content items."""
response = {}
with api.env.adopt_roles([
"Manager",
]):
with api.env.adopt_roles(["Manager"]):
for data in persons_payload:
content = api.content.create(container=portal, **data)
response[content.UID()] = content.title
Expand Down
14 changes: 14 additions & 0 deletions tests/content/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from plone.dexterity.fti import DexterityFTI
from plone.dexterity.interfaces import IDexterityFTI
from zope.component import queryUtility

import pytest


@pytest.fixture(scope="class")
def get_fti(portal_class):
def get_fti(name: str) -> DexterityFTI:
"""Get the Factory Type Information for a type by name."""
return queryUtility(IDexterityFTI, name=name)

return get_fti
59 changes: 42 additions & 17 deletions tests/content/test_person.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,61 @@
CONTENT_TYPE = "Person"


class TestPerson:
class TestPersonFTI:
@pytest.fixture(autouse=True)
def _fti(self, get_fti, integration):
def _setup(self, get_fti):
self.fti = get_fti(CONTENT_TYPE)

def test_fti(self):
assert isinstance(self.fti, DexterityFTI)

def test_factory(self):
factory = self.fti.factory
obj = createObject(factory)
assert obj is not None
assert isinstance(obj, Person)

@pytest.mark.parametrize(
"behavior",
"attr,expected",
[
"collective.person.person",
"collective.contact_behaviors.contact_info",
"volto.blocks.editable.layout",
"plone.namefromtitle",
"plone.shortname",
"plone.excludefromnavigation",
"plone.relateditems",
"plone.versioning",
"plone.leadimage",
("title", "Person"),
("description", ""),
("global_allow", True),
("filter_content_types", True),
(
"allowed_content_types",
(
"File",
"Image",
),
),
("add_permission", "collective.person.person.add"),
("klass", "collective.person.content.person.Person"),
(
"behaviors",
(
"collective.person.person",
"collective.contact_behaviors.contact_info",
"volto.blocks.editable.layout",
"plone.namefromtitle",
"plone.shortname",
"plone.leadimage",
"plone.excludefromnavigation",
"plone.relateditems",
"plone.versioning",
),
),
],
)
def test_has_behavior(self, get_behaviors, behavior):
assert behavior in get_behaviors(CONTENT_TYPE)
def test_fti(self, attr: str, expected):
"""Test FTI values."""
fti: DexterityFTI = self.fti

assert isinstance(fti, DexterityFTI)
assert getattr(fti, attr) == expected


class TestPerson:
@pytest.fixture(autouse=True)
def _setup(self, portal):
self.portal = portal

def test_create(self, portal, persons_payload):
payload = persons_payload[0]
Expand Down
10 changes: 0 additions & 10 deletions tests/indexing/conftest.py

This file was deleted.

10 changes: 8 additions & 2 deletions tests/indexing/test_catalog_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
import pytest


@pytest.mark.portal(
profiles=[
"collective.person:demo",
"collective.person:catalog",
],
)
class TestCatalogMetadata:
@pytest.fixture(autouse=True)
def _setup(self, portal):
self.portal = portal
def _setup(self, portal_class):
self.portal = portal_class

@pytest.mark.parametrize(
"query,column,expected",
Expand Down
50 changes: 4 additions & 46 deletions tests/restapi/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from plone import api
from plone.app.testing import SITE_OWNER_NAME
from plone.app.testing import SITE_OWNER_PASSWORD
from plone.restapi.testing import RelativeSession

import pytest
import transaction
Expand Down Expand Up @@ -31,59 +29,19 @@ def roles_vocab():

def _create_content(portal, payload):
"""Create a content in the root of the portal."""
return api.content.create(container=portal, **payload)


def _publish_content(content):
"""Publish a content."""
content = api.content.create(container=portal, **payload)
api.content.transition(content, transition="publish")
return content


@pytest.fixture()
def app(functional):
return functional["app"]


@pytest.fixture()
def portal(functional, persons_payload, roles_vocab):
def functional_portal(functional, persons_payload, roles_vocab):
portal = functional["portal"]
with api.env.adopt_user(SITE_OWNER_NAME):
# Set registry for roles
api.portal.set_registry_record("person.roles", roles_vocab)
# Create Content
content = _create_content(portal, persons_payload[0])
with api.env.adopt_user(SITE_OWNER_NAME):
# Publish Content
_publish_content(content)
_create_content(portal, persons_payload[0])

transaction.commit()
return portal


@pytest.fixture()
def http_request(functional):
return functional["request"]


@pytest.fixture()
def request_factory(portal):
def factory():
url = portal.absolute_url()
api_session = RelativeSession(url)
api_session.headers.update({"Accept": "application/json"})
return api_session

return factory


@pytest.fixture()
def anon_request(request_factory):
return request_factory()


@pytest.fixture()
def manager_request(request_factory):
request = request_factory()
request.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD)
yield request
request.auth = ()
Loading