11from __future__ import annotations
22
3+ from collections .abc import Callable
4+
35import httpx
46import pytest
5- from vercel import oidc as vercel_oidc
67
78import ai
9+ from ai .providers .ai_gateway import provider as gateway_provider
810from ai .providers .ai_gateway .client import errors
911
1012
13+ def _set_oidc_token (
14+ monkeypatch : pytest .MonkeyPatch ,
15+ get_token : Callable [[], str ],
16+ ) -> None :
17+ monkeypatch .setattr (
18+ gateway_provider ,
19+ "_get_vercel_oidc_token_impl" ,
20+ get_token ,
21+ )
22+
23+
24+ def _fail_oidc_import (monkeypatch : pytest .MonkeyPatch ) -> None :
25+ monkeypatch .setattr (
26+ gateway_provider ,
27+ "_get_vercel_oidc_token_impl" ,
28+ lambda : pytest .fail ("OIDC should not be used when an API key is set" ),
29+ )
30+
31+
1132async def test_list_models_gets_config_with_gateway_headers_and_sorts_ids () -> (
1233 None
1334):
@@ -79,11 +100,7 @@ async def test_list_models_uses_oidc_on_vercel_when_no_api_key(
79100) -> None :
80101 monkeypatch .delenv ("AI_GATEWAY_API_KEY" , raising = False )
81102 monkeypatch .setenv ("VERCEL" , "1" )
82- monkeypatch .setattr (
83- vercel_oidc ,
84- "get_vercel_oidc_token" ,
85- lambda : "oidc-test-token" ,
86- )
103+ _set_oidc_token (monkeypatch , lambda : "oidc-test-token" )
87104 captured_headers : dict [str , str ] = {}
88105
89106 def _handler (request : httpx .Request ) -> httpx .Response :
@@ -115,11 +132,7 @@ async def test_list_models_uses_oidc_token_env_without_vercel_flag(
115132 monkeypatch .delenv ("AI_GATEWAY_API_KEY" , raising = False )
116133 monkeypatch .delenv ("VERCEL" , raising = False )
117134 monkeypatch .setenv ("VERCEL_OIDC_TOKEN" , "pulled-oidc-token" )
118- monkeypatch .setattr (
119- vercel_oidc ,
120- "get_vercel_oidc_token" ,
121- lambda : "pulled-oidc-token" ,
122- )
135+ _set_oidc_token (monkeypatch , lambda : "pulled-oidc-token" )
123136 captured_headers : dict [str , str ] = {}
124137
125138 def _handler (request : httpx .Request ) -> httpx .Response :
@@ -141,20 +154,43 @@ def _handler(request: httpx.Request) -> httpx.Response:
141154 assert captured_headers ["ai-gateway-auth-method" ] == "oidc"
142155
143156
144- async def test_api_key_env_takes_precedence_over_oidc (
157+ async def test_oidc_expected_without_vercel_extra_raises_installation_error (
145158 monkeypatch : pytest .MonkeyPatch ,
146159) -> None :
147- monkeypatch .setenv ("AI_GATEWAY_API_KEY" , "env-test-key" )
160+ monkeypatch .delenv ("AI_GATEWAY_API_KEY" , raising = False )
148161 monkeypatch .setenv ("VERCEL" , "1" )
162+ monkeypatch .setattr (
163+ gateway_provider ,
164+ "_get_vercel_oidc_token_impl" ,
165+ None ,
166+ )
149167
150- def _fail_oidc ( ) -> str :
151- pytest .fail ("OIDC should not be fetched when an API key is set " )
168+ def _handler ( request : httpx . Request ) -> httpx . Response :
169+ pytest .fail ("Gateway should not be called without the OIDC helper " )
152170
153- monkeypatch . setattr (
154- vercel_oidc ,
155- "get_vercel_oidc_token " ,
156- _fail_oidc ,
171+ provider = ai . get_provider (
172+ "vercel" ,
173+ base_url = "https://gateway.test/v3/ai " ,
174+ client = httpx . AsyncClient ( transport = httpx . MockTransport ( _handler )) ,
157175 )
176+
177+ try :
178+ with pytest .raises (ai .InstallationError ) as exc_info :
179+ await provider .list_models ()
180+ finally :
181+ await provider .aclose ()
182+
183+ assert "AI Gateway OIDC authentication requires" in str (exc_info .value )
184+ assert "ai[vercel]" in str (exc_info .value )
185+ assert "AI_GATEWAY_API_KEY" in str (exc_info .value )
186+
187+
188+ async def test_api_key_env_takes_precedence_over_oidc (
189+ monkeypatch : pytest .MonkeyPatch ,
190+ ) -> None :
191+ monkeypatch .setenv ("AI_GATEWAY_API_KEY" , "env-test-key" )
192+ monkeypatch .setenv ("VERCEL" , "1" )
193+ _fail_oidc_import (monkeypatch )
158194 captured_headers : dict [str , str ] = {}
159195
160196 def _handler (request : httpx .Request ) -> httpx .Response :
@@ -181,15 +217,7 @@ async def test_explicit_api_key_takes_precedence_over_oidc(
181217) -> None :
182218 monkeypatch .setenv ("AI_GATEWAY_API_KEY" , "env-test-key" )
183219 monkeypatch .setenv ("VERCEL" , "1" )
184-
185- def _fail_oidc () -> str :
186- pytest .fail ("OIDC should not be fetched when an API key is set" )
187-
188- monkeypatch .setattr (
189- vercel_oidc ,
190- "get_vercel_oidc_token" ,
191- _fail_oidc ,
192- )
220+ _fail_oidc_import (monkeypatch )
193221 captured_headers : dict [str , str ] = {}
194222
195223 def _handler (request : httpx .Request ) -> httpx .Response :
0 commit comments