Skip to content

Commit 95b44fb

Browse files
tests: use inline_snapshot.Is on parametrized test (#945)
Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com>
1 parent b8cb367 commit 95b44fb

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

tests/client/test_auth.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import httpx
88
import pytest
9+
from inline_snapshot import Is, snapshot
910
from pydantic import AnyHttpUrl, AnyUrl
1011

1112
from mcp.client.auth import OAuthClientProvider, PKCEParameters
@@ -580,3 +581,82 @@ async def test_auth_flow_with_valid_tokens(self, oauth_provider, mock_storage, v
580581
await auth_flow.asend(response)
581582
except StopAsyncIteration:
582583
pass # Expected
584+
585+
586+
@pytest.mark.parametrize(
587+
(
588+
"issuer_url",
589+
"service_documentation_url",
590+
"authorization_endpoint",
591+
"token_endpoint",
592+
"registration_endpoint",
593+
"revocation_endpoint",
594+
),
595+
(
596+
# Pydantic's AnyUrl incorrectly adds trailing slash to base URLs
597+
# This is being fixed in https://github.com/pydantic/pydantic-core/pull/1719 (Pydantic 2.12+)
598+
pytest.param(
599+
"https://auth.example.com",
600+
"https://auth.example.com/docs",
601+
"https://auth.example.com/authorize",
602+
"https://auth.example.com/token",
603+
"https://auth.example.com/register",
604+
"https://auth.example.com/revoke",
605+
id="simple-url",
606+
marks=pytest.mark.xfail(
607+
reason="Pydantic AnyUrl adds trailing slash to base URLs - fixed in Pydantic 2.12+"
608+
),
609+
),
610+
pytest.param(
611+
"https://auth.example.com/",
612+
"https://auth.example.com/docs",
613+
"https://auth.example.com/authorize",
614+
"https://auth.example.com/token",
615+
"https://auth.example.com/register",
616+
"https://auth.example.com/revoke",
617+
id="with-trailing-slash",
618+
),
619+
pytest.param(
620+
"https://auth.example.com/v1/mcp",
621+
"https://auth.example.com/v1/mcp/docs",
622+
"https://auth.example.com/v1/mcp/authorize",
623+
"https://auth.example.com/v1/mcp/token",
624+
"https://auth.example.com/v1/mcp/register",
625+
"https://auth.example.com/v1/mcp/revoke",
626+
id="with-path-param",
627+
),
628+
),
629+
)
630+
def test_build_metadata(
631+
issuer_url: str,
632+
service_documentation_url: str,
633+
authorization_endpoint: str,
634+
token_endpoint: str,
635+
registration_endpoint: str,
636+
revocation_endpoint: str,
637+
):
638+
from mcp.server.auth.routes import build_metadata
639+
from mcp.server.auth.settings import ClientRegistrationOptions, RevocationOptions
640+
641+
metadata = build_metadata(
642+
issuer_url=AnyHttpUrl(issuer_url),
643+
service_documentation_url=AnyHttpUrl(service_documentation_url),
644+
client_registration_options=ClientRegistrationOptions(enabled=True, valid_scopes=["read", "write", "admin"]),
645+
revocation_options=RevocationOptions(enabled=True),
646+
)
647+
648+
assert metadata.model_dump(exclude_defaults=True, mode="json") == snapshot(
649+
{
650+
"issuer": Is(issuer_url),
651+
"authorization_endpoint": Is(authorization_endpoint),
652+
"token_endpoint": Is(token_endpoint),
653+
"registration_endpoint": Is(registration_endpoint),
654+
"scopes_supported": ["read", "write", "admin"],
655+
"grant_types_supported": ["authorization_code", "refresh_token"],
656+
"token_endpoint_auth_methods_supported": ["client_secret_post"],
657+
"service_documentation": Is(service_documentation_url),
658+
"revocation_endpoint": Is(revocation_endpoint),
659+
"revocation_endpoint_auth_methods_supported": ["client_secret_post"],
660+
"code_challenge_methods_supported": ["S256"],
661+
}
662+
)

0 commit comments

Comments
 (0)