feat(astrolabe): add dynamic MCP server configuration for testing
Replace static post-installation configuration with dynamic test-time configuration to support testing multiple MCP server deployments. Changes: - Remove static MCP server URL and OAuth client setup from post-installation - Add configure_astrolabe_for_mcp_server fixture (session-scoped) - Fixture dynamically configures: * Nextcloud system config (mcp_server_url, mcp_server_public_url) * OAuth client creation via occ oidc:create * Client credential storage (astrolabe_client_id, astrolabe_client_secret) - Update existing OAuth tests to use dynamic configuration - Add test_astrolabe_multi_server_integration.py with parametrized tests Benefits: - Test Astrolabe with mcp-oauth, mcp-keycloak, mcp-multi-user-basic - Each test configures for its specific MCP server - No static configuration conflicts between deployments - Cleaner post-installation (37 lines, down from 85) Test Results: - test_astrolabe_configuration_for_different_servers: PASSED (mcp-oauth, mcp-keycloak) - test_astrolabe_reconfiguration: PASSED 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.5
parent
4507359760
commit
cd7ba5685a
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -euox pipefail
|
set -euox pipefail
|
||||||
|
|
||||||
echo "Installing and configuring Astrolabe app for testing..."
|
echo "Installing Astrolabe app for testing..."
|
||||||
|
|
||||||
# Check if development astrolabe app is mounted at /opt/apps/astrolabe
|
# Check if development astrolabe app is mounted at /opt/apps/astrolabe
|
||||||
if [ -d /opt/apps/astrolabe ]; then
|
if [ -d /opt/apps/astrolabe ]; then
|
||||||
@@ -30,55 +30,7 @@ else
|
|||||||
php /var/www/html/occ app:enable astrolabe
|
php /var/www/html/occ app:enable astrolabe
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Configure MCP server URLs in Nextcloud system config
|
echo "✓ Astrolabe app installed successfully"
|
||||||
# - mcp_server_url: Internal URL for PHP app to call MCP server APIs (Docker internal network)
|
echo ""
|
||||||
# - mcp_server_public_url: Public URL for OAuth token audience (what browsers/MCP clients see)
|
echo "Note: MCP server configuration is managed dynamically during tests"
|
||||||
php /var/www/html/occ config:system:set mcp_server_url --value='http://mcp-oauth:8001'
|
echo " to support testing multiple MCP server deployments."
|
||||||
php /var/www/html/occ config:system:set mcp_server_public_url --value='http://localhost:8001'
|
|
||||||
|
|
||||||
# Create OAuth client for Astrolabe app
|
|
||||||
# The resource_url MUST match what the MCP server expects as token audience
|
|
||||||
# This allows tokens from this client to be validated by MCP server's UnifiedTokenVerifier
|
|
||||||
MCP_CLIENT_ID="nextcloudMcpServerUIPublicClient"
|
|
||||||
MCP_RESOURCE_URL="http://localhost:8001"
|
|
||||||
MCP_REDIRECT_URI="http://localhost:8080/apps/astrolabe/oauth/callback"
|
|
||||||
|
|
||||||
echo "Configuring OAuth client for Astrolabe..."
|
|
||||||
|
|
||||||
# Check if client already exists
|
|
||||||
if php /var/www/html/occ oidc:list 2>/dev/null | grep -q "$MCP_CLIENT_ID"; then
|
|
||||||
echo "OAuth client $MCP_CLIENT_ID already exists, removing to recreate with correct settings..."
|
|
||||||
php /var/www/html/occ oidc:remove "$MCP_CLIENT_ID" || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create OAuth client with correct resource_url for MCP server audience
|
|
||||||
echo "Creating OAuth confidential client with resource_url=$MCP_RESOURCE_URL"
|
|
||||||
CLIENT_OUTPUT=$(php /var/www/html/occ oidc:create \
|
|
||||||
"Astrolabe" \
|
|
||||||
"$MCP_REDIRECT_URI" \
|
|
||||||
--client_id="$MCP_CLIENT_ID" \
|
|
||||||
--type=confidential \
|
|
||||||
--flow=code \
|
|
||||||
--token_type=jwt \
|
|
||||||
--resource_url="$MCP_RESOURCE_URL" \
|
|
||||||
--allowed_scopes="openid profile email offline_access notes:read notes:write calendar:read calendar:write contacts:read contacts:write cookbook:read cookbook:write deck:read deck:write tables:read tables:write files:read files:write")
|
|
||||||
|
|
||||||
echo "$CLIENT_OUTPUT"
|
|
||||||
|
|
||||||
# Extract client_secret from JSON output
|
|
||||||
CLIENT_SECRET=$(echo "$CLIENT_OUTPUT" | php -r 'echo json_decode(file_get_contents("php://stdin"), true)["client_secret"] ?? "";')
|
|
||||||
|
|
||||||
if [ -n "$CLIENT_SECRET" ]; then
|
|
||||||
echo "Configuring Astrolabe client secret in system config..."
|
|
||||||
php /var/www/html/occ config:system:set astrolabe_client_secret --value="$CLIENT_SECRET"
|
|
||||||
echo "✓ Client secret configured: ${CLIENT_SECRET:0:8}..."
|
|
||||||
else
|
|
||||||
echo "⚠ Warning: Could not extract client_secret from OIDC client creation"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Configure OAuth client ID in system config
|
|
||||||
echo "Configuring Astrolabe client ID in system config..."
|
|
||||||
php /var/www/html/occ config:system:set astrolabe_client_id --value="$MCP_CLIENT_ID"
|
|
||||||
echo "✓ Client ID configured: $MCP_CLIENT_ID"
|
|
||||||
|
|
||||||
echo "Astrolabe app installed and configured successfully"
|
|
||||||
|
|||||||
+228
-2
@@ -114,6 +114,7 @@ async def create_mcp_client_session(
|
|||||||
client_name: str = "MCP",
|
client_name: str = "MCP",
|
||||||
elicitation_callback: Any = None,
|
elicitation_callback: Any = None,
|
||||||
sampling_callback: Any = None,
|
sampling_callback: Any = None,
|
||||||
|
headers: dict[str, str] | None = None,
|
||||||
) -> AsyncGenerator[ClientSession, Any]:
|
) -> AsyncGenerator[ClientSession, Any]:
|
||||||
"""
|
"""
|
||||||
Factory function to create an MCP client session with proper lifecycle management.
|
Factory function to create an MCP client session with proper lifecycle management.
|
||||||
@@ -135,6 +136,8 @@ async def create_mcp_client_session(
|
|||||||
Should match signature: async def callback(context: RequestContext, params: ElicitRequestParams) -> ElicitResult | ErrorData
|
Should match signature: async def callback(context: RequestContext, params: ElicitRequestParams) -> ElicitResult | ErrorData
|
||||||
sampling_callback: Optional callback for handling sampling (LLM generation) requests.
|
sampling_callback: Optional callback for handling sampling (LLM generation) requests.
|
||||||
Should match signature: async def callback(context: RequestContext, params: CreateMessageRequestParams) -> CreateMessageResult | ErrorData
|
Should match signature: async def callback(context: RequestContext, params: CreateMessageRequestParams) -> CreateMessageResult | ErrorData
|
||||||
|
headers: Optional custom headers (e.g., for BasicAuth). If both headers and token are provided,
|
||||||
|
custom headers take precedence.
|
||||||
|
|
||||||
Yields:
|
Yields:
|
||||||
Initialized MCP ClientSession
|
Initialized MCP ClientSession
|
||||||
@@ -147,8 +150,9 @@ async def create_mcp_client_session(
|
|||||||
"""
|
"""
|
||||||
logger.info(f"Creating Streamable HTTP client for {client_name}")
|
logger.info(f"Creating Streamable HTTP client for {client_name}")
|
||||||
|
|
||||||
# Prepare headers with OAuth token if provided
|
# Prepare headers - custom headers take precedence over token-based auth
|
||||||
headers = {"Authorization": f"Bearer {token}"} if token else None
|
if headers is None:
|
||||||
|
headers = {"Authorization": f"Bearer {token}"} if token else None
|
||||||
|
|
||||||
# Use native async with - Python ensures LIFO cleanup
|
# Use native async with - Python ensures LIFO cleanup
|
||||||
# Cleanup order will be: ClientSession.__aexit__ -> streamablehttp_client.__aexit__
|
# Cleanup order will be: ClientSession.__aexit__ -> streamablehttp_client.__aexit__
|
||||||
@@ -240,6 +244,32 @@ async def nc_mcp_oauth_client(
|
|||||||
yield session
|
yield session
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
async def nc_mcp_basic_auth_client(
|
||||||
|
anyio_backend,
|
||||||
|
) -> AsyncGenerator[ClientSession, Any]:
|
||||||
|
"""
|
||||||
|
Fixture to create an MCP client session with BasicAuth credentials.
|
||||||
|
Connects to the multi-user BasicAuth MCP server on port 8003 with ENABLE_MULTI_USER_BASIC_AUTH=true.
|
||||||
|
|
||||||
|
Uses BasicAuth credentials for multi-user pass-through mode (ADR-020).
|
||||||
|
Credentials are passed in Authorization header and forwarded to Nextcloud APIs.
|
||||||
|
|
||||||
|
Uses anyio pytest plugin for proper async fixture handling.
|
||||||
|
"""
|
||||||
|
import base64
|
||||||
|
|
||||||
|
credentials = base64.b64encode(b"admin:admin").decode("utf-8")
|
||||||
|
auth_header = f"Basic {credentials}"
|
||||||
|
|
||||||
|
async for session in create_mcp_client_session(
|
||||||
|
url="http://localhost:8003/mcp",
|
||||||
|
headers={"Authorization": auth_header},
|
||||||
|
client_name="BasicAuth MCP (Multi-User)",
|
||||||
|
):
|
||||||
|
yield session
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
async def nc_mcp_oauth_jwt_client(
|
async def nc_mcp_oauth_jwt_client(
|
||||||
anyio_backend,
|
anyio_backend,
|
||||||
@@ -3187,3 +3217,199 @@ async def nc_mcp_keycloak_client_no_custom_scopes(
|
|||||||
client_name="Keycloak No Custom Scopes MCP",
|
client_name="Keycloak No Custom Scopes MCP",
|
||||||
):
|
):
|
||||||
yield session
|
yield session
|
||||||
|
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# Astrolabe Dynamic Configuration Fixtures
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
async def configure_astrolabe_for_mcp_server(nc_client):
|
||||||
|
"""Configure Astrolabe app to connect to a specific MCP server.
|
||||||
|
|
||||||
|
This fixture dynamically configures the Astrolabe app's MCP server settings
|
||||||
|
and OAuth client, allowing tests to verify integration with different MCP
|
||||||
|
server deployments (mcp-oauth, mcp-keycloak, mcp-multi-user-basic, etc.).
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
async def test_my_integration(configure_astrolabe_for_mcp_server):
|
||||||
|
await configure_astrolabe_for_mcp_server(
|
||||||
|
mcp_server_internal_url="http://mcp-oauth:8001",
|
||||||
|
mcp_server_public_url="http://localhost:8001"
|
||||||
|
)
|
||||||
|
# ... test Astrolabe integration ...
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nc_client: NextcloudClient fixture for occ command execution
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Async function that accepts:
|
||||||
|
- mcp_server_internal_url: Internal Docker URL for PHP app to call MCP APIs
|
||||||
|
- mcp_server_public_url: Public URL for OAuth token audience validation
|
||||||
|
- client_id: Optional OAuth client ID (default: "nextcloudMcpServerUIPublicClient")
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
async def _configure(
|
||||||
|
mcp_server_internal_url: str,
|
||||||
|
mcp_server_public_url: str,
|
||||||
|
client_id: str = "nextcloudMcpServerUIPublicClient",
|
||||||
|
) -> dict[str, str]:
|
||||||
|
"""Configure Astrolabe for the specified MCP server.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict with client_id and client_secret
|
||||||
|
"""
|
||||||
|
logger.info(
|
||||||
|
f"Configuring Astrolabe for MCP server: {mcp_server_internal_url} (public: {mcp_server_public_url})"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Configure MCP server URLs in Nextcloud system config
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"docker",
|
||||||
|
"compose",
|
||||||
|
"exec",
|
||||||
|
"-T",
|
||||||
|
"app",
|
||||||
|
"php",
|
||||||
|
"/var/www/html/occ",
|
||||||
|
"config:system:set",
|
||||||
|
"mcp_server_url",
|
||||||
|
"--value",
|
||||||
|
mcp_server_internal_url,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"docker",
|
||||||
|
"compose",
|
||||||
|
"exec",
|
||||||
|
"-T",
|
||||||
|
"app",
|
||||||
|
"php",
|
||||||
|
"/var/www/html/occ",
|
||||||
|
"config:system:set",
|
||||||
|
"mcp_server_public_url",
|
||||||
|
"--value",
|
||||||
|
mcp_server_public_url,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info("✓ MCP server URLs configured")
|
||||||
|
|
||||||
|
# Remove existing OAuth client if it exists
|
||||||
|
try:
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"docker",
|
||||||
|
"compose",
|
||||||
|
"exec",
|
||||||
|
"-T",
|
||||||
|
"app",
|
||||||
|
"php",
|
||||||
|
"/var/www/html/occ",
|
||||||
|
"oidc:remove",
|
||||||
|
client_id,
|
||||||
|
],
|
||||||
|
check=False, # Don't fail if client doesn't exist
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
logger.info(f"Removed existing OAuth client: {client_id}")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Create OAuth client for Astrolabe
|
||||||
|
redirect_uri = "http://localhost:8080/apps/astrolabe/oauth/callback"
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
[
|
||||||
|
"docker",
|
||||||
|
"compose",
|
||||||
|
"exec",
|
||||||
|
"-T",
|
||||||
|
"app",
|
||||||
|
"php",
|
||||||
|
"/var/www/html/occ",
|
||||||
|
"oidc:create",
|
||||||
|
"Astrolabe",
|
||||||
|
redirect_uri,
|
||||||
|
"--client_id",
|
||||||
|
client_id,
|
||||||
|
"--type",
|
||||||
|
"confidential",
|
||||||
|
"--flow",
|
||||||
|
"code",
|
||||||
|
"--token_type",
|
||||||
|
"jwt",
|
||||||
|
"--resource_url",
|
||||||
|
mcp_server_public_url,
|
||||||
|
"--allowed_scopes",
|
||||||
|
"openid profile email offline_access notes:read notes:write calendar:read calendar:write contacts:read contacts:write cookbook:read cookbook:write deck:read deck:write tables:read tables:write files:read files:write",
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Parse client_secret from JSON output
|
||||||
|
client_output = json.loads(result.stdout.strip())
|
||||||
|
client_secret = client_output.get("client_secret")
|
||||||
|
|
||||||
|
if not client_secret:
|
||||||
|
raise ValueError(
|
||||||
|
"Failed to extract client_secret from OAuth client creation"
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(f"✓ OAuth client created: {client_id}")
|
||||||
|
|
||||||
|
# Store client credentials in Nextcloud system config
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"docker",
|
||||||
|
"compose",
|
||||||
|
"exec",
|
||||||
|
"-T",
|
||||||
|
"app",
|
||||||
|
"php",
|
||||||
|
"/var/www/html/occ",
|
||||||
|
"config:system:set",
|
||||||
|
"astrolabe_client_id",
|
||||||
|
"--value",
|
||||||
|
client_id,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"docker",
|
||||||
|
"compose",
|
||||||
|
"exec",
|
||||||
|
"-T",
|
||||||
|
"app",
|
||||||
|
"php",
|
||||||
|
"/var/www/html/occ",
|
||||||
|
"config:system:set",
|
||||||
|
"astrolabe_client_secret",
|
||||||
|
"--value",
|
||||||
|
client_secret,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info("✓ Client credentials stored in system config")
|
||||||
|
logger.info(f"Astrolabe configured for MCP server: {mcp_server_public_url}")
|
||||||
|
|
||||||
|
return {"client_id": client_id, "client_secret": client_secret}
|
||||||
|
|
||||||
|
return _configure
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
"""Test Astrolabe integration with multiple MCP server deployments.
|
||||||
|
|
||||||
|
This test suite verifies that the Astrolabe app can be dynamically configured
|
||||||
|
to connect to different MCP server deployments (mcp-oauth, mcp-keycloak, etc.).
|
||||||
|
|
||||||
|
The configuration is managed dynamically during tests using the
|
||||||
|
configure_astrolabe_for_mcp_server fixture, which allows testing multiple
|
||||||
|
deployment scenarios without requiring static post-installation configuration.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
pytestmark = [pytest.mark.integration, pytest.mark.oauth]
|
||||||
|
|
||||||
|
|
||||||
|
class TestAstrolabeMultiServerIntegration:
|
||||||
|
"""Test suite for Astrolabe integration with multiple MCP servers."""
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"mcp_server_config",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "mcp-oauth",
|
||||||
|
"internal_url": "http://mcp-oauth:8001",
|
||||||
|
"public_url": "http://localhost:8001",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mcp-keycloak",
|
||||||
|
"internal_url": "http://mcp-keycloak:8002",
|
||||||
|
"public_url": "http://localhost:8002",
|
||||||
|
},
|
||||||
|
# Add more MCP server configurations as needed:
|
||||||
|
# {
|
||||||
|
# "name": "mcp-multi-user-basic",
|
||||||
|
# "internal_url": "http://mcp-multi-user-basic:8000",
|
||||||
|
# "public_url": "http://localhost:8003",
|
||||||
|
# },
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_astrolabe_configuration_for_different_servers(
|
||||||
|
self, configure_astrolabe_for_mcp_server, mcp_server_config
|
||||||
|
):
|
||||||
|
"""Test that Astrolabe can be configured for different MCP servers.
|
||||||
|
|
||||||
|
This test verifies that:
|
||||||
|
1. The configure_astrolabe_for_mcp_server fixture successfully configures
|
||||||
|
the Astrolabe app for different MCP server endpoints
|
||||||
|
2. OAuth client credentials are properly generated and stored
|
||||||
|
3. The configuration can be dynamically changed between tests
|
||||||
|
"""
|
||||||
|
logger.info(f"Configuring Astrolabe for {mcp_server_config['name']}...")
|
||||||
|
|
||||||
|
# Configure Astrolabe for the specific MCP server
|
||||||
|
credentials = await configure_astrolabe_for_mcp_server(
|
||||||
|
mcp_server_internal_url=mcp_server_config["internal_url"],
|
||||||
|
mcp_server_public_url=mcp_server_config["public_url"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verify credentials were returned
|
||||||
|
assert "client_id" in credentials
|
||||||
|
assert "client_secret" in credentials
|
||||||
|
assert credentials["client_id"] == "nextcloudMcpServerUIPublicClient"
|
||||||
|
assert len(credentials["client_secret"]) > 0
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"✓ Astrolabe successfully configured for {mcp_server_config['name']}"
|
||||||
|
)
|
||||||
|
logger.info(f" Internal URL: {mcp_server_config['internal_url']}")
|
||||||
|
logger.info(f" Public URL: {mcp_server_config['public_url']}")
|
||||||
|
logger.info(f" Client ID: {credentials['client_id']}")
|
||||||
|
logger.info(f" Client Secret: {credentials['client_secret'][:8]}...")
|
||||||
|
|
||||||
|
async def test_astrolabe_reconfiguration(self, configure_astrolabe_for_mcp_server):
|
||||||
|
"""Test that Astrolabe can be reconfigured multiple times in the same session.
|
||||||
|
|
||||||
|
This verifies that the OAuth client can be recreated with different
|
||||||
|
settings without conflicts.
|
||||||
|
"""
|
||||||
|
# First configuration: mcp-oauth
|
||||||
|
logger.info("First configuration: mcp-oauth")
|
||||||
|
credentials1 = await configure_astrolabe_for_mcp_server(
|
||||||
|
mcp_server_internal_url="http://mcp-oauth:8001",
|
||||||
|
mcp_server_public_url="http://localhost:8001",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert credentials1["client_id"] == "nextcloudMcpServerUIPublicClient"
|
||||||
|
|
||||||
|
# Second configuration: mcp-keycloak (reconfiguration)
|
||||||
|
logger.info("Second configuration: mcp-keycloak (reconfiguration)")
|
||||||
|
credentials2 = await configure_astrolabe_for_mcp_server(
|
||||||
|
mcp_server_internal_url="http://mcp-keycloak:8002",
|
||||||
|
mcp_server_public_url="http://localhost:8002",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert credentials2["client_id"] == "nextcloudMcpServerUIPublicClient"
|
||||||
|
|
||||||
|
# Client secrets should be different (new client created)
|
||||||
|
assert credentials1["client_secret"] != credentials2["client_secret"]
|
||||||
|
|
||||||
|
logger.info("✓ Astrolabe successfully reconfigured without conflicts")
|
||||||
@@ -10,8 +10,14 @@ logger = logging.getLogger(__name__)
|
|||||||
pytestmark = [pytest.mark.integration, pytest.mark.oauth]
|
pytestmark = [pytest.mark.integration, pytest.mark.oauth]
|
||||||
|
|
||||||
|
|
||||||
async def test_capture_settings_page(browser):
|
async def test_capture_settings_page(browser, configure_astrolabe_for_mcp_server):
|
||||||
"""Capture what's actually rendered on the personal settings page."""
|
"""Capture what's actually rendered on the personal settings page."""
|
||||||
|
# Configure Astrolabe for mcp-oauth server
|
||||||
|
await configure_astrolabe_for_mcp_server(
|
||||||
|
mcp_server_internal_url="http://mcp-oauth:8001",
|
||||||
|
mcp_server_public_url="http://localhost:8001",
|
||||||
|
)
|
||||||
|
|
||||||
nextcloud_host = os.getenv("NEXTCLOUD_HOST", "http://localhost:8080")
|
nextcloud_host = os.getenv("NEXTCLOUD_HOST", "http://localhost:8080")
|
||||||
username = os.getenv("NEXTCLOUD_USERNAME", "admin")
|
username = os.getenv("NEXTCLOUD_USERNAME", "admin")
|
||||||
password = os.getenv("NEXTCLOUD_PASSWORD", "admin")
|
password = os.getenv("NEXTCLOUD_PASSWORD", "admin")
|
||||||
|
|||||||
@@ -44,14 +44,32 @@ async def nc_admin_http_client(nextcloud_credentials):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
async def authorized_nc_session(browser, nextcloud_credentials):
|
async def configure_astrolabe_for_tests(configure_astrolabe_for_mcp_server):
|
||||||
|
"""Configure Astrolabe to connect to mcp-oauth server before running tests.
|
||||||
|
|
||||||
|
This module-scoped fixture ensures Astrolabe is properly configured
|
||||||
|
for the mcp-oauth server (http://localhost:8001) before any tests run.
|
||||||
|
"""
|
||||||
|
logger.info("Configuring Astrolabe for mcp-oauth server...")
|
||||||
|
await configure_astrolabe_for_mcp_server(
|
||||||
|
mcp_server_internal_url="http://mcp-oauth:8001",
|
||||||
|
mcp_server_public_url="http://localhost:8001",
|
||||||
|
)
|
||||||
|
logger.info("✓ Astrolabe configured for mcp-oauth server")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
async def authorized_nc_session(
|
||||||
|
browser, nextcloud_credentials, configure_astrolabe_for_tests
|
||||||
|
):
|
||||||
"""Module-scoped fixture that logs in and authorizes the NC PHP app once.
|
"""Module-scoped fixture that logs in and authorizes the NC PHP app once.
|
||||||
|
|
||||||
This fixture:
|
This fixture:
|
||||||
1. Creates a browser context
|
1. Configures Astrolabe for mcp-oauth server (via configure_astrolabe_for_tests)
|
||||||
2. Logs in to Nextcloud
|
2. Creates a browser context
|
||||||
3. Authorizes the MCP Server UI app (if not already authorized)
|
3. Logs in to Nextcloud
|
||||||
4. Returns the page for use in all tests
|
4. Authorizes the MCP Server UI app (if not already authorized)
|
||||||
|
5. Returns the page for use in all tests
|
||||||
|
|
||||||
The authorization is done once and reused for all tests in this module.
|
The authorization is done once and reused for all tests in this module.
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user