wiregui/tests/e2e/test_login.py
Stefano Bertelli 3bf6fabcff
Some checks failed
CI / test (push) Failing after 1m52s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
feat: IdP provisioning from YAML file + Playwright e2e tests
Add WG_IDP_CONFIG_FILE env var to seed OIDC/SAML identity providers
from a YAML file at startup, enabling GitOps and IaC workflows.
Providers are upserted by id (merge strategy preserves manual additions).

Convert all e2e tests from NiceGUI User fixture to Playwright async API
with --headed and --slowmo flags for visual debugging. Add full OIDC
login flow test against the mock-oidc service.
2026-03-31 14:23:31 -05:00

63 lines
2.6 KiB
Python

"""End-to-end tests for login, logout, and auth guard flows."""
from playwright.async_api import Page, expect
from wiregui.db import async_session
from wiregui.models.user import User as UserModel
from wiregui.utils.time import utcnow
from tests.e2e.conftest import TEST_APP_BASE, TEST_EMAIL, TEST_PASSWORD, login
async def test_login_valid_credentials(page: Page, test_user: UserModel):
"""Valid login redirects to devices page."""
await login(page)
await expect(page.get_by_text("My Devices")).to_be_visible(timeout=10_000)
async def test_login_invalid_password(page: Page, test_user: UserModel):
"""Wrong password shows error and stays on login page."""
await login(page, password="wrongpassword")
await expect(page.get_by_text("Invalid email or password")).to_be_visible(timeout=10_000)
await expect(page.get_by_role("button", name="Sign in", exact=True)).to_be_visible()
async def test_login_nonexistent_email(page: Page, test_user: UserModel):
"""Nonexistent email shows error."""
await login(page, email="nobody@nowhere.com")
await expect(page.get_by_text("Invalid email or password")).to_be_visible(timeout=10_000)
await expect(page.get_by_role("button", name="Sign in", exact=True)).to_be_visible()
async def test_login_disabled_user(page: Page, test_user: UserModel):
"""Disabled user cannot log in."""
async with async_session() as session:
u = await session.get(UserModel, test_user.id)
u.disabled_at = utcnow()
session.add(u)
await session.commit()
try:
await login(page)
await expect(page.get_by_text("Invalid email or password")).to_be_visible(timeout=10_000)
await expect(page.get_by_role("button", name="Sign in", exact=True)).to_be_visible()
finally:
async with async_session() as session:
u = await session.get(UserModel, test_user.id)
u.disabled_at = None
session.add(u)
await session.commit()
async def test_logout(page: Page, test_user: UserModel):
"""Logout clears session and redirects to login."""
await login(page)
await expect(page.get_by_text("My Devices")).to_be_visible(timeout=10_000)
await page.get_by_text("Logout").click()
await expect(page.get_by_role("button", name="Sign in", exact=True)).to_be_visible(timeout=10_000)
async def test_unauthenticated_redirect(page: Page, test_user: UserModel):
"""Accessing a protected page without auth redirects to login."""
await page.goto(f"{TEST_APP_BASE}/devices")
await expect(page.get_by_role("button", name="Sign in", exact=True)).to_be_visible(timeout=10_000)