7adc7c00ab
Enable managed remote browser custom pages with login autofill and add website sync workflows so external admin surfaces can be handled inside SmartUp. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
172 lines
5.5 KiB
Python
172 lines
5.5 KiB
Python
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
|