import sys from pathlib import Path import pytest from fastapi.testclient import TestClient from sqlalchemy import create_engine, text from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import StaticPool sys.path.insert(0, str(Path(__file__).resolve().parent)) from app import database as database_module from app.database import Base, get_db from app.main import app from app.models.custom_page import CustomPage from app.utils.auth import get_current_user @pytest.fixture() def db_session(): engine = create_engine( "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool, ) Base.metadata.create_all(bind=engine) TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) db = TestingSessionLocal() try: yield db finally: db.close() Base.metadata.drop_all(bind=engine) @pytest.fixture() def client(db_session): def override_get_db(): yield db_session app.dependency_overrides[get_db] = override_get_db app.dependency_overrides[get_current_user] = lambda: object() try: yield TestClient(app) finally: app.dependency_overrides.clear() def test_create_page_auto_enables_autofill_when_credentials_are_saved(client): response = client.post("/api/custom-pages", json={ "name": "Login page", "url": "https://example.test/login", "access_mode": "remote_browser", "login_username": "alice", "login_password": "secret", }) assert response.status_code == 201 assert response.json()["login_autofill_enabled"] is True assert response.json()["login_password_configured"] is True def test_create_page_respects_explicit_autofill_disable(client): response = client.post("/api/custom-pages", json={ "name": "Login page", "url": "https://example.test/login", "access_mode": "remote_browser", "login_username": "alice", "login_password": "secret", "login_autofill_enabled": False, }) assert response.status_code == 201 assert response.json()["login_autofill_enabled"] is False def test_update_page_auto_enables_autofill_when_new_password_is_saved(client, db_session): page = CustomPage( name="Login page", url="https://example.test/login", access_mode="remote_browser", login_username="alice", login_password="old-secret", login_autofill_enabled=False, ) db_session.add(page) db_session.commit() db_session.refresh(page) response = client.put(f"/api/custom-pages/{page.id}", json={ "login_username": "alice@example.test", "login_password": "new-secret", }) assert response.status_code == 200 assert response.json()["login_autofill_enabled"] is True def test_update_page_keeps_autofill_disabled_when_existing_password_is_kept(client, db_session): page = CustomPage( name="Login page", url="https://example.test/login", access_mode="remote_browser", login_username="alice", login_password="secret", login_autofill_enabled=False, ) db_session.add(page) db_session.commit() db_session.refresh(page) response = client.put(f"/api/custom-pages/{page.id}", json={ "login_username": "alice@example.test", }) assert response.status_code == 200 assert response.json()["login_autofill_enabled"] is False def test_update_page_respects_explicit_autofill_disable(client, db_session): page = CustomPage( name="Login page", url="https://example.test/login", access_mode="remote_browser", login_username="alice", login_password="secret", login_autofill_enabled=False, ) db_session.add(page) db_session.commit() db_session.refresh(page) response = client.put(f"/api/custom-pages/{page.id}", json={ "login_username": "alice@example.test", "login_autofill_enabled": False, }) assert response.status_code == 200 assert response.json()["login_autofill_enabled"] is False def test_custom_page_migration_backfills_autofill_once(monkeypatch): engine = create_engine( "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool, ) monkeypatch.setattr(database_module, "engine", engine) Base.metadata.create_all(bind=engine) with engine.begin() as conn: conn.execute(text("ALTER TABLE custom_pages DROP COLUMN login_autofill_backfilled_at")) conn.execute(text( "INSERT INTO custom_pages " "(name, url, icon, sort_order, enabled, use_proxy, access_mode, login_username, login_password, login_autofill_enabled, created_at, updated_at) " "VALUES ('Login page', 'https://example.test/login', 'Link', 0, 1, 0, 'remote_browser', 'alice', 'secret', 0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)" )) database_module._migrate_custom_pages() with engine.begin() as conn: row = conn.execute(text( "SELECT login_autofill_enabled, login_autofill_backfilled_at FROM custom_pages WHERE name = 'Login page'" )).one() assert row.login_autofill_enabled == 1 assert row.login_autofill_backfilled_at is not None conn.execute(text("UPDATE custom_pages SET login_autofill_enabled = 0")) database_module._migrate_custom_pages() with engine.begin() as conn: row = conn.execute(text("SELECT login_autofill_enabled FROM custom_pages WHERE name = 'Login page'")).one() assert row.login_autofill_enabled == 0