fix: actually check the endpoint during setup

async_setup_entry handed client.with_options(timeout=10.0).models.list to the
executor. On AsyncOpenAI that returns an awaitable paginator, so it came back
unawaited, no request was made, and a bad key or an unreachable endpoint still
set up. It now awaits client.models.list(timeout=10.0), matching core's
openai_conversation, so a 401 raises ConfigEntryAuthFailed and a connection
error ConfigEntryNotReady, as the README already says.

The shared mock_init_component fixture now patches models.list with an
AsyncMock and keeps the patch for the whole test, because tests that change a
subentry reload the entry and run setup again.

Reported by @MartinNuc in #1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SUd68TsT5QZ68Dtfw2uWBU
This commit is contained in:
Adam SmithandClaude Opus 5.5 committed 2026-10-11 06:45:52 -04:00
1 parent 151d741a71
commit a6faa44b2f
3 files changed
+64 -7

No files matched your search

+9 -3
View File
@@ -1,6 +1,6 @@
"""Fixtures for openai_compatible tests."""
from collections.abc import Generator
from collections.abc import AsyncGenerator, Generator
from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch
@@ -154,13 +154,19 @@ async def mock_config_entry_with_reasoning_model(
@pytest.fixture
async def mock_init_component(
hass: HomeAssistant, mock_config_entry: MockConfigEntry
) -> None:
"""Initialize integration."""
) -> AsyncGenerator[None]:
"""Initialize integration.
The patch stays active for the whole test: setup awaits GET /models, and a
test that changes a subentry reloads the entry, which runs setup again.
"""
with patch(
"openai.resources.models.AsyncModels.list",
new_callable=AsyncMock,
):
assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done()
yield
@pytest.fixture(autouse=True)