"""Tests for Spotify PKCE and token handling.""" import asyncio import base64 import hashlib import time import httpx2 from app.adapters.spotify.auth import ( TokenSet, derive_code_challenge, refresh_access_token, ) def test_code_challenge_is_unpadded_base64url_sha256() -> None: verifier = "a-fixed-code-verifier" expected = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()) challenge = derive_code_challenge(verifier) assert challenge == expected.rstrip(b"=").decode() assert "=" not in challenge def test_refresh_keeps_existing_refresh_token_when_omitted() -> None: async def run() -> None: async def handler(request: httpx2.Request) -> httpx2.Response: assert request.url == "https://accounts.spotify.com/api/token" return httpx2.Response(200, json={"access_token": "new", "expires_in": 3600}) tokens = TokenSet("old", "keep-me", time.monotonic() + 3600) async with httpx2.AsyncClient(transport=httpx2.MockTransport(handler)) as http: refreshed = await refresh_access_token(http, client_id="client", tokens=tokens) assert refreshed.access_token == "new" assert refreshed.refresh_token == "keep-me" asyncio.run(run()) def test_token_expiry_uses_sixty_second_skew() -> None: assert TokenSet("access", "refresh", time.monotonic() + 59).is_expired assert not TokenSet("access", "refresh", time.monotonic() + 61).is_expired