chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
"""Tests for the ChatKit integration sample attachment store."""
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
|
||||
import agent_framework
|
||||
import pytest
|
||||
|
||||
_ATTACHMENT_STORE_PATH = (
|
||||
Path(__file__).parents[3] / "samples" / "05-end-to-end" / "chatkit-integration" / "attachment_store.py"
|
||||
)
|
||||
|
||||
|
||||
def _load_attachment_store_module() -> ModuleType:
|
||||
spec = importlib.util.spec_from_file_location("chatkit_attachment_store", _ATTACHMENT_STORE_PATH)
|
||||
assert spec is not None
|
||||
assert spec.loader is not None
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
attachment_store_module = _load_attachment_store_module()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def chatkit_app_module(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> ModuleType:
|
||||
sample_dir = _ATTACHMENT_STORE_PATH.parent
|
||||
monkeypatch.chdir(tmp_path)
|
||||
monkeypatch.setenv("FOUNDRY_MODEL", "test-model")
|
||||
monkeypatch.setenv("FOUNDRY_PROJECT_ENDPOINT", "https://example.com")
|
||||
monkeypatch.setattr(agent_framework, "FunctionResultContent", object, raising=False)
|
||||
monkeypatch.syspath_prepend(str(sample_dir))
|
||||
|
||||
spec = importlib.util.spec_from_file_location("chatkit_integration_app", sample_dir / "app.py")
|
||||
assert spec is not None
|
||||
assert spec.loader is not None
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
def test_get_file_path_returns_direct_child(tmp_path: Path) -> None:
|
||||
store = attachment_store_module.FileBasedAttachmentStore(uploads_dir=str(tmp_path))
|
||||
|
||||
assert store.get_file_path("attachment-123") == tmp_path / "attachment-123"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"attachment_id",
|
||||
[
|
||||
"../outside",
|
||||
"nested/attachment-123",
|
||||
"nested/../attachment-123",
|
||||
r"nested\attachment-123",
|
||||
r"nested\..\attachment-123",
|
||||
"/tmp/attachment-123",
|
||||
"",
|
||||
".",
|
||||
"..",
|
||||
],
|
||||
)
|
||||
def test_get_file_path_rejects_non_filename_ids(tmp_path: Path, attachment_id: str) -> None:
|
||||
store = attachment_store_module.FileBasedAttachmentStore(uploads_dir=str(tmp_path))
|
||||
|
||||
with pytest.raises(ValueError, match="Invalid attachment ID"):
|
||||
store.get_file_path(attachment_id)
|
||||
|
||||
|
||||
async def test_attachment_routes_return_bad_request_for_invalid_id(chatkit_app_module: ModuleType) -> None:
|
||||
upload = chatkit_app_module.UploadFile(file=BytesIO(b"contents"), filename="attachment.txt")
|
||||
|
||||
upload_response = await chatkit_app_module.upload_file(".", upload)
|
||||
preview_response = await chatkit_app_module.preview_image(".")
|
||||
|
||||
assert upload_response.status_code == 400
|
||||
assert json.loads(upload_response.body) == {"error": "Invalid attachment ID."}
|
||||
assert preview_response.status_code == 400
|
||||
assert json.loads(preview_response.body) == {"error": "Invalid attachment ID."}
|
||||
@@ -0,0 +1,594 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import copy
|
||||
import os
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from pytest import MonkeyPatch, mark, param
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_basic import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_ai_basic,
|
||||
)
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_with_code_interpreter import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_ai_with_code_interpreter,
|
||||
)
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_with_existing_agent import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_ai_with_existing_agent,
|
||||
)
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_with_explicit_settings import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_ai_with_explicit_settings,
|
||||
)
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
mixed_tools_example as azure_ai_with_function_tools_mixed,
|
||||
)
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
tools_on_agent_level as azure_ai_with_function_tools_agent,
|
||||
)
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
tools_on_run_level as azure_ai_with_function_tools_run,
|
||||
)
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_with_local_mcp import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_ai_with_local_mcp,
|
||||
)
|
||||
from samples.getting_started.agents.azure_ai.azure_ai_with_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_ai_with_thread,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_assistants_basic import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_assistants_basic,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_assistants_with_code_interpreter import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_assistants_with_code_interpreter,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_assistants_with_existing_assistant import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_assistants_with_existing_assistant,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_assistants_with_explicit_settings import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_assistants_with_explicit_settings,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_assistants_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_assistants_with_function_tools,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_assistants_with_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_assistants_with_thread,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_chat_client_basic import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_chat_client_basic,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_chat_client_with_explicit_settings import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_chat_client_with_explicit_settings,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_chat_client_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_chat_client_with_function_tools,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_chat_client_with_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_chat_client_with_thread,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_responses_client_basic import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_responses_client_basic,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_responses_client_with_code_interpreter import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_responses_client_with_code_interpreter,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_responses_client_with_explicit_settings import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_responses_client_with_explicit_settings,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_responses_client_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_responses_client_with_function_tools,
|
||||
)
|
||||
from samples.getting_started.agents.azure_openai.azure_responses_client_with_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_responses_client_with_thread,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_assistants_basic import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_assistants_basic,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_assistants_with_code_interpreter import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_assistants_with_code_interpreter,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_assistants_with_existing_assistant import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_assistants_with_existing_assistant,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_assistants_with_explicit_settings import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_assistants_with_explicit_settings,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_assistants_with_file_search import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_assistants_with_file_search,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_assistants_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_assistants_with_function_tools,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_assistants_with_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_assistants_with_thread,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_chat_client_basic import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_chat_client_basic,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_chat_client_with_explicit_settings import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_chat_client_with_explicit_settings,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_chat_client_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_chat_client_with_function_tools,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_chat_client_with_local_mcp import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_chat_client_with_local_mcp,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_chat_client_with_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_chat_client_with_thread,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_chat_client_with_web_search import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_chat_client_with_web_search,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_basic import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_basic,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_reasoning import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_reasoning,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_with_code_interpreter import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_with_code_interpreter,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_with_explicit_settings import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_with_explicit_settings,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_with_file_search import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_with_file_search,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_with_function_tools import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_with_function_tools,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_with_local_mcp import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_with_local_mcp,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_with_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_with_thread,
|
||||
)
|
||||
from samples.getting_started.agents.openai.openai_responses_client_with_web_search import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client_with_web_search,
|
||||
)
|
||||
|
||||
# Environment variable for controlling sample tests
|
||||
RUN_SAMPLES_TESTS = "RUN_SAMPLES_TESTS"
|
||||
|
||||
# All agent samples across providers
|
||||
agent_samples = [
|
||||
# Azure Assistants Agent samples
|
||||
param(
|
||||
azure_assistants_basic,
|
||||
[], # Non-interactive sample
|
||||
id="azure_assistants_basic",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_assistants_with_code_interpreter,
|
||||
[], # Non-interactive sample
|
||||
id="azure_assistants_with_code_interpreter",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_assistants_with_function_tools,
|
||||
[], # Non-interactive sample
|
||||
id="azure_assistants_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_assistants_with_existing_assistant,
|
||||
[], # Non-interactive sample
|
||||
id="azure_assistants_with_existing_assistant",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_assistants_with_explicit_settings,
|
||||
[], # Non-interactive sample
|
||||
id="azure_assistants_with_explicit_settings",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_assistants_with_thread,
|
||||
[], # Non-interactive sample
|
||||
id="azure_assistants_with_thread",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# Azure Chat Client Agent samples
|
||||
param(
|
||||
azure_chat_client_basic,
|
||||
[], # Non-interactive sample
|
||||
id="azure_chat_client_basic",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_chat_client_with_explicit_settings,
|
||||
[], # Non-interactive sample
|
||||
id="azure_chat_client_with_explicit_settings",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_chat_client_with_function_tools,
|
||||
[], # Non-interactive sample
|
||||
id="azure_chat_client_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_chat_client_with_thread,
|
||||
[], # Non-interactive sample
|
||||
id="azure_chat_client_with_thread",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# Azure Responses Client Agent samples
|
||||
param(
|
||||
azure_responses_client_basic,
|
||||
[], # Non-interactive sample
|
||||
id="azure_responses_client_basic",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_responses_client_with_code_interpreter,
|
||||
[], # Non-interactive sample
|
||||
id="azure_responses_client_with_code_interpreter",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_responses_client_with_explicit_settings,
|
||||
[], # Non-interactive sample
|
||||
id="azure_responses_client_with_explicit_settings",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_responses_client_with_function_tools,
|
||||
[], # Non-interactive sample
|
||||
id="azure_responses_client_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_responses_client_with_thread,
|
||||
[], # Non-interactive sample
|
||||
id="azure_responses_client_with_thread",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# Azure AI Agent samples
|
||||
param(
|
||||
azure_ai_basic,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_basic",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_ai_with_code_interpreter,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_with_code_interpreter",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_ai_with_existing_agent,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_with_existing_agent",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_ai_with_explicit_settings,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_with_explicit_settings",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_ai_with_function_tools_agent,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_ai_with_function_tools_run,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_ai_with_function_tools_mixed,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_ai_with_thread,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_with_thread",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_ai_with_local_mcp,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_with_local_mcp",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# OpenAI Assistants Agent samples
|
||||
param(
|
||||
openai_assistants_basic,
|
||||
[], # Non-interactive sample
|
||||
id="openai_assistants_basic",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_assistants_with_code_interpreter,
|
||||
[], # Non-interactive sample
|
||||
id="openai_assistants_with_code_interpreter",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_assistants_with_existing_assistant,
|
||||
[], # Non-interactive sample
|
||||
id="openai_assistants_with_existing_assistant",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_assistants_with_explicit_settings,
|
||||
[], # Non-interactive sample
|
||||
id="openai_assistants_with_explicit_settings",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_assistants_with_file_search,
|
||||
[], # Non-interactive sample
|
||||
id="openai_assistants_with_file_search",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
pytest.mark.skip(reason="OpenAI file search functionality is currently broken - tracked in GitHub issue"),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_assistants_with_function_tools,
|
||||
[], # Non-interactive sample
|
||||
id="openai_assistants_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_assistants_with_thread,
|
||||
[], # Non-interactive sample
|
||||
id="openai_assistants_with_thread",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# OpenAI Chat Client Agent samples
|
||||
param(
|
||||
openai_chat_client_basic,
|
||||
[], # Non-interactive sample
|
||||
id="openai_chat_client_basic",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_chat_client_with_explicit_settings,
|
||||
[], # Non-interactive sample
|
||||
id="openai_chat_client_with_explicit_settings",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_chat_client_with_function_tools,
|
||||
[], # Non-interactive sample
|
||||
id="openai_chat_client_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_chat_client_with_local_mcp,
|
||||
[], # Non-interactive sample
|
||||
id="openai_chat_client_with_local_mcp",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_chat_client_with_thread,
|
||||
[], # Non-interactive sample
|
||||
id="openai_chat_client_with_thread",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_chat_client_with_web_search,
|
||||
[], # Non-interactive sample
|
||||
id="openai_chat_client_with_web_search",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# OpenAI Responses Client Agent samples
|
||||
param(
|
||||
openai_responses_client_basic,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_basic",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client_reasoning,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_reasoning",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client_with_code_interpreter,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_with_code_interpreter",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client_with_explicit_settings,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_with_explicit_settings",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client_with_file_search,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_with_file_search",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
pytest.mark.skip(reason="OpenAI file search functionality is currently broken - tracked in GitHub issue"),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client_with_function_tools,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_with_function_tools",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client_with_local_mcp,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_with_local_mcp",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client_with_thread,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_with_thread",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client_with_web_search,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client_with_web_search",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.flaky
|
||||
@mark.parametrize("sample, responses", agent_samples)
|
||||
async def test_agent_samples(sample: Callable[..., Awaitable[Any]], responses: list[str], monkeypatch: MonkeyPatch):
|
||||
"""Test agent samples with input mocking and retry logic."""
|
||||
saved_responses = copy.deepcopy(responses)
|
||||
|
||||
def reset():
|
||||
responses.clear()
|
||||
responses.extend(saved_responses)
|
||||
|
||||
def mock_input(prompt: str = "") -> str:
|
||||
return responses.pop(0) if responses else "exit"
|
||||
|
||||
monkeypatch.setattr("builtins.input", mock_input)
|
||||
await sample()
|
||||
@@ -0,0 +1,133 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import copy
|
||||
import os
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from pytest import MonkeyPatch, mark, param
|
||||
from samples.getting_started.client.azure_ai_chat_client import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_ai_chat_client,
|
||||
)
|
||||
from samples.getting_started.client.azure_assistants_client import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_assistants_client,
|
||||
)
|
||||
from samples.getting_started.client.azure_chat_client import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_chat_client,
|
||||
)
|
||||
from samples.getting_started.client.azure_responses_client import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as azure_responses_client,
|
||||
)
|
||||
from samples.getting_started.client.chat_response_cancellation import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as chat_response_cancellation,
|
||||
)
|
||||
from samples.getting_started.client.openai_assistants_client import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_assistants_client,
|
||||
)
|
||||
from samples.getting_started.client.openai_chat_client import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_chat_client,
|
||||
)
|
||||
from samples.getting_started.client.openai_responses_client import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as openai_responses_client,
|
||||
)
|
||||
|
||||
# Environment variable for controlling sample tests
|
||||
RUN_SAMPLES_TESTS = "RUN_SAMPLES_TESTS"
|
||||
|
||||
# All chat client samples across providers
|
||||
chat_client_samples = [
|
||||
# Azure Chat Client samples
|
||||
param(
|
||||
azure_assistants_client,
|
||||
[], # Non-interactive sample
|
||||
id="azure_assistants_client",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_chat_client,
|
||||
[], # Non-interactive sample
|
||||
id="azure_chat_client",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
azure_responses_client,
|
||||
[], # Non-interactive sample
|
||||
id="azure_responses_client",
|
||||
marks=[
|
||||
pytest.mark.azure,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# Azure AI Chat Client samples
|
||||
param(
|
||||
azure_ai_chat_client,
|
||||
[], # Non-interactive sample
|
||||
id="azure_ai_chat_client",
|
||||
marks=[
|
||||
pytest.mark.azure_ai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# OpenAI Chat Client samples
|
||||
param(
|
||||
openai_assistants_client,
|
||||
[], # Non-interactive sample
|
||||
id="openai_assistants_client",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_chat_client,
|
||||
[], # Non-interactive sample
|
||||
id="openai_chat_client",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
openai_responses_client,
|
||||
[], # Non-interactive sample
|
||||
id="openai_responses_client",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
# General Chat Client samples (no provider-specific environment variable)
|
||||
param(
|
||||
chat_response_cancellation,
|
||||
[], # Non-interactive sample
|
||||
id="chat_response_cancellation",
|
||||
marks=pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@mark.parametrize("sample, responses", chat_client_samples)
|
||||
async def test_chat_client_samples(
|
||||
sample: Callable[..., Awaitable[Any]],
|
||||
responses: list[str],
|
||||
monkeypatch: MonkeyPatch,
|
||||
):
|
||||
"""Test chat client samples with input mocking and retry logic."""
|
||||
saved_responses = copy.deepcopy(responses)
|
||||
|
||||
def reset():
|
||||
responses.clear()
|
||||
responses.extend(saved_responses)
|
||||
|
||||
def mock_input(prompt: str = "") -> str:
|
||||
return responses.pop(0) if responses else "exit"
|
||||
|
||||
monkeypatch.setattr("builtins.input", mock_input)
|
||||
await sample()
|
||||
@@ -0,0 +1,56 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import copy
|
||||
import os
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from pytest import MonkeyPatch, mark, param
|
||||
from samples.getting_started.threads.custom_chat_message_store_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as threads_custom_store,
|
||||
)
|
||||
from samples.getting_started.threads.suspend_resume_thread import ( # pyrefly: ignore[missing-import] # ty: ignore[unresolved-import]
|
||||
main as threads_suspend_resume,
|
||||
)
|
||||
|
||||
# Environment variable for controlling sample tests
|
||||
RUN_SAMPLES_TESTS = "RUN_SAMPLES_TESTS"
|
||||
|
||||
# All thread samples
|
||||
thread_samples = [
|
||||
param(
|
||||
threads_custom_store,
|
||||
[], # Non-interactive sample
|
||||
id="threads_custom_store",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
param(
|
||||
threads_suspend_resume,
|
||||
[], # Non-interactive sample
|
||||
id="threads_suspend_resume",
|
||||
marks=[
|
||||
pytest.mark.openai,
|
||||
pytest.mark.skipif(os.getenv(RUN_SAMPLES_TESTS, None) is None, reason="Not running sample tests."),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@mark.parametrize("sample, responses", thread_samples)
|
||||
async def test_thread_samples(sample: Callable[..., Awaitable[Any]], responses: list[str], monkeypatch: MonkeyPatch):
|
||||
"""Test thread samples with input mocking and retry logic."""
|
||||
saved_responses = copy.deepcopy(responses)
|
||||
|
||||
def reset():
|
||||
responses.clear()
|
||||
responses.extend(saved_responses)
|
||||
|
||||
def mock_input(prompt: str = "") -> str:
|
||||
return responses.pop(0) if responses else "exit"
|
||||
|
||||
monkeypatch.setattr("builtins.input", mock_input)
|
||||
await sample()
|
||||
@@ -0,0 +1,99 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
"""Unit tests for resolve_toolbox_endpoint() in the foundry-hosted-agents response samples.
|
||||
|
||||
Covers both 04_foundry_toolbox/main.py and 06_files/main.py which share the same
|
||||
implementation of resolve_toolbox_endpoint().
|
||||
"""
|
||||
|
||||
import importlib.util
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Stub out packages unavailable in the unit-test environment so that importing
|
||||
# the sample modules does not fail.
|
||||
# ---------------------------------------------------------------------------
|
||||
_MISSING_MODULES = (
|
||||
"agent_framework_foundry_hosting",
|
||||
"azure.ai.agentserver",
|
||||
"azure.ai.agentserver.responses",
|
||||
)
|
||||
for _mod_name in _MISSING_MODULES:
|
||||
sys.modules.setdefault(_mod_name, MagicMock())
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Load the two sample modules by file path to avoid needing them on sys.path.
|
||||
# ---------------------------------------------------------------------------
|
||||
_RESPONSES_DIR = (
|
||||
Path(__file__).parent.parent.parent.parent / "samples" / "04-hosting" / "foundry-hosted-agents" / "responses"
|
||||
)
|
||||
|
||||
|
||||
def _load_sample(subdir: str, module_alias: str):
|
||||
spec = importlib.util.spec_from_file_location(module_alias, _RESPONSES_DIR / subdir / "main.py")
|
||||
assert spec is not None
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
assert spec.loader is not None
|
||||
spec.loader.exec_module(mod)
|
||||
return mod
|
||||
|
||||
|
||||
_toolbox_mod = _load_sample("04_foundry_toolbox", "foundry_toolbox_main")
|
||||
_files_mod = _load_sample("06_files", "files_main")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Parameterise over both modules so the same test cases run for each.
|
||||
# ---------------------------------------------------------------------------
|
||||
@pytest.fixture(params=["04_foundry_toolbox", "06_files"])
|
||||
def resolve_endpoint(request):
|
||||
"""Return resolve_toolbox_endpoint from the requested sample module."""
|
||||
mod = _toolbox_mod if request.param == "04_foundry_toolbox" else _files_mod
|
||||
return mod.resolve_toolbox_endpoint
|
||||
|
||||
|
||||
class TestResolveToolboxEndpoint:
|
||||
def test_explicit_endpoint_returned_as_is(self, resolve_endpoint, monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setenv("TOOLBOX_ENDPOINT", "https://example.com/mcp")
|
||||
monkeypatch.delenv("FOUNDRY_PROJECT_ENDPOINT", raising=False)
|
||||
monkeypatch.delenv("TOOLBOX_NAME", raising=False)
|
||||
|
||||
assert resolve_endpoint() == "https://example.com/mcp"
|
||||
|
||||
def test_empty_string_raises_value_error(self, resolve_endpoint, monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setenv("TOOLBOX_ENDPOINT", "")
|
||||
|
||||
with pytest.raises(ValueError, match="TOOLBOX_ENDPOINT is set but empty"):
|
||||
resolve_endpoint()
|
||||
|
||||
def test_fallback_constructs_url_from_project_vars(self, resolve_endpoint, monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.delenv("TOOLBOX_ENDPOINT", raising=False)
|
||||
monkeypatch.setenv("FOUNDRY_PROJECT_ENDPOINT", "https://project.azure.com/")
|
||||
monkeypatch.setenv("TOOLBOX_NAME", "my-toolbox")
|
||||
|
||||
result = resolve_endpoint()
|
||||
|
||||
assert result == "https://project.azure.com/toolboxes/my-toolbox/mcp?api-version=v1"
|
||||
|
||||
def test_fallback_strips_trailing_slash_from_project_endpoint(
|
||||
self, resolve_endpoint, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
monkeypatch.delenv("TOOLBOX_ENDPOINT", raising=False)
|
||||
monkeypatch.setenv("FOUNDRY_PROJECT_ENDPOINT", "https://project.azure.com///")
|
||||
monkeypatch.setenv("TOOLBOX_NAME", "my-toolbox")
|
||||
|
||||
result = resolve_endpoint()
|
||||
|
||||
assert result == "https://project.azure.com/toolboxes/my-toolbox/mcp?api-version=v1"
|
||||
|
||||
def test_neither_variable_group_set_raises_value_error(self, resolve_endpoint, monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.delenv("TOOLBOX_ENDPOINT", raising=False)
|
||||
monkeypatch.delenv("FOUNDRY_PROJECT_ENDPOINT", raising=False)
|
||||
monkeypatch.delenv("TOOLBOX_NAME", raising=False)
|
||||
|
||||
with pytest.raises(ValueError, match="Either set TOOLBOX_ENDPOINT"):
|
||||
resolve_endpoint()
|
||||
Reference in New Issue
Block a user