72 lines
2.7 KiB
TypeScript
72 lines
2.7 KiB
TypeScript
import type { ToolPart } from "@opencode-ai/sdk/v2/client"
|
|
import { test, expect } from "../fixtures"
|
|
import { withSession } from "../actions"
|
|
import { promptModelSelector, promptSelector, promptVariantSelector } from "../selectors"
|
|
|
|
const isBash = (part: unknown): part is ToolPart => {
|
|
if (!part || typeof part !== "object") return false
|
|
if (!("type" in part) || part.type !== "tool") return false
|
|
if (!("tool" in part) || part.tool !== "bash") return false
|
|
return "state" in part
|
|
}
|
|
|
|
test("shell mode runs a command in the project directory", async ({ page, project }) => {
|
|
test.setTimeout(120_000)
|
|
|
|
await project.open()
|
|
const cmd = process.platform === "win32" ? "dir" : "command ls"
|
|
|
|
await withSession(project.sdk, `e2e shell ${Date.now()}`, async (session) => {
|
|
project.trackSession(session.id)
|
|
await project.gotoSession(session.id)
|
|
const button = page.locator('[data-action="prompt-permissions"]').first()
|
|
await expect(button).toBeVisible()
|
|
if ((await button.getAttribute("aria-pressed")) !== "true") {
|
|
await button.click()
|
|
await expect(button).toHaveAttribute("aria-pressed", "true")
|
|
}
|
|
await project.shell(cmd)
|
|
|
|
await expect
|
|
.poll(
|
|
async () => {
|
|
const list = await project.sdk.session
|
|
.messages({ sessionID: session.id, limit: 50 })
|
|
.then((x) => x.data ?? [])
|
|
const msg = list.findLast(
|
|
(item) => item.info.role === "assistant" && "path" in item.info && item.info.path.cwd === project.directory,
|
|
)
|
|
if (!msg) return
|
|
|
|
const part = msg.parts
|
|
.filter(isBash)
|
|
.find((item) => item.state.input?.command === cmd && item.state.status === "completed")
|
|
|
|
if (!part || part.state.status !== "completed") return
|
|
const output =
|
|
typeof part.state.metadata?.output === "string" ? part.state.metadata.output : part.state.output
|
|
if (!output.includes("README.md")) return
|
|
|
|
return { cwd: project.directory, output }
|
|
},
|
|
{ timeout: 90_000 },
|
|
)
|
|
.toEqual(expect.objectContaining({ cwd: project.directory, output: expect.stringContaining("README.md") }))
|
|
})
|
|
})
|
|
|
|
test("shell mode unmounts model and variant controls", async ({ page, project }) => {
|
|
await project.open()
|
|
|
|
const prompt = page.locator(promptSelector).first()
|
|
await expect(page.locator(promptModelSelector)).toHaveCount(1)
|
|
await expect(page.locator(promptVariantSelector)).toHaveCount(1)
|
|
|
|
await prompt.click()
|
|
await page.keyboard.type("!")
|
|
|
|
await expect(prompt).toHaveAttribute("aria-label", /enter shell command/i)
|
|
await expect(page.locator(promptModelSelector)).toHaveCount(0)
|
|
await expect(page.locator(promptVariantSelector)).toHaveCount(0)
|
|
})
|