mirror of
https://github.com/anomalyco/opencode.git
synced 2026-09-04 10:54:38 +00:00
86 lines
3.9 KiB
TypeScript
86 lines
3.9 KiB
TypeScript
import { expect, story } from "../../storybook/playwright/story"
|
|
|
|
for (const draft of ["empty-draft", "multiline-draft", "mixed-attachments"]) {
|
|
story(`select all stays inside the composer with ${draft}`, async ({ mount, page }) => {
|
|
const component = await mount(`opencode-composer-flow--${draft}`)
|
|
const input = component.getByRole("textbox", { name: "Prompt", exact: true })
|
|
const text = await input.textContent()
|
|
|
|
for (let count = 0; count < 2; count++) {
|
|
await input.press("ControlOrMeta+a")
|
|
expect(
|
|
await input.evaluate((editor) => {
|
|
const selection = window.getSelection()
|
|
return {
|
|
text: selection?.toString(),
|
|
inside: editor.contains(selection?.anchorNode ?? null) && editor.contains(selection?.focusNode ?? null),
|
|
}
|
|
}),
|
|
).toEqual({ text, inside: true })
|
|
}
|
|
|
|
await page.keyboard.type("Replacement draft")
|
|
await expect(input).toHaveText("Replacement draft")
|
|
await expect(component.getByRole("status")).toHaveText("Ready")
|
|
if (draft === "mixed-attachments") {
|
|
await expect(component.getByAltText("layout.png")).toBeVisible()
|
|
await expect(component.getByText("Keep the normal flow flat", { exact: true })).toBeVisible()
|
|
}
|
|
})
|
|
}
|
|
|
|
story("renders a draft once and supports editing, caret restoration, and failure recovery", async ({ mount, page }) => {
|
|
await page.addInitScript(() => {
|
|
const replace = Element.prototype.replaceChildren
|
|
Element.prototype.replaceChildren = function (this: Element, ...nodes) {
|
|
// The ref can run before data-component is assigned, so count on every target.
|
|
this.setAttribute("data-test-replacements", String(Number(this.getAttribute("data-test-replacements")) + 1))
|
|
return replace.apply(this, nodes)
|
|
}
|
|
})
|
|
const component = await mount("opencode-composer-flow--failed-submission-restoration")
|
|
const input = component.getByRole("textbox", { name: "Prompt", exact: true })
|
|
await expect(input).toHaveText("Preserve this draft on failure")
|
|
await expect(input).toHaveAttribute("data-test-replacements", "1")
|
|
|
|
await input.press("Home")
|
|
await input.press("Shift+ArrowRight")
|
|
await input.pressSequentially("XY")
|
|
await expect(input).toHaveText("XYreserve this draft on failure")
|
|
await expect(input).toHaveAttribute("data-test-replacements", "1")
|
|
|
|
// Closing the model picker restores the controller's saved caret through its editor ref.
|
|
await component.locator('[data-action="composer-model"]').click()
|
|
await page.getByRole("menu").getByRole("textbox").press("Escape")
|
|
await expect(input).toBeFocused()
|
|
await input.pressSequentially("!")
|
|
await expect(input).toHaveText("XY!reserve this draft on failure")
|
|
await component.getByRole("button", { name: "Send", exact: true }).click()
|
|
await expect(component.getByRole("status")).toHaveText("Submission failed; draft restored")
|
|
await expect(input).toHaveText("Preserve this draft on failure")
|
|
})
|
|
|
|
// Moved from packages/app/e2e/regression/prompt-thinking-level.spec.ts
|
|
story("shows the thinking level control while relevant", async ({ mount, page }) => {
|
|
const component = await mount("opencode-composer-flow--model-and-variant")
|
|
const composer = component.locator('[data-component="composer"]')
|
|
const input = composer.locator('[data-component="composer-editor"]')
|
|
const control = composer.getByRole("button", { name: "Choose model variant" })
|
|
|
|
await page.mouse.move(0, 0)
|
|
await page.evaluate(() => (document.activeElement as HTMLElement | null)?.blur())
|
|
await expect(control).toBeVisible()
|
|
|
|
await control.click()
|
|
const high = page.getByRole("menuitemradio", { name: "high" })
|
|
await expect(high).toBeVisible()
|
|
await page.mouse.move(0, 0)
|
|
await expect(control).toBeVisible()
|
|
await expect(high).toBeVisible()
|
|
await high.click()
|
|
|
|
await input.focus()
|
|
await expect(control).toBeVisible()
|
|
await input.blur()
|
|
await expect(control).toBeVisible()
|
|
})
|