Playwright Tests / test-playwright (1, 2) (push) Canceled after 0s
Playwright Tests / test-playwright (2, 2) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s
A panel is one screen and the ordered set of whole dashboards it shows, so a hallway tablet and a workshop tablet carry different sets without either dashboard knowing about the other. More than one and the device draws a rail to switch between them — the same rail the editor puts on screen, because the wall has it and it takes room off the canvas. A screen has no keyboard, so it pairs rather than logs in: it shows a six-character code, somebody approves it against a panel from the dashboards overview, and the credential that mints reaches that panel's published dashboards and the message endpoints its widgets speak, and nothing else. Deleting the panel revokes it. Closes the per-device view and the kiosk credential; supersedes the multi-page/multi-section UI, since a page is now a dashboard of its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHpLJHozysQXjsxAyU1WHj
69 lines
2.3 KiB
Python
69 lines
2.3 KiB
Python
from collections.abc import Generator
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from sqlalchemy import create_engine, text
|
|
from sqlalchemy.engine import make_url
|
|
from sqlmodel import Session, SQLModel
|
|
|
|
from app.core.config import settings
|
|
from app.core.db import engine, init_db
|
|
from app.main import app
|
|
from tests.utils.user import authentication_token_from_email
|
|
from tests.utils.utils import get_superuser_token_headers
|
|
|
|
|
|
@pytest.fixture(scope="session", autouse=True)
|
|
def flow_data(tmp_path_factory: pytest.TempPathFactory) -> Generator[None, None, None]:
|
|
"""Keep flows and secrets written by tests out of the real store."""
|
|
root = tmp_path_factory.mktemp("flow-data")
|
|
settings.FLOWS_DIR = root / "flows"
|
|
settings.SECRETS_FILE = root / "secrets.enc"
|
|
settings.PANELS_FILE = root / "panels.json"
|
|
yield
|
|
|
|
|
|
@pytest.fixture(scope="session", autouse=True)
|
|
def db() -> Generator[Session, None, None]:
|
|
"""Create the throwaway database `tests/__init__.py` points at, drop it after."""
|
|
url = make_url(str(settings.SQLALCHEMY_DATABASE_URI))
|
|
# The teardown drops this database, so refuse to run against anything but
|
|
# the dedicated test one.
|
|
assert url.database and url.database.endswith("_test"), url.database
|
|
|
|
maintenance = create_engine(
|
|
url.set(database="postgres"), isolation_level="AUTOCOMMIT"
|
|
)
|
|
drop = text(f'DROP DATABASE IF EXISTS "{url.database}" WITH (FORCE)')
|
|
with maintenance.connect() as connection:
|
|
connection.execute(drop)
|
|
connection.execute(text(f'CREATE DATABASE "{url.database}"'))
|
|
|
|
SQLModel.metadata.create_all(engine)
|
|
with Session(engine) as session:
|
|
init_db(session)
|
|
yield session
|
|
|
|
engine.dispose()
|
|
with maintenance.connect() as connection:
|
|
connection.execute(drop)
|
|
maintenance.dispose()
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def client() -> Generator[TestClient, None, None]:
|
|
with TestClient(app) as c:
|
|
yield c
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def superuser_token_headers(client: TestClient) -> dict[str, str]:
|
|
return get_superuser_token_headers(client)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def normal_user_token_headers(client: TestClient, db: Session) -> dict[str, str]:
|
|
return authentication_token_from_email(
|
|
client=client, email=settings.EMAIL_TEST_USER, db=db
|
|
)
|