Files
chat/tests/test_first_run.py
2026-04-26 14:33:28 -04:00

147 lines
4.6 KiB
Python

from __future__ import annotations
import pytest
from fastapi.testclient import TestClient
from chat.app import app
from chat.db.connection import open_db
from chat.eventlog.log import append_event
from chat.eventlog.projector import project
@pytest.fixture
def client(tmp_path, monkeypatch):
cfg = tmp_path / "config.toml"
cfg.write_text('featherless_api_key = "test"\n')
monkeypatch.setenv("CHAT_CONFIG_PATH", str(cfg))
db = tmp_path / "test.db"
monkeypatch.setenv("CHAT_DB_PATH", str(db))
with TestClient(app) as c:
if hasattr(app.state, "background_worker"):
app.state.background_worker.enabled = False
yield c
def test_root_redirects_to_settings_when_no_you(client):
response = client.get("/", follow_redirects=False)
assert response.status_code == 303
assert response.headers["location"] == "/settings"
def test_chats_redirects_to_settings_when_no_you(client):
response = client.get("/chats", follow_redirects=False)
assert response.status_code == 303
assert response.headers["location"] == "/settings"
def test_redirects_to_bots_new_when_you_exists_but_no_bots(client, tmp_path):
with open_db(tmp_path / "test.db") as conn:
append_event(
conn,
kind="you_authored",
payload={
"name": "Me",
"pronouns": "they/them",
"persona": "engineer",
},
)
project(conn)
response = client.get("/chats", follow_redirects=False)
assert response.status_code == 303
assert response.headers["location"] == "/bots/new"
def test_root_redirects_to_bots_new_when_you_exists_but_no_bots(client, tmp_path):
with open_db(tmp_path / "test.db") as conn:
append_event(
conn,
kind="you_authored",
payload={
"name": "Me",
"pronouns": "they/them",
"persona": "engineer",
},
)
project(conn)
response = client.get("/", follow_redirects=False)
assert response.status_code == 303
assert response.headers["location"] == "/bots/new"
def test_no_redirect_when_setup_complete(client, tmp_path):
with open_db(tmp_path / "test.db") as conn:
append_event(
conn,
kind="you_authored",
payload={
"name": "Me",
"pronouns": "they/them",
"persona": "engineer",
},
)
append_event(
conn,
kind="bot_authored",
payload={
"id": "bot_a",
"name": "BotA",
"persona": "...",
"voice_samples": [],
"traits": [],
"backstory": "",
"initial_relationship_to_you": "",
"kickoff_prose": "",
},
)
project(conn)
response = client.get("/chats", follow_redirects=False)
# /chats page renders normally (200) instead of redirecting.
assert response.status_code == 200
def test_settings_page_accessible_without_you(client):
"""Don't redirect FROM /settings — user needs to fill it out."""
response = client.get("/settings", follow_redirects=False)
assert response.status_code == 200
def test_bots_new_accessible_without_redirect(client, tmp_path):
with open_db(tmp_path / "test.db") as conn:
append_event(
conn,
kind="you_authored",
payload={"name": "Me", "pronouns": "", "persona": ""},
)
project(conn)
response = client.get("/bots/new", follow_redirects=False)
assert response.status_code == 200
def test_bots_list_accessible_without_redirect_when_empty(client, tmp_path):
"""The bot list page itself should never redirect — even when empty."""
with open_db(tmp_path / "test.db") as conn:
append_event(
conn,
kind="you_authored",
payload={"name": "Me", "pronouns": "", "persona": ""},
)
project(conn)
response = client.get("/bots", follow_redirects=False)
assert response.status_code == 200
def test_post_to_settings_not_redirected(client):
"""POST should bypass middleware — it's a write, not a landing nav."""
response = client.post(
"/settings",
data={"name": "Me", "pronouns": "", "persona": ""},
follow_redirects=False,
)
# Settings POST returns 200 with the saved page (no HTTPException raised).
assert response.status_code == 200
def test_health_endpoint_not_redirected(client):
response = client.get("/health", follow_redirects=False)
assert response.status_code == 200