You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add uninstalled, functional-layer, and request-builder fixtures (#43)
* Add uninstalled fixture (#38)
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
* Add functional-layer fixtures (#39)
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
* Add request-builder fixtures (#40)
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
* Silence mypy import-untyped warning for requests
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.
| Description | Zope root bound to the **functional** testing layer. |
147
+
| Required Fixture |**functional**|
148
+
| Scope |**Function**|
149
+
150
+
Use this when you need a functional-layer counterpart to `app` — typically for REST API or browser tests.
151
+
152
+
```python
153
+
deftest_functional_app(functional_app):
154
+
"""Test app title."""
155
+
assert functional_app.getPhysicalPath() == ("", )
156
+
```
157
+
158
+
### functional_portal
159
+
160
+
|||
161
+
| --- | --- |
162
+
| Description | Portal object bound to the **functional** testing layer. Honors `@pytest.mark.portal`. |
163
+
| Required Fixture |**functional**|
164
+
| Scope |**Function**|
165
+
166
+
Parallel to `portal`, but bound to the functional layer. Accepts the same `@pytest.mark.portal` marker for profiles, content, and roles — see the **Markers** section.
This fixture removes the duplicate per-project boilerplate from the canonical uninstall smoke test. You must define a `package_name` fixture in your `conftest.py` (or test module) that returns the distribution name of your add-on.
242
+
243
+
```python
244
+
import pytest
245
+
246
+
247
+
@pytest.fixture
248
+
defpackage_name() -> str:
249
+
"""Distribution name of the add-on under test."""
250
+
return"collective.person"
251
+
252
+
253
+
classTestSetupUninstall:
254
+
@pytest.fixture(autouse=True)
255
+
def_uninstalled(self, uninstalled):
256
+
"""Uninstall the add-on before every test in this class."""
| Description | Callable that builds a `RelativeSession` against the functional portal. |
452
+
| Required Fixture |**functional_portal**|
453
+
| Scope |**Function**|
454
+
455
+
Replaces the 5+ near-identical request-session fixtures that downstream codebases reimplement. Returns a `RelativeSession` (a thin `requests.Session` subclass that resolves relative URLs against the portal's base URL) with sensible defaults:
456
+
457
+
-`role="Manager"` — authenticate as the portal owner.
458
+
-`role="Anonymous"` (default) — no authentication.
459
+
-`basic_auth=(user, password)` — any other identity; takes precedence over `role`.
460
+
-`api=True` (default) — suffix the base URL with `++api++` so relative calls hit the REST API.
461
+
462
+
Sessions are closed automatically at the end of the test.
463
+
464
+
```python
465
+
deftest_list_content(request_factory):
466
+
"""Test that the Manager role can list content."""
467
+
session = request_factory(role="Manager")
468
+
response = session.get("/")
469
+
assert response.status_code ==200
470
+
```
471
+
472
+
### manager_request
473
+
474
+
|||
475
+
| --- | --- |
476
+
| Description |`RelativeSession` pre-authenticated as the portal owner (Manager). |
477
+
| Required Fixture |**request_factory**|
478
+
| Scope |**Function**|
479
+
480
+
```python
481
+
deftest_controlpanels(manager_request):
482
+
"""Test listing of control panels."""
483
+
response = manager_request.get("/@controlpanels")
484
+
assert response.status_code ==200
485
+
```
486
+
487
+
### anon_request
488
+
489
+
|||
490
+
| --- | --- |
491
+
| Description |`RelativeSession` with no authentication (Anonymous). |
Added the `uninstalled` fixture — reads a user-provided `package_name` fixture and calls `installer.uninstall_product`, removing boilerplate from the canonical add-on uninstall smoke test. @ericof
Added `functional_app`, `functional_portal`, and `functional_http_request` fixtures — functional-layer counterparts to `app`, `portal`, and `http_request`. `functional_portal` honors the `@pytest.mark.portal` marker. @ericof
Added `request_factory`, `manager_request`, and `anon_request` fixtures — build a `RelativeSession` against the functional portal with Manager, Anonymous, or custom basic-auth credentials. Replaces boilerplate duplicated across downstream codebases. @ericof
0 commit comments