tests: refactor to pytest (conftest session fixture, sync wrappers for async, importorskip for playwright)
This commit is contained in:
1 parent
bb1297f8e2
commit
29fab7ff5f
5 files changed
+130
-135
No files matched your search
+41
-31
@@ -1,16 +1,17 @@
|
||||
"""Browser tests for ani-web (Playwright, headless Chromium).
|
||||
|
||||
Run via tests/run.py or standalone: python tests/test_browser.py <base_url>
|
||||
Covers what HTTP tests can't: the login UI, the user chip, and real
|
||||
video playback behind auth. Needs: pip install playwright && playwright install chromium
|
||||
Run via pytest (see conftest.py for the throwaway server). Covers what
|
||||
HTTP tests can't: the login UI, the user chip, and real video playback
|
||||
behind auth. Skipped if playwright is not installed.
|
||||
"""
|
||||
import asyncio
|
||||
import http.cookiejar
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
from playwright.async_api import async_playwright
|
||||
import pytest
|
||||
|
||||
async_playwright = pytest.importorskip("playwright.async_api").async_playwright
|
||||
|
||||
BASE = "http://127.0.0.1:8399"
|
||||
LAUNCH_ARGS = ["--autoplay-policy=no-user-gesture-required"]
|
||||
@@ -36,7 +37,11 @@ async def _login(page, user, pw):
|
||||
timeout=5000, polling=POLL)
|
||||
|
||||
|
||||
async def test_login_ui():
|
||||
def test_login_ui():
|
||||
asyncio.run(_login_ui())
|
||||
|
||||
|
||||
async def _login_ui():
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(args=LAUNCH_ARGS)
|
||||
page = await (await browser.new_context()).new_page()
|
||||
@@ -65,7 +70,6 @@ async def test_login_ui():
|
||||
assert "Seed Anime" in await page.inner_text("#main"), "seeded history must show"
|
||||
assert not errors, errors
|
||||
await browser.close()
|
||||
print("ok test_login_ui")
|
||||
|
||||
|
||||
async def _login_settled(page):
|
||||
@@ -74,7 +78,11 @@ async def _login_settled(page):
|
||||
"document.getElementById('me').textContent.length > 0", timeout=5000, polling=POLL)
|
||||
|
||||
|
||||
async def test_video_plays_behind_auth():
|
||||
def test_video_plays_behind_auth():
|
||||
asyncio.run(_video_plays_behind_auth())
|
||||
|
||||
|
||||
async def _video_plays_behind_auth():
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(args=LAUNCH_ARGS)
|
||||
page = await (await browser.new_context()).new_page()
|
||||
@@ -94,10 +102,13 @@ async def test_video_plays_behind_auth():
|
||||
real_errors = [e for e in errors if "401" not in e]
|
||||
assert not real_errors, real_errors
|
||||
await browser.close()
|
||||
print("ok test_video_plays_behind_auth")
|
||||
|
||||
|
||||
async def test_history_page_and_delete():
|
||||
def test_history_page_and_delete():
|
||||
asyncio.run(_history_page_and_delete())
|
||||
|
||||
|
||||
async def _history_page_and_delete():
|
||||
# self-contained: seed erin's own entries over HTTP first
|
||||
jar = http.cookiejar.CookieJar()
|
||||
op = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
|
||||
@@ -129,10 +140,13 @@ async def test_history_page_and_delete():
|
||||
await page.wait_for_selector(".toast", timeout=5000)
|
||||
assert not errors, errors
|
||||
await browser.close()
|
||||
print("ok test_history_page_and_delete")
|
||||
|
||||
|
||||
async def test_stream_failure_retry():
|
||||
def test_stream_failure_retry():
|
||||
asyncio.run(_stream_failure_retry())
|
||||
|
||||
|
||||
async def _stream_failure_retry():
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(args=LAUNCH_ARGS)
|
||||
page = await (await browser.new_context()).new_page()
|
||||
@@ -157,10 +171,13 @@ async def test_stream_failure_retry():
|
||||
"document.querySelector('video').readyState >= 4 && document.querySelector('video').currentTime > 1",
|
||||
timeout=120000, polling=250)
|
||||
await browser.close()
|
||||
print("ok test_stream_failure_retry")
|
||||
|
||||
|
||||
async def test_recent_searches():
|
||||
def test_recent_searches():
|
||||
asyncio.run(_recent_searches())
|
||||
|
||||
|
||||
async def _recent_searches():
|
||||
# UI: focus the (empty) search box -> dropdown of saved searches;
|
||||
# typing filters; clicking one runs the search.
|
||||
jar = http.cookiejar.CookieJar()
|
||||
@@ -192,10 +209,13 @@ async def test_recent_searches():
|
||||
assert "q=chainsaw" in page.url, page.url
|
||||
assert not errors, errors
|
||||
await browser.close()
|
||||
print("ok test_recent_searches")
|
||||
|
||||
|
||||
async def test_auto_next_countdown():
|
||||
def test_auto_next_countdown():
|
||||
asyncio.run(_auto_next_countdown())
|
||||
|
||||
|
||||
async def _auto_next_countdown():
|
||||
# playing a full episode to its natural end is too slow; simulate the
|
||||
# `ended` event and verify the countdown overlay + cancel path.
|
||||
async with async_playwright() as p:
|
||||
@@ -223,10 +243,13 @@ async def test_auto_next_countdown():
|
||||
assert "E1" in await page.inner_text(".ep.active")
|
||||
assert not errors, errors
|
||||
await browser.close()
|
||||
print("ok test_auto_next_countdown")
|
||||
|
||||
|
||||
async def test_episode_watch_state():
|
||||
def test_episode_watch_state():
|
||||
asyncio.run(_episode_watch_state())
|
||||
|
||||
|
||||
async def _episode_watch_state():
|
||||
# completed episodes dimmed with a check, first unwatched highlighted.
|
||||
# seed the first rendered ep as finished (id read off the list),
|
||||
# reload, and check the classes.
|
||||
@@ -252,16 +275,3 @@ async def test_episode_watch_state():
|
||||
await page.wait_for_selector("#eps .ep.nextup", timeout=10000)
|
||||
assert not errors, errors
|
||||
await browser.close()
|
||||
print("ok test_episode_watch_state")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
BASE = sys.argv[1]
|
||||
asyncio.run(test_login_ui())
|
||||
asyncio.run(test_video_plays_behind_auth())
|
||||
asyncio.run(test_history_page_and_delete())
|
||||
asyncio.run(test_stream_failure_retry())
|
||||
asyncio.run(test_recent_searches())
|
||||
asyncio.run(test_auto_next_countdown())
|
||||
asyncio.run(test_episode_watch_state())
|
||||
Reference in new issue
Block a user