Files
mcp-nextcloud/tests/integration/test_astrolabe_settings_buttons.py
Chris CoutinhoandClaude Opus 4.8 4ed228613e test(astrolabe): migrate suite to session-JWT auth model
Astrolabe was refactored to mint session-derived JWTs (TokenGenerationRequest
Event) and a one-click background-indexing opt-in, dropping the OAuth
authorize/callback/refresh surface. Bump the submodule and bring the test
suite in line:

- New test_astrolabe_session_jwt_search.py: a logged-in user searches via the
  minted JWT with no provisioning (replaces the obsolete login_flow_provisioning
  OAuth-authorize test; token_refresh test deleted — refresh flow is gone).
- settings_buttons: assert the new revoke endpoint + that oauth/disconnect is
  gone (404).
- multi_user_background_sync / plotly / chunk_context: drop the OAuth authorize
  step; provision via the one-click "Enable background indexing" button
  (#mcp-enable-background-button -> #mcp-revoke-background-button) instead of
  generating + pasting an app password.
- docker-compose.yml: mount the astrolabe submodule into the app container.
- third_party/astrolabe: bump to the one-click opt-in commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 23:06:27 +02:00

64 lines
2.5 KiB
Python

"""Integration tests for Astrolabe personal-settings background-sync endpoints.
Cross-system interface test. The astrolabe app (installed by
app-hooks/post-installation/20-install-astrolabe-app.sh; source in
./third_party/astrolabe) was refactored to session-minted JWTs — the old
per-user OAuth flow and its ``/apps/astrolabe/oauth/disconnect`` route are
gone. Background indexing is now an app-password opt-in with a single revoke
endpoint.
These tests assert the *current* HTTP surface of the settings page:
- the revoke endpoint exists and is auth-gated
(POST /apps/astrolabe/api/v1/background-sync/credentials/revoke)
- the obsolete OAuth disconnect route is gone (404)
- the personal settings page route resolves
"""
import httpx
import pytest
pytestmark = pytest.mark.integration
NEXTCLOUD_URL = "http://localhost:8080"
ASTROLABE = f"{NEXTCLOUD_URL}/apps/astrolabe"
# Auth failures (no session) surface as 401 or a login redirect.
_UNAUTH = {401, 302, 303, 307, 308}
async def test_revoke_endpoint_requires_auth():
"""The background-sync revoke endpoint exists and rejects anonymous calls."""
async with httpx.AsyncClient(follow_redirects=False) as client:
resp = await client.post(
f"{ASTROLABE}/api/v1/background-sync/credentials/revoke",
headers={"OCS-APIRequest": "true"},
)
# Must NOT be 404 — the route must exist — and must be auth-gated.
assert resp.status_code != 404, "revoke route missing"
assert resp.status_code in _UNAUTH, (
f"expected auth rejection, got {resp.status_code}"
)
async def test_obsolete_oauth_disconnect_route_removed():
"""The pre-refactor OAuth disconnect route must no longer exist.
Regression guard for the auth refactor: ``/apps/astrolabe/oauth/disconnect``
(and the rest of the OAuth authorize/callback/disconnect surface) was
removed in favour of session-minted JWTs.
"""
async with httpx.AsyncClient(follow_redirects=False) as client:
resp = await client.post(f"{ASTROLABE}/oauth/disconnect")
assert resp.status_code == 404, (
f"obsolete oauth/disconnect route still resolves ({resp.status_code})"
)
async def test_settings_page_route_resolves():
"""The personal settings page route exists (auth-gated when no session)."""
async with httpx.AsyncClient(follow_redirects=False) as client:
resp = await client.get(f"{NEXTCLOUD_URL}/settings/user/astrolabe")
assert resp.status_code in ({200} | _UNAUTH), (
f"unexpected status for settings page: {resp.status_code}"
)