test(e2e): replace Cypress with Playwright E2E tests#4108
Conversation
WalkthroughThis PR migrates the RERO ILS end-to-end test suite from Cypress to Playwright. The changes include: a new GitHub Actions workflow that orchestrates Docker, Python, and Playwright browser setup; comprehensive pytest fixtures in conftest.py providing login helpers, REST API utilities, and circulation helpers; updates to test fixture data (libraries, organisations, users) to use "e2e" naming conventions instead of "cypress"; documentation clarifications; and new Playwright test modules implementing five circulation scenarios, login/logout flows, collection CRUD, document editor, and template workflows. Cypress-related files and configurations are removed throughout the codebase. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 20
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/e2e.yml:
- Around line 47-54: The "Start Flask server (background)" step currently
retries the readiness probe loop (for i in $(seq 1 30); do curl ... grep -q OK
&& break; sleep 2; done) but always exits 0 even if the probe never succeeded;
modify the step to detect failure after the loop and exit non‑zero (e.g., check
whether the final curl/grep succeeded or whether the loop completed all 30
iterations) so the job fails fast when the Flask readiness probe never becomes
healthy; update the existing loop logic in the e2e.yml step rather than adding a
new step.
In `@doc/circulation/scenarios.md`:
- Around line 152-153: The doc uses the wrong cancel branch after
ADD_REQUEST_5.1: replace the inconsistent CANCEL_REQUEST_4.1.1 reference with
the matching CANCEL_REQUEST_5.* branch so the cancel action corresponds to the
"5" transit family (IN_TRANSIT_TO_HOUSE); update any cases or examples that
reference CANCEL_REQUEST_4.1.1 to use the appropriate CANCEL_REQUEST_5.*
identifier alongside ADD_REQUEST_5.1.
In `@tests/e2e/conftest.py`:
- Around line 86-95: In _make_page ensure the POST to f"{base_url}/api/login"
checks the Response (e.g., assign the result of p.request.post to a variable)
and assert/raise if it failed (check response.ok or response.status not in
200-299) before proceeding to p.goto; do the same change in the other helper
with identical login behavior (the helper around lines 102-109) so that API
login failures produce immediate, explicit test errors instead of later UI
failures.
- Around line 80-83: Remove all Python type annotations from function signatures
in this conftest.py module (e.g., the fixture function browser_context_args and
other fixtures/helpers in the 86-145 and 145-528 ranges). Locate functions like
browser_context_args, any pytest fixtures or helper functions that currently
contain parameter or return annotations (e.g., ": Type" or "-> Type") and delete
those annotations from the signature while leaving the body and docstrings
unchanged; you may also remove any now-unused typing imports if they become
unused after signature cleanup.
In `@tests/e2e/README.md`:
- Around line 37-43: Update the README wording to clarify that the `--base-url`
requirement only applies to direct `pytest` invocations (e.g., the example `uv
run pytest tests/e2e -m e2e --base-url ...`) and not to the project's task
wrappers; explicitly state that the `uv run poe e2e*` tasks already include
`--base-url https://localhost:5000` by default and only direct `pytest` runs
need an explicit `--base-url` override.
In `@tests/e2e/test_circulation_scenario_a.py`:
- Around line 60-79: Remove all Python type annotations from the test function
and fixture signatures in this module: change the fixture function
_test_data(librarian_page: Page, base_url: str) to _test_data(librarian_page,
base_url) and change the test function test_standard_loan(librarian_page: Page,
base_url: str, _test_data) to test_standard_loan(librarian_page, base_url,
_test_data); ensure any other test/fixture signatures in this file also drop
annotations (no : Type or -> ReturnType) while keeping names and behavior
unchanged.
- Around line 73-75: Teardown currently deletes the item with api_delete which
can fail if requests/loans exist; replace the raw item delete with the safer
barcode-based cleanup by calling api_cleanup_items_by_barcode(...) using the
created item's barcode (item_pid) before deleting the document with
api_delete(documents, doc_pid); update the teardown where yield doc_pid,
item_pid is followed by api_delete(librarian_page, base_url, "items", item_pid)
to instead call api_cleanup_items_by_barcode(librarian_page, base_url,
[item_pid]) and then api_delete(librarian_page, base_url, "documents", doc_pid).
In `@tests/e2e/test_circulation_scenario_b.py`:
- Around line 60-84: Remove all Python type annotations from the test/factory
function signatures in this module: change the fixture def
_test_data(librarian_page: Page, base_url: str) to def
_test_data(librarian_page, base_url) and change the test def
test_loan_with_transit(librarian_page: Page, spock_page: Page, base_url: str,
_test_data) to def test_loan_with_transit(librarian_page, spock_page, base_url,
_test_data); do not modify logic inside api_* calls or the yield/cleanup, and if
you need type hints keep them only as comments or in stub/type files rather than
inline annotations.
- Around line 73-75: The teardown currently calls api_delete(librarian_page,
base_url, "items", item_pid) then api_delete(..., "documents", doc_pid) which
can fail to remove items left in transit/checkout; replace the raw item delete
with a resilient cleanup call by invoking
api_cleanup_items_by_barcode(librarian_page, base_url, barcode=item_pid or
actual barcode variable) (or the helper's signature) before deleting the
document, then proceed to call api_delete for the document; ensure you still
yield doc_pid, item_pid as before and reference api_cleanup_items_by_barcode,
api_delete, doc_pid, item_pid, librarian_page and base_url so the change is
local to the teardown block.
In `@tests/e2e/test_circulation_scenario_c.py`:
- Around line 60-73: The fixture _test_data and the test function
test_multiple_requests_with_transit contain Python type annotations in their
signatures; remove all parameter and return type annotations (e.g., ": Page", ":
str", and any "-> ..." parts) from the _test_data fixture and the
test_multiple_requests_with_transit definition so they follow the repo rule
against signature annotations while keeping names and behavior unchanged.
In `@tests/e2e/test_circulation_scenario_d.py`:
- Line 70: The test module uses Python type annotations in function signatures
(e.g., def _test_data(librarian_page: Page, base_url: str):) which violates the
repo rule for test files; remove all parameter and return annotations from
_test_data and the other helper/test functions in this file (the ones that
currently annotate Page, str, int or use -> return types), leaving plain def
_test_data(librarian_page, base_url): etc., and then clean up any now-unused
typing imports (Page, str/typing imports) at top of the file.
In `@tests/e2e/test_circulation_scenario_e.py`:
- Line 68: Remove all Python signature type annotations from functions in this
test module (e.g., the helper _test_data and the other functions at the
indicated locations) so they follow the repo rule forbidding annotations in
signatures; edit each function definition to drop parameter and return
annotations (leave parameter names and body unchanged) for symbols like
_test_data, the helper functions at lines ~79, ~95, ~112 and the test at ~131 so
the signatures contain plain names only (no ": type" or "-> type").
- Around line 112-127: The helper _update_pickup_location currently returns
silently when no pending loan is found and ignores the POST response; change it
to fail the test when no pending loan exists and assert the update succeeded: in
_update_pickup_location, after computing item_pid and querying loans (using
item_barcode and loan_pid), raise/assert if hits is empty, then call the POST to
/api/item/update_loan_pickup_location with loan_pid and pickup_location_pid and
assert the response status_code is 200 (or check the response JSON for success)
so the test fails if the pickup-location update did not occur.
In `@tests/e2e/test_collections.py`:
- Around line 55-65: COURSE and EXHIBITION currently use hard-coded
collection_id values causing cross-run collisions; update the test fixtures
(variables named COURSE and EXHIBITION and any other similar dicts between lines
~70-102) to generate unique collection_id per test run (e.g., append a
timestamp/UUID or use pytest's tmp/unique helper) so create/edit/delete flows
never clash with leftovers from prior runs; ensure the generated IDs are
deterministic within a single test run but unique across runs and propagate the
new collection_id values to all places in the test that reference them.
- Line 30: Remove Python signature annotations from the test module: drop the ":
Page", ": str", ": int = 0" and "-> None" from the _pick_date function
definition and do the same for the other helper/test function signatures flagged
in this file (the other helpers referenced in the review). Ensure function names
(e.g., _pick_date) keep the same parameters but without type annotations so the
signatures comply with the repo rule forbidding type annotations in test .py
files.
In `@tests/e2e/test_document_editor.py`:
- Line 26: Remove all Python function signature type annotations from this test
module (e.g., the return annotation "-> None" and any parameter type hints) so
the functions comply with the repo rule; specifically update
_wait_for_form_ready and the other helper/test functions referenced (the
functions at the other comment locations) to have plain untyped signatures (no
": Type" or "-> Type") while leaving bodies and behavior unchanged.
In `@tests/e2e/test_login.py`:
- Line 27: Remove Python signature type annotations from the test functions in
this module — e.g., change the signature of test_librarian_login (and the other
test functions reported) to plain untyped parameters; specifically, eliminate
all ": Type" and "-> Type" annotations from the function signatures so they
conform to the repo rule forbidding signature annotations while keeping the rest
of each function body intact.
In `@tests/e2e/test_templates.py`:
- Around line 28-29: TEMPLATE_NAME is a static global which can collide between
runs; change it to be generated uniquely per test run (e.g., append a timestamp
or uuid) and propagate that dynamic name into every place the constant is used
(the module-level TEMPLATE_NAME and all usages referenced around lines 62-84),
or create a fixture that returns a unique_name and use that fixture in tests
that create/load templates; ensure cleanup uses the same generated name so
delete/lookup targets the correct record.
- Line 34: The test function test_create_and_use_template should not use Python
signature annotations; remove the type annotations from its signature (change
"def test_create_and_use_template(librarian_page: Page, base_url: str):" to "def
test_create_and_use_template(librarian_page, base_url):") and, if the Page type
import (e.g., from playwright...) becomes unused, also remove that import to
avoid unused-import warnings.
In `@tests/ui/test_views.py`:
- Around line 71-74: The test test_view_parameter_e2e currently expects a 404
for the URL built with url_for("rero_ils.index_with_view_code", viewcode="e2e")
but the seeded fixture now defines the viewcode "e2e"; update the assertion in
test_view_parameter_e2e to expect a successful resolution (e.g., assert
result.status_code == 200) so it matches how other known view codes are tested
and resolves against the seeded fixture.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c2324f6c-13e7-419a-b101-5df37b2b3804
⛔ Files ignored due to path filters (5)
doc/circulation/loan_states.dotis excluded by!**/*.dotdoc/circulation/loan_states.svgis excluded by!**/*.svgdoc/reroils_resources.svgis excluded by!**/*.svgtests/e2e/cypress/package-lock.jsonis excluded by!**/package-lock.jsonuv.lockis excluded by!**/*.lock
📒 Files selected for processing (66)
.github/workflows/e2e.yml.gitignoreMANIFEST.incheck_license_config.ymldata/libraries.jsondata/organisations.jsondata/users.jsondoc/README.mddoc/circulation/README.mddoc/circulation/actions.mddoc/circulation/scenarios.mdpyproject.tomlrero_ils/modules/organisations/api.pyscripts/bootstrapscripts/cypresstests/e2e/README.mdtests/e2e/conftest.pytests/e2e/cypress/.gitignoretests/e2e/cypress/__init__.pytests/e2e/cypress/cypress.jsontests/e2e/cypress/cypress/fixtures/cipo.jsontests/e2e/cypress/cypress/fixtures/collections.jsontests/e2e/cypress/cypress/fixtures/common.jsontests/e2e/cypress/cypress/fixtures/documents.jsontests/e2e/cypress/cypress/fixtures/item_types.jsontests/e2e/cypress/cypress/fixtures/items.jsontests/e2e/cypress/cypress/fixtures/patron_types.jsontests/e2e/cypress/cypress/fixtures/templates.jsontests/e2e/cypress/cypress/fixtures/users.jsontests/e2e/cypress/cypress/integration/application/test-login-logout.spec.jstests/e2e/cypress/cypress/integration/circulation/scenario-a.spec.jstests/e2e/cypress/cypress/integration/circulation/scenario-b.spec.jstests/e2e/cypress/cypress/integration/circulation/test-on-site-cipo.spec.jstests/e2e/cypress/cypress/integration/collections/test-collections.spec.jstests/e2e/cypress/cypress/integration/editor/ci-po/create-ci-po.spec.jstests/e2e/cypress/cypress/integration/editor/document/create-document-prov-activity.spec.jstests/e2e/cypress/cypress/integration/editor/document/create-document-resp-statement.spec.jstests/e2e/cypress/cypress/integration/editor/document/create-document-simple-fields.spec.jstests/e2e/cypress/cypress/integration/editor/document/create-simple-document.spec.jstests/e2e/cypress/cypress/integration/examples/empty-template.spec.js.disabledtests/e2e/cypress/cypress/integration/examples/example-test-request.spec.jstests/e2e/cypress/cypress/integration/templates/templates-test.spec.jstests/e2e/cypress/cypress/plugins/index.jstests/e2e/cypress/cypress/support/api.jstests/e2e/cypress/cypress/support/cipo.jstests/e2e/cypress/cypress/support/circulation.jstests/e2e/cypress/cypress/support/collection.jstests/e2e/cypress/cypress/support/commands.jstests/e2e/cypress/cypress/support/document.jstests/e2e/cypress/cypress/support/index.jstests/e2e/cypress/cypress/support/navigation.jstests/e2e/cypress/cypress/support/record.jstests/e2e/cypress/cypress/support/user.jstests/e2e/cypress/cypress/support/utils.jstests/e2e/cypress/package.jsontests/e2e/test_circulation_scenario_a.pytests/e2e/test_circulation_scenario_b.pytests/e2e/test_circulation_scenario_c.pytests/e2e/test_circulation_scenario_d.pytests/e2e/test_circulation_scenario_e.pytests/e2e/test_collections.pytests/e2e/test_document_editor.pytests/e2e/test_front_page.pytests/e2e/test_login.pytests/e2e/test_templates.pytests/ui/test_views.py
💤 Files with no reviewable changes (43)
- tests/e2e/cypress/cypress/fixtures/patron_types.json
- tests/e2e/cypress/cypress/fixtures/item_types.json
- tests/e2e/cypress/cypress/integration/templates/templates-test.spec.js
- tests/e2e/cypress/cypress/integration/examples/example-test-request.spec.js
- tests/e2e/cypress/cypress/fixtures/templates.json
- tests/e2e/cypress/.gitignore
- tests/e2e/cypress/cypress/fixtures/documents.json
- tests/e2e/cypress/cypress/fixtures/users.json
- tests/e2e/cypress/cypress/fixtures/collections.json
- tests/e2e/test_front_page.py
- tests/e2e/cypress/cypress/support/circulation.js
- tests/e2e/cypress/cypress/integration/editor/document/create-document-resp-statement.spec.js
- tests/e2e/cypress/cypress/integration/examples/empty-template.spec.js.disabled
- tests/e2e/cypress/cypress/integration/collections/test-collections.spec.js
- tests/e2e/cypress/cypress/fixtures/common.json
- tests/e2e/cypress/cypress/integration/circulation/test-on-site-cipo.spec.js
- tests/e2e/cypress/cypress/support/document.js
- tests/e2e/cypress/cypress/fixtures/cipo.json
- tests/e2e/cypress/cypress/integration/circulation/scenario-a.spec.js
- tests/e2e/cypress/cypress/support/utils.js
- tests/e2e/cypress/cypress/support/navigation.js
- tests/e2e/cypress/cypress/integration/editor/document/create-document-prov-activity.spec.js
- tests/e2e/cypress/cypress/support/index.js
- scripts/cypress
- tests/e2e/cypress/cypress/support/cipo.js
- tests/e2e/cypress/cypress/integration/application/test-login-logout.spec.js
- tests/e2e/cypress/cypress/plugins/index.js
- tests/e2e/cypress/cypress/integration/editor/ci-po/create-ci-po.spec.js
- tests/e2e/cypress/cypress/fixtures/items.json
- tests/e2e/cypress/cypress/support/record.js
- tests/e2e/cypress/cypress/support/commands.js
- check_license_config.yml
- MANIFEST.in
- tests/e2e/cypress/init.py
- tests/e2e/cypress/cypress.json
- tests/e2e/cypress/package.json
- tests/e2e/cypress/cypress/integration/circulation/scenario-b.spec.js
- tests/e2e/cypress/cypress/support/user.js
- tests/e2e/cypress/cypress/support/collection.js
- tests/e2e/cypress/cypress/support/api.js
- tests/e2e/cypress/cypress/integration/editor/document/create-document-simple-fields.spec.js
- tests/e2e/cypress/cypress/integration/editor/document/create-simple-document.spec.js
- .gitignore
40ae1d7 to
7d6336c
Compare
f2ffd44 to
fbf2341
Compare
fbf2341 to
48c39d6
Compare
206ce1f to
f9a6730
Compare
f9a6730 to
3b179fb
Compare
3c8f839 to
a572a79
Compare
14027f0 to
e444f45
Compare
0cc45ce to
3556231
Compare
05b0ae1 to
67f8b0c
Compare
Replace the unmaintained Cypress test suite (last updated 2020) with a modern Playwright-based suite using pytest-playwright. All tests are driven via the REST API for state management and the Angular UI only for interaction assertions. * delete all Cypress specs, fixtures, support files and the scripts/cypress runner * add pytest-playwright to dev dependencies and configure poe tasks: e2e (all browsers, cross-browser mark), e2e_chromium, e2e_firefox, e2e_webkit * add bootstrap step to install Chromium, Firefox and WebKit browsers * add E2E=yes to conftest.py so pytest-invenio does not skip the tests * introduce isolated browser contexts per fixture so concurrent librarian/patron/spock sessions do not share cookies * add @pytest.mark.chromium_only for tests requiring Angular PrimeNG form submission (document editor, collections, templates); these tests are excluded from Firefox/WebKit runs * implement test_login.py: librarian login, logout, patron login * implement test_circulation_scenario_a.py: standard loan at owning library (ADD_REQUEST_1.1 → VALIDATE_1.2 → CHECKOUT_2.1 → CHECKIN_3.1.1) * implement test_circulation_scenario_b.py: standard loan with inter-library transit (VALIDATE_1.2 → CHECKIN_4.1 → CHECKOUT_2.1 → CHECKIN_3.1.2 → CHECKIN_5.1.1) * implement test_circulation_scenario_c.py: multiple in-transit requests, two patrons * implement test_circulation_scenario_d.py: denied actions and unconventional workflow * implement test_circulation_scenario_e.py: complex workflow with mid-cycle cancellations and pickup location changes * implement test_document_editor.py: create document via Angular editor (chromium_only) * implement test_collections.py: create, edit and delete a collection (chromium_only) * add tests/e2e/README.md documenting how to run the tests, why chromium_only exists and how to remove it via rero-ils-ui/ng-core * rename "cypress" to "e2e" in data/organisations.json, data/libraries.json and data/users.json; update viewcode test in tests/ui/test_views.py and is_test_organisation() in rero_ils/modules/organisations/api.py accordingly * fix api_harvester models.save(): add db.session.commit() after begin_nested() so lastrun updates are actually persisted * fix api_harvester cli set-last-run: parse ISO date string to datetime before assigning to the DateTime column * update doc/circulation/loan_states.dot: split ITEM_IN_TRANSIT into ITEM_IN_TRANSIT_FOR_PICKUP and ITEM_IN_TRANSIT_TO_HOUSE, remove non-existent DISPUTED and DELETED states, rename delivery_receive / house_receive to receive, add cancel transitions; regenerate SVG * update doc/circulation/scenarios.md: fix action reference notation (underscore → dot), correct prose, use standard fenced code blocks * update doc/circulation/README.md: use backtick-wrapped state names, fix line-break markup, tighten prose * update doc/README.md: fix heading levels and .jpg typo in make output Co-Authored-by: Peter Weber <peter.weber@rero.ch>
67f8b0c to
f75ff16
Compare
Replace the unmaintained Cypress test suite (last updated 2020) with a modern Playwright-based suite using pytest-playwright. All tests are driven via the REST API for state management and the Angular UI only for interaction assertions.