Files
next-ai-draw-io/tests/e2e/model-test.spec.ts
T
dayuan.jiang 69fb66804d feat(settings): reorganize the settings dialog and the model settings
Tabs Models, General, Drawing and About, each with a fixed title row.

The models tab becomes three pages: the user's providers with one status
each and the server's models; a searchable picker of all 24 providers in
four groups; and a provider page in three steps (connection, models,
test). A new provider gets its first suggested model, and a passing test
offers to use the model in the chat. Bedrock asks for one way of signing
in, with an optional session token for temporary access keys.

The composer's model picker lists every model, marking untested and
failed ones, and can open the provider picker. A chat error that offers
model settings opens the provider the request went to.
2026-10-08 17:44:08 +09:00

101 lines
3.6 KiB
TypeScript

import { expect, test } from "@playwright/test"
import { getIframe } from "./lib/fixtures"
// One provider with three models; the test endpoint answers each differently
const CONFIG = {
version: 1,
providers: [
{
id: "p1",
provider: "glm",
apiKey: "test-key",
models: [
{ id: "m1", modelId: "model-ok" },
{ id: "m2", modelId: "model-no-tools" },
{ id: "m3", modelId: "model-broken" },
],
},
],
}
test("the Test button checks all models at once and shows each result", async ({
page,
}) => {
await page.addInitScript((config) => {
localStorage.setItem(
"next-ai-draw-io-model-configs",
JSON.stringify(config),
)
}, CONFIG)
const started: string[] = []
await page.route("**/api/validate-model", async (route) => {
const { modelId } = route.request().postDataJSON()
started.push(modelId)
// Answer only once all three requests arrived: they run in parallel
while (started.length < 3) await new Promise((r) => setTimeout(r, 50))
const answers: Record<string, object> = {
"model-ok": { valid: true, responseTime: 1234 },
"model-no-tools": {
valid: true,
responseTime: 800,
warning:
"Connected, but the model answered without calling a tool.",
},
"model-broken": { valid: false, error: "Model not found" },
}
await route.fulfill({ json: answers[modelId] })
})
await page.goto("/", { waitUntil: "networkidle" })
await getIframe(page).waitFor({ state: "visible", timeout: 30000 })
await page.getByTestId("model-selector").click()
await page.getByText("Configure Models...").click()
const dialog = page.locator('[role="dialog"]')
await dialog.getByTestId("provider-row-p1").click()
await dialog.getByTestId("test-models").click()
await expect(
dialog.getByText("answered without calling a tool"),
).toBeVisible({ timeout: 15000 })
await expect(dialog.getByText("Model not found")).toBeVisible()
await expect(dialog.getByText("Works · 1.2 s")).toBeVisible()
expect(started.sort()).toEqual([
"model-broken",
"model-no-tools",
"model-ok",
])
})
test("the key link and the base URL cleanup", async ({ page }) => {
await page.addInitScript((config) => {
localStorage.setItem(
"next-ai-draw-io-model-configs",
JSON.stringify(config),
)
}, CONFIG)
await page.goto("/", { waitUntil: "networkidle" })
await getIframe(page).waitFor({ state: "visible", timeout: 30000 })
await page.getByTestId("model-selector").click()
await page.getByText("Configure Models...").click()
const dialog = page.locator('[role="dialog"]')
await dialog.getByTestId("provider-row-p1").click()
await expect(
dialog.getByRole("link", { name: "Get API key" }),
).toHaveAttribute(
"href",
"https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys",
)
// The base URL is under "More options"
await dialog.getByRole("button", { name: /^More options/ }).click()
const baseUrl = dialog.locator("#base-url")
await baseUrl.fill("https://proxy.example.com/v4/chat/completions/")
await baseUrl.blur()
await expect(baseUrl).toHaveValue("https://proxy.example.com/v4")
await expect(
dialog.getByText(
"Requests go to https://proxy.example.com/v4/chat/completions",
),
).toBeVisible()
})