"""Tests for GenAIClient Protocol + FakeGenAIClient (spec ยง6.3).""" from __future__ import annotations import pytest from pydantic import BaseModel from ix.genai import ( FakeGenAIClient, GenAIClient, GenAIInvocationResult, GenAIUsage, ) class _Schema(BaseModel): foo: str bar: int class TestProtocolConformance: def test_fake_is_runtime_checkable_as_protocol(self) -> None: client = FakeGenAIClient(parsed=_Schema(foo="x", bar=1)) assert isinstance(client, GenAIClient) class TestReturnsCannedResult: async def test_defaults_populate_usage_and_model(self) -> None: parsed = _Schema(foo="bank", bar=2) client = FakeGenAIClient(parsed=parsed) result = await client.invoke(request_kwargs={"model": "x"}, response_schema=_Schema) assert isinstance(result, GenAIInvocationResult) assert result.parsed is parsed assert isinstance(result.usage, GenAIUsage) assert result.usage.prompt_tokens == 0 assert result.usage.completion_tokens == 0 assert result.model_name == "fake" async def test_explicit_usage_and_model_passed_through(self) -> None: parsed = _Schema(foo="k", bar=3) usage = GenAIUsage(prompt_tokens=10, completion_tokens=20) client = FakeGenAIClient(parsed=parsed, usage=usage, model_name="mock:0.1") result = await client.invoke(request_kwargs={}, response_schema=_Schema) assert result.usage is usage assert result.model_name == "mock:0.1" class TestRaiseOnCallHook: async def test_raise_on_call_propagates(self) -> None: err = RuntimeError("ollama is down") client = FakeGenAIClient( parsed=_Schema(foo="x", bar=1), raise_on_call=err ) with pytest.raises(RuntimeError, match="ollama is down"): await client.invoke(request_kwargs={}, response_schema=_Schema)