Skip to content

Add uninstalled, functional-layer, and request-builder fixtures#43

Merged
ericof merged 4 commits intomainfrom
issues-38-39-40
Apr 16, 2026
Merged

Add uninstalled, functional-layer, and request-builder fixtures#43
ericof merged 4 commits intomainfrom
issues-38-39-40

Conversation

@ericof
Copy link
Copy Markdown
Member

@ericof ericof commented Apr 16, 2026

Summary

Ships three high-signal fixture additions that eliminate the most common sources of boilerplate duplication across downstream Plone add-ons:

  • uninstalled — reads a user-provided package_name fixture and calls installer.uninstall_product. Removes the canonical copy-pasted autouse fixture used in add-on uninstall smoke tests.
  • functional_app / functional_portal / functional_http_request — functional-layer counterparts to app / portal / http_request. functional_portal honors @pytest.mark.portal for profiles, content, and roles.
  • request_factory / manager_request / anon_request — builder + convenience fixtures returning a RelativeSession against the functional portal. Supports role="Manager", role="Anonymous", or explicit basic_auth=(user, password), with the ++api++ traverser enabled by default.

Notes

  • The RelativeSession class in fixtures/requests.py is a standalone minimal equivalent of plone.restapi.testing.RelativeSession, chosen to avoid pulling in plone.restapi[test]'s fragile import chain (plone.app.iterate, collective.MockMailHost) as a hard pytest-plone dependency. Same calling convention downstream already expects.
  • requests is now an explicit runtime dependency (previously only transitive via Products.CMFPlone).
  • README has a dedicated section for each new fixture; news fragments added for all three issues.

Test plan

  • Three new test modules: test_uninstalled.py, test_functional_layer.py, test_request_factory.py
  • functional_portal marker behavior covered (roles, content, no-marker)
  • request_factory: default/Manager/api=False/basic_auth/unknown-role/Accept header
  • RelativeSession relative-URL resolution and absolute-URL passthrough
  • Full suite: 47 passed locally (uv run pytest)
  • ruff check + ruff format clean

Closes #38
Closes #39
Closes #40

ericof added 4 commits April 16, 2026 12:02
Adds an `uninstalled` fixture that reads a user-provided `package_name`
fixture and calls `installer.uninstall_product`. Removes the per-project
boilerplate that downstream codebases duplicate in their canonical add-on
uninstall smoke test.

Closes #38
Adds `functional_app`, `functional_portal`, and `functional_http_request`
as functional-layer counterparts to the existing integration-layer
fixtures. `functional_portal` honors `@pytest.mark.portal`, matching the
behavior of `portal`.

This eliminates the most common reason downstream codebases override
pytest-plone fixtures — aliasing `functional["portal"]` as `portal`.

Closes #39
Introduces `request_factory`, `manager_request`, and `anon_request`,
replacing the 5+ near-identical session fixtures that downstream
codebases reimplement.

`request_factory` returns a built-in `RelativeSession` (a thin
`requests.Session` subclass) bound to the functional portal. Supported
modes: `role="Manager"`, `role="Anonymous"` (default), or explicit
`basic_auth=(user, password)`. The `++api++` suffix is added by default.

The standalone `RelativeSession` avoids pulling in
`plone.restapi[test]`'s fragile import chain (`plone.app.iterate`,
`collective.MockMailHost`) while keeping the same calling convention
downstream code already expects.

Closes #40
CI runs `uvx mypy src` in an isolated environment that does not honor the project's `ignore_missing_imports=true` setting in pyproject.toml. Add an inline type: ignore on the `requests` import rather than broadening CI or adding `types-requests` just for a single import.
@ericof ericof merged commit 03863e4 into main Apr 16, 2026
12 checks passed
@ericof ericof deleted the issues-38-39-40 branch April 16, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant