Files
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

140 lines
4.8 KiB
Python

"""Tests for the wizard's interactive model selection prompt."""
from __future__ import annotations
from typing import Any
from unittest.mock import MagicMock
import pytest
from surfaces.cli.wizard import _ui, flow
from surfaces.cli.wizard.config import PROVIDER_BY_VALUE
def _wire_prompts(
monkeypatch: pytest.MonkeyPatch,
select_values: list[str],
text_values: list[str] | None = None,
) -> None:
select_iter = iter(select_values)
text_iter = iter(text_values or [])
def _mock_select(*_args: Any, **_kwargs: Any) -> Any:
m = MagicMock()
m.ask.return_value = next(select_iter)
return m
def _mock_text(*_args: Any, **_kwargs: Any) -> Any:
m = MagicMock()
m.ask.return_value = next(text_iter)
return m
monkeypatch.setattr(_ui, "select_prompt", _mock_select)
monkeypatch.setattr(flow.questionary, "text", _mock_text)
def test_choose_model_returns_curated_default(monkeypatch: pytest.MonkeyPatch) -> None:
provider = PROVIDER_BY_VALUE["anthropic"]
_wire_prompts(monkeypatch, select_values=[provider.default_model])
model = _ui._choose_model(provider, default=provider.default_model)
assert model == provider.default_model
def test_choose_model_offers_full_curated_list(monkeypatch: pytest.MonkeyPatch) -> None:
provider = PROVIDER_BY_VALUE["openai"]
captured: dict[str, list[str]] = {}
def _mock_select(_prompt: str, choices: list[Any], **_kwargs: Any) -> Any:
captured["values"] = [c.value for c in choices]
m = MagicMock()
m.ask.return_value = provider.default_model
return m
monkeypatch.setattr(_ui, "select_prompt", _mock_select)
_ui._choose_model(provider, default="")
expected_curated = [opt.value for opt in provider.models]
assert captured["values"][:-1] == expected_curated
assert captured["values"][-1] == _ui._CUSTOM_MODEL_SENTINEL
def test_choose_model_preserves_saved_model_not_in_curated(
monkeypatch: pytest.MonkeyPatch,
) -> None:
provider = PROVIDER_BY_VALUE["openai"]
captured: dict[str, list[str]] = {}
def _mock_select(_prompt: str, choices: list[Any], **_kwargs: Any) -> Any:
captured["values"] = [c.value for c in choices]
m = MagicMock()
m.ask.return_value = "my-tuned-gpt"
return m
monkeypatch.setattr(_ui, "select_prompt", _mock_select)
model = _ui._choose_model(provider, default="my-tuned-gpt")
assert model == "my-tuned-gpt"
assert "my-tuned-gpt" in captured["values"]
def test_choose_model_accepts_custom_entry(monkeypatch: pytest.MonkeyPatch) -> None:
provider = PROVIDER_BY_VALUE["anthropic"]
_wire_prompts(
monkeypatch,
select_values=[_ui._CUSTOM_MODEL_SENTINEL],
text_values=["claude-future-preview"],
)
model = _ui._choose_model(provider, default=provider.default_model)
assert model == "claude-future-preview"
def test_choose_model_works_for_cli_provider(monkeypatch: pytest.MonkeyPatch) -> None:
"""CLI providers (codex, claude-code, etc.) use the same curated picker."""
provider = PROVIDER_BY_VALUE["codex"]
_wire_prompts(monkeypatch, select_values=["gpt-5.4"])
model = _ui._choose_model(provider, default="")
assert model == "gpt-5.4"
class TestGpt56CatalogPresence:
"""The onboarding picker must offer Sol / Terra / Luna (#3931)."""
@pytest.mark.parametrize("model", ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"])
def test_openai_picker_lists_every_tier(self, model: str) -> None:
values = {option.value for option in PROVIDER_BY_VALUE["openai"].models}
assert model in values
@pytest.mark.parametrize("model", ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"])
def test_azure_picker_lists_every_tier(self, model: str) -> None:
values = {option.value for option in PROVIDER_BY_VALUE["azure-openai"].models}
assert model in values
def test_openrouter_picker_uses_namespaced_ids(self) -> None:
values = {option.value for option in PROVIDER_BY_VALUE["openrouter"].models}
assert "openai/gpt-5.6-sol" in values
def test_codex_picker_lists_sol(self) -> None:
values = {option.value for option in PROVIDER_BY_VALUE["codex"].models}
assert "gpt-5.6-sol" in values
def test_openai_default_model_is_unchanged(self) -> None:
# #3931 explicitly does not re-point defaults; adding quick-picks
# must not promote a GPT-5.6 tier to the default slot.
assert PROVIDER_BY_VALUE["openai"].default_model == "gpt-5.4-mini"
def test_openai_picker_selects_sol(self, monkeypatch: pytest.MonkeyPatch) -> None:
provider = PROVIDER_BY_VALUE["openai"]
_wire_prompts(monkeypatch, select_values=["gpt-5.6-sol"])
assert _ui._choose_model(provider, default="") == "gpt-5.6-sol"