Files
learningcircuit--local-deep…/tests/llm_providers/test_custom_endpoint_ci_integration.py
T
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

146 lines
4.8 KiB
Python

"""
CI Integration tests for OpenAI-Compatible Endpoint.
These tests use real API calls to verify the custom endpoint URL handling works.
They require OPENROUTER_API_KEY to be set in the environment (available in CI).
REGRESSION TEST: This test would have caught the v1.3.10+ regression where
custom endpoint URLs were not being passed correctly to the OpenAI client.
"""
import os
import pytest
from local_deep_research.llm.providers.implementations.custom_openai_endpoint import (
CustomOpenAIEndpointProvider,
)
# Mark for tests that require the API key
requires_openrouter_key = pytest.mark.skipif(
not os.environ.get("OPENROUTER_API_KEY"),
reason="OPENROUTER_API_KEY not set - skipping CI integration tests",
)
@requires_openrouter_key
class TestCustomEndpointWithOpenRouter:
"""Integration tests using OpenRouter as a real OpenAI-compatible endpoint.
These tests verify that CustomOpenAIEndpointProvider correctly handles
custom URLs by actually connecting to OpenRouter's API.
"""
OPENROUTER_URL = "https://openrouter.ai/api/v1"
def test_fetch_models_from_openrouter(self):
"""Can fetch models from OpenRouter using custom endpoint.
REGRESSION TEST: This is the exact scenario that broke in v1.3.10+.
The custom URL was not being passed to the OpenAI client.
"""
api_key = os.environ.get("OPENROUTER_API_KEY")
# Use CustomOpenAIEndpointProvider with OpenRouter URL
models = CustomOpenAIEndpointProvider.list_models_for_api(
api_key=api_key,
base_url=self.OPENROUTER_URL,
)
# OpenRouter should return many models
assert isinstance(models, list)
assert len(models) > 0, (
"Should fetch at least one model from OpenRouter"
)
# Verify model format
for model in models[:5]: # Check first 5
assert "value" in model
assert "label" in model
assert isinstance(model["value"], str)
assert len(model["value"]) > 0
def test_models_include_known_providers(self):
"""OpenRouter models include known providers like OpenAI, Anthropic.
This verifies we're actually getting real model data.
"""
api_key = os.environ.get("OPENROUTER_API_KEY")
models = CustomOpenAIEndpointProvider.list_models_for_api(
api_key=api_key,
base_url=self.OPENROUTER_URL,
)
model_ids = [m["value"] for m in models]
# OpenRouter should have models from major providers
# Check for at least one of these patterns
has_known_model = any(
any(
provider in model_id
for provider in ["openai", "anthropic", "google", "meta"]
)
for model_id in model_ids
)
assert has_known_model, (
f"Expected models from known providers, got: {model_ids[:10]}"
)
def test_url_not_modified(self):
"""The URL we pass is used as-is (no unwanted /v1 suffix added).
REGRESSION TEST: Previously the code was adding /v1 to URLs,
which would break URLs that already have it.
"""
api_key = os.environ.get("OPENROUTER_API_KEY")
# URL already has /v1 - should work without modification
url_with_v1 = "https://openrouter.ai/api/v1"
models = CustomOpenAIEndpointProvider.list_models_for_api(
api_key=api_key,
base_url=url_with_v1,
)
# If URL was modified to /v1/v1, this would fail
assert len(models) > 0, "URL should work as-is without modification"
class TestCustomEndpointAPIContract:
"""Tests verifying the API contract is correct for CI usage."""
def test_base_url_parameter_exists(self):
"""list_models_for_api has base_url as second parameter.
This ensures the API contract used by settings_routes.py is stable.
"""
import inspect
sig = inspect.signature(
CustomOpenAIEndpointProvider.list_models_for_api
)
params = list(sig.parameters.keys())
assert params == ["api_key", "base_url"], (
f"Expected ['api_key', 'base_url'], got {params}"
)
@requires_openrouter_key
def test_works_without_settings_snapshot(self):
"""Can call list_models_for_api without any settings infrastructure.
REGRESSION TEST: The v1.3.10+ code required settings_snapshot which
added unnecessary complexity and broke the feature.
"""
api_key = os.environ.get("OPENROUTER_API_KEY")
# Should work with just api_key and base_url - no settings needed
models = CustomOpenAIEndpointProvider.list_models_for_api(
api_key=api_key,
base_url="https://openrouter.ai/api/v1",
)
assert len(models) > 0