"""Integration tests for the public runtime config endpoint. Covers GET /api/v1/config/public and the SELF_SERVE_ENABLED interaction with the existing /auth/register invite-code gate. """ from __future__ import annotations import pytest from httpx import AsyncClient from app.core.config import settings class TestConfigPublic: """GET /api/v1/config/public — anonymous, no auth.""" @pytest.mark.asyncio async def test_get_config_public_returns_self_serve_flag( self, client: AsyncClient, monkeypatch: pytest.MonkeyPatch ): """Endpoint reflects the current SELF_SERVE_ENABLED setting and the configured OAuth providers, with no auth required.""" # Default-off: SELF_SERVE_ENABLED is False unless explicitly set. monkeypatch.setattr(settings, "SELF_SERVE_ENABLED", False) monkeypatch.setattr(settings, "GOOGLE_CLIENT_ID", None) monkeypatch.setattr(settings, "MS_CLIENT_ID", None) response = await client.get("/api/v1/config/public") assert response.status_code == 200 body = response.json() assert body == {"self_serve_enabled": False, "oauth_providers": []} # Flip it on, with both OAuth providers configured. monkeypatch.setattr(settings, "SELF_SERVE_ENABLED", True) monkeypatch.setattr(settings, "GOOGLE_CLIENT_ID", "google-test-id") monkeypatch.setattr(settings, "MS_CLIENT_ID", "ms-test-id") response = await client.get("/api/v1/config/public") assert response.status_code == 200 body = response.json() assert body["self_serve_enabled"] is True assert body["oauth_providers"] == ["google", "microsoft"] # Only Microsoft configured. monkeypatch.setattr(settings, "GOOGLE_CLIENT_ID", None) monkeypatch.setattr(settings, "MS_CLIENT_ID", "ms-test-id") response = await client.get("/api/v1/config/public") assert response.status_code == 200 assert response.json()["oauth_providers"] == ["microsoft"] class TestRegisterInviteCodeGate: """Regression + new-behavior tests for /auth/register vs SELF_SERVE_ENABLED.""" @pytest.mark.asyncio async def test_register_invite_code_required_when_self_serve_disabled( self, client: AsyncClient, monkeypatch: pytest.MonkeyPatch ): """Pre-self-serve behavior: REQUIRE_INVITE_CODE=True without an invite code (and no account-invite) must still 400.""" monkeypatch.setattr(settings, "REQUIRE_INVITE_CODE", True) monkeypatch.setattr(settings, "SELF_SERVE_ENABLED", False) response = await client.post( "/api/v1/auth/register", json={ "email": "no-invite@example.com", "password": "SecurePass123!", "name": "No Invite", }, ) assert response.status_code == 400 assert "invite code is required" in response.json()["detail"].lower() @pytest.mark.asyncio async def test_register_invite_code_optional_when_self_serve_enabled( self, client: AsyncClient, monkeypatch: pytest.MonkeyPatch ): """Self-serve on: registration succeeds with no invite code even when REQUIRE_INVITE_CODE is True. The user, personal account, and a Pro trial subscription are all created.""" monkeypatch.setattr(settings, "REQUIRE_INVITE_CODE", True) monkeypatch.setattr(settings, "SELF_SERVE_ENABLED", True) response = await client.post( "/api/v1/auth/register", json={ "email": "self-serve@example.com", "password": "SecurePass123!", "name": "Self Serve", }, ) assert response.status_code == 201, response.text body = response.json() assert body["email"] == "self-serve@example.com" assert body["account_role"] == "owner" assert "account_id" in body