From 4d62c176c7fccdf43d01aa9901648038440e03e3 Mon Sep 17 00:00:00 2001 From: Yuhan Lei Date: Sun, 17 May 2026 22:12:27 +0800 Subject: [PATCH 1/3] fix(app): keep thinking picker clicks active --- .../e2e/models/model-picker-thinking.spec.ts | 113 ++++++++++++++++++ .../components/prompt-input/model-picker.tsx | 17 ++- 2 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 packages/app/e2e/models/model-picker-thinking.spec.ts diff --git a/packages/app/e2e/models/model-picker-thinking.spec.ts b/packages/app/e2e/models/model-picker-thinking.spec.ts new file mode 100644 index 000000000..0b1bc1e6a --- /dev/null +++ b/packages/app/e2e/models/model-picker-thinking.spec.ts @@ -0,0 +1,113 @@ +import type { Page } from "@playwright/test" +import { expect, test } from "../fixtures" + +type ModelKey = { + providerID: string + modelID: string +} + +type Probe = { + model?: ModelKey + variant?: string | null + selected?: string | null + variants?: string[] + models?: Array +} + +async function probe(page: Page): Promise { + return page.evaluate(() => { + const win = window as Window & { + __opencode_e2e?: { + model?: { + current?: Probe + controls?: { + setModel?: (value: ModelKey | undefined) => void + setVariant?: (value: string | undefined) => void + } + } + } + } + return win.__opencode_e2e?.model?.current ?? null + }) +} + +async function setModel(page: Page, value: ModelKey) { + await page.evaluate((value) => { + const win = window as Window & { + __opencode_e2e?: { + model?: { + controls?: { + setModel?: (value: ModelKey | undefined) => void + } + } + } + } + const fn = win.__opencode_e2e?.model?.controls?.setModel + if (!fn) throw new Error("Model e2e model control is not enabled") + fn(value) + }, value) +} + +async function setVariant(page: Page, value: string | undefined) { + await page.evaluate((value) => { + const win = window as Window & { + __opencode_e2e?: { + model?: { + controls?: { + setVariant?: (value: string | undefined) => void + } + } + } + } + const fn = win.__opencode_e2e?.model?.controls?.setVariant + if (!fn) throw new Error("Model e2e variant control is not enabled") + fn(value) + }, value) +} + +async function chooseModelWithVariants(page: Page): Promise { + await expect.poll(() => probe(page).then((state) => state?.models?.length ?? 0), { timeout: 30_000 }).toBeGreaterThan(0) + + const candidates = (await probe(page))?.models ?? [] + for (const candidate of candidates) { + await setModel(page, candidate) + await expect + .poll(() => probe(page).then((state) => `${state?.model?.providerID}:${state?.model?.modelID}`), { + timeout: 30_000, + }) + .toBe(`${candidate.providerID}:${candidate.modelID}`) + + const variants = (await probe(page))?.variants ?? [] + if (variants.length > 0) return variants + } + + return undefined +} + +test("thinking option click updates variant from nested model picker", async ({ page, project }) => { + await page.setViewportSize({ width: 1440, height: 900 }) + await project.open() + + const variants = await chooseModelWithVariants(page) + test.skip(!variants, "no visible e2e model with thinking variants") + if (!variants) return + const target = variants.includes("xhigh") ? "xhigh" : variants[0] + if (!target) throw new Error("Expected at least one thinking variant") + + await setVariant(page, undefined) + await expect.poll(() => probe(page).then((state) => state?.variant ?? null), { timeout: 30_000 }).toBe(null) + + await page.locator('[data-action="prompt-model"]').first().click() + + const thinkingTrigger = page.locator('[data-action="prompt-model-thinking-trigger"]').first() + await expect(thinkingTrigger).toBeVisible() + await expect(thinkingTrigger).toBeEnabled() + await thinkingTrigger.click() + + const option = page.locator(`[data-action="prompt-model-thinking-option"][data-variant="${target}"]`).first() + await expect(option).toBeVisible() + await option.click() + + await expect.poll(() => probe(page).then((state) => state?.selected ?? null), { timeout: 30_000 }).toBe(target) + await expect.poll(() => probe(page).then((state) => state?.variant ?? null), { timeout: 30_000 }).toBe(target) +}) diff --git a/packages/app/src/components/prompt-input/model-picker.tsx b/packages/app/src/components/prompt-input/model-picker.tsx index f918adc4d..cdbfeeac9 100644 --- a/packages/app/src/components/prompt-input/model-picker.tsx +++ b/packages/app/src/components/prompt-input/model-picker.tsx @@ -107,6 +107,7 @@ const ThinkingLevelSection: Component<{ model?: ModelState }> = (props) => { {language.t("dialog.model.variant")} @@ -124,6 +125,8 @@ const ThinkingLevelSection: Component<{ model?: ModelState }> = (props) => {