117 lines
4.4 KiB
Python
117 lines
4.4 KiB
Python
"""E2E: kiro-native model picker renders the kiro catalog and persists a pick."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from urllib.parse import urlparse
|
|
|
|
from playwright.sync_api import Page, Route, expect
|
|
|
|
|
|
def _patch_session_as_kiro_native(page: Page, session_id: str) -> list[dict]:
|
|
"""Patch the browser's session snapshot into a kiro-native response.
|
|
|
|
The server fixture seeds a normal session so the page boots against the real
|
|
app/server. This route patch rewrites only ``GET``/``PATCH
|
|
/v1/sessions/{session_id}`` as seen by the browser into a kiro-native
|
|
snapshot carrying the curated kiro ``model_options`` (the shape
|
|
:func:`omnigent.kiro_native.kiro_base_model_options` serves) and a persisted
|
|
``model_override``.
|
|
|
|
:param page: Playwright page before navigation.
|
|
:param session_id: Session id to patch, e.g. ``"conv_abc123"``.
|
|
:returns: Captured PATCH request bodies.
|
|
"""
|
|
latest_payload: dict | None = None
|
|
patch_bodies: list[dict] = []
|
|
|
|
def _handle(route: Route) -> None:
|
|
nonlocal latest_payload
|
|
request = route.request
|
|
parsed = urlparse(request.url)
|
|
if parsed.path != f"/v1/sessions/{session_id}":
|
|
route.continue_()
|
|
return
|
|
|
|
headers = {"content-type": "application/json"}
|
|
if request.method == "GET":
|
|
response = route.fetch()
|
|
payload = response.json()
|
|
headers = {**response.headers, **headers}
|
|
elif request.method == "PATCH":
|
|
request_body = json.loads(request.post_data or "{}")
|
|
patch_bodies.append(request_body)
|
|
payload = dict(latest_payload or {})
|
|
if "model_override" in request_body:
|
|
payload["model_override"] = request_body["model_override"]
|
|
else:
|
|
route.continue_()
|
|
return
|
|
|
|
payload["labels"] = {
|
|
**payload.get("labels", {}),
|
|
"omnigent.wrapper": "kiro-native-ui",
|
|
}
|
|
payload["harness"] = "kiro-native"
|
|
payload["model_options"] = [
|
|
{"id": "auto", "displayName": "Auto", "isDefault": True, "isCurrent": False},
|
|
{
|
|
"id": "claude-haiku-4.5",
|
|
"displayName": "Claude Haiku 4.5",
|
|
"isDefault": False,
|
|
"isCurrent": False,
|
|
},
|
|
{"id": "glm-5", "displayName": "GLM-5", "isDefault": False, "isCurrent": False},
|
|
]
|
|
payload.setdefault("model_override", "claude-haiku-4.5")
|
|
latest_payload = dict(payload)
|
|
route.fulfill(status=200, headers=headers, body=json.dumps(payload))
|
|
|
|
page.route("**/v1/sessions/**", _handle)
|
|
return patch_bodies
|
|
|
|
|
|
def test_kiro_native_picker_lists_models_and_persists_pick(
|
|
page: Page,
|
|
seeded_session: tuple[str, str],
|
|
) -> None:
|
|
"""The kiro-native picker renders the curated catalog and persists a pick.
|
|
|
|
kiro applies the chosen model as ``--model`` at launch, so the picker writes
|
|
the selection to ``model_override`` (no in-session mirror). This covers the
|
|
snapshot-driven picker render and the PATCH that carries the pick.
|
|
|
|
:param page: Playwright page fixture.
|
|
:param seeded_session: ``(base_url, session_id)`` for a real server-backed
|
|
session; the browser snapshot is patched to kiro-native.
|
|
:returns: None.
|
|
"""
|
|
base_url, session_id = seeded_session
|
|
patch_bodies = _patch_session_as_kiro_native(page, session_id)
|
|
|
|
page.goto(f"{base_url}/c/{session_id}")
|
|
|
|
trigger = page.get_by_test_id("agent-picker-trigger")
|
|
expect(trigger).to_be_visible(timeout=15_000)
|
|
trigger.click()
|
|
|
|
# The curated kiro catalog renders with its display names.
|
|
haiku_row = page.locator('[data-testid="model-picker-item"][data-model-id="claude-haiku-4.5"]')
|
|
expect(haiku_row).to_be_visible()
|
|
expect(haiku_row).to_contain_text("Claude Haiku 4.5")
|
|
expect(
|
|
page.locator('[data-testid="model-picker-item"][data-model-id="glm-5"]')
|
|
).to_be_visible()
|
|
|
|
# Picking a model PATCHes model_override (consumed at launch via --model).
|
|
with page.expect_response(
|
|
lambda response: (
|
|
response.request.method == "PATCH"
|
|
and urlparse(response.url).path == f"/v1/sessions/{session_id}"
|
|
and response.status == 200
|
|
)
|
|
):
|
|
page.locator('[data-testid="model-picker-item"][data-model-id="glm-5"]').click()
|
|
|
|
assert patch_bodies[-1] == {"model_override": "glm-5"}
|