tests/e2e/test_requests_overseerr_e2e.py
Rama dev · réplica de lectura del repositorio original.
"""Routing requests through Overseerr/Jellyseerr, driven through the real screens (discussion #110).
Round-tripped through the API rather than asserted on the DOM alone: a chooser that renders and
saves nothing would pass a render-only check, and what the target setting is worth is entirely the
value that reaches a run.
Nothing here answers as Overseerr — no fake serves its API — which is deliberate. The account list
is fetched, so this covers the case the card has to survive: the target is chosen, saved and
reloaded even when the instance behind it never replies.
"""
from __future__ import annotations
import pytest
from playwright.sync_api import Page, expect
from tests.e2e.conftest import ShortlistApp
pytestmark = pytest.mark.e2e
LOAD = 15_000
def _saved_status(page: Page):
"""The Requests tab's own "Saved" readout (it has no save bar)."""
return page.get_by_role("status").get_by_text("Saved", exact=True)
def _panel(page: Page):
"""The Requests panel alone.
Scoped, not page-wide: Settings → Connections carries its own Radarr, Sonarr and Overseerr cards,
which stay on screen whichever route is chosen. A page-wide locator therefore matches the
connection card as well as the control under test — "Overseerr / Jellyseerr" resolves to two
buttons, and "Radarr" is present no matter what the target is set to.
"""
return page.locator("section#requests")
def _connect_overseerr(app: ShortlistApp) -> None:
"""Requests on, with Overseerr's address and key saved — what makes the card render its controls."""
app.api(
"PUT",
"/api/settings",
json={
"values": {
"requests.enabled": True,
"requests.overseerr.url": "http://overseerr.invalid",
"requests.overseerr.apikey": "fake-key",
}
},
)
def test_switching_the_target_saves_and_survives_a_reload(page: Page, app: ShortlistApp):
_connect_overseerr(app)
page.goto("/settings#requests")
expect(_panel(page).get_by_role("button", name="Radarr & Sonarr")).to_have_attribute(
"aria-pressed", "true", timeout=LOAD
)
_panel(page).get_by_role("button", name="Overseerr / Jellyseerr", exact=True).click()
# Autosave has no button; the stored value is the real wait.
expect(_saved_status(page)).to_be_visible(timeout=LOAD)
app.wait_for_setting("requests.target", "overseerr")
page.reload()
expect(_panel(page).get_by_role("button", name="Overseerr / Jellyseerr", exact=True)).to_have_attribute(
"aria-pressed", "true", timeout=LOAD
)
def test_the_overseerr_card_replaces_the_two_arr_cards(page: Page, app: ShortlistApp):
_connect_overseerr(app)
app.api("PUT", "/api/settings", json={"values": {"requests.target": "overseerr"}})
page.goto("/settings#requests")
expect(_panel(page).get_by_label("Request as")).to_be_visible(timeout=LOAD)
expect(_panel(page).get_by_text("Radarr", exact=True)).to_have_count(0)
expect(_panel(page).get_by_text("Sonarr", exact=True)).to_have_count(0)
# Guardrails belong to Shortlist, not to the app doing the fetching, so they stay on both routes.
expect(_panel(page).get_by_text("Guardrails", exact=True)).to_be_visible()
def test_the_tag_fields_are_gone_because_overseerr_cannot_carry_them(page: Page, app: ShortlistApp):
"""Overseerr's POST /request body has no tags field, so offering the setting would be a lie."""
_connect_overseerr(app)
app.api("PUT", "/api/settings", json={"values": {"requests.target": "overseerr"}})
page.goto("/settings#requests")
expect(_panel(page).get_by_label("Request as")).to_be_visible(timeout=LOAD)
expect(_panel(page).get_by_label("Tag added items")).to_have_count(0)
expect(_panel(page).get_by_label("Also tag by person")).to_have_count(0)
def test_the_default_route_still_shows_radarr_and_sonarr(page: Page, app: ShortlistApp):
"""The control case. Adding a second route must not change what an existing install sees."""
app.api("PUT", "/api/settings", json={"values": {"requests.enabled": True}})
page.goto("/settings#requests")
expect(_panel(page).get_by_text("Radarr", exact=True).first).to_be_visible(timeout=LOAD)
expect(_panel(page).get_by_text("Sonarr", exact=True).first).to_be_visible()
expect(_panel(page).get_by_label("Request as")).to_have_count(0)