Files
opencode/packages/session-ui/component-tests/session-timeline-reasoning.spec.ts

108 lines
5.2 KiB
TypeScript

import { expect, story } from "../../stories/playwright/story"
for (const mode of ["hidden", "compact", "full"] as const) {
for (const reasoning of ["blank", "heading"] as const) {
story(`projects ${mode} mode with ${reasoning} active reasoning`, async ({ mount }) => {
const timeline = await mount("current-session-timeline-rows--conversation", {
args: { scenario: "reasoning", mode, reasoning },
})
await expect(timeline.locator('[data-timeline-row="UserMessage"]')).toContainText(
"Find why the Session header shifts after the first streamed response.",
)
const active = mode !== "hidden"
const part = timeline.locator('[data-timeline-part-id="msg_projection_assistant:reasoning:0"]')
await expect(timeline.locator('[data-timeline-row="Thinking"]')).toHaveCount(active ? 1 : 0)
await expect(part).toHaveCount(active ? 1 : 0)
if (!active || reasoning !== "heading") {
await expect(timeline.getByText("Inspecting stability", { exact: true })).toHaveCount(0)
return
}
const trigger = part.getByRole("button")
const body = part.getByText("I will inspect the timeline before changing its state.", { exact: true })
await expect(trigger).toHaveAttribute("aria-expanded", String(mode === "full"))
await expect(part.locator('[data-component="text-shimmer"]')).toHaveAttribute("data-active", "true")
if (mode === "compact") {
await expect(trigger).toContainText("Inspecting stability")
await expect(body).toBeHidden()
await trigger.click()
await expect(trigger).toHaveAttribute("aria-expanded", "true")
}
await expect(body).toBeVisible()
await trigger.click()
await expect(trigger).toHaveAttribute("aria-expanded", "false")
await expect(body).toBeHidden()
await expect(trigger).toContainText("Inspecting stability")
})
}
for (const following of ["tool", "text"] as const) {
story(`stops Thinking before ${following} in ${mode} mode`, async ({ mount }) => {
const timeline = await mount("current-session-timeline-rows--conversation", {
args: {
scenario: "reasoning",
mode,
reasoning: "heading",
tool: following === "tool",
text: following === "text" ? "The timeline is stable" : "",
},
})
const part = timeline.locator('[data-timeline-part-id="msg_projection_assistant:reasoning:0"]')
if (following === "tool") {
const group = timeline.locator('[data-component="collapsed-tool-group"]')
const trigger = group.locator(':scope > [data-component="collapsible"] > [data-slot="collapsible-trigger"]')
await expect(trigger).toHaveText(/^Used\s*1\s*Skill$/)
await expect(trigger).toHaveAttribute("aria-expanded", "false")
await expect(group.locator('[data-component="context-tool-group-trigger"]')).toHaveAttribute(
"aria-label",
"Used 1 Skill",
)
await expect(timeline.getByText("Inspecting stability", { exact: true })).toBeHidden()
await trigger.click()
await expect(trigger).toHaveAttribute("aria-expanded", "true")
await expect(group.locator('[data-timeline-part-id="tool_reasoning_projection_skill"]')).toBeVisible()
await expect(group.locator('[data-component="reasoning-part"]')).toHaveCount(mode === "hidden" ? 0 : 1)
}
if (following === "text")
await expect(timeline.getByText("The timeline is stable", { exact: true })).toBeVisible()
await expect(timeline.locator('[data-timeline-row="Thinking"]')).toHaveCount(0)
await expect(part).toHaveCount(mode === "hidden" ? 0 : 1)
if (mode === "hidden") return
const thought = part.locator('[data-slot="collapsible-trigger"]')
const thoughtTitle = thought.locator('[data-slot="basic-tool-tool-title"]')
await expect(thoughtTitle).toContainText("Thought")
await expect(thoughtTitle).toHaveCSS("font-size", "13px")
await expect(thoughtTitle).toHaveCSS("line-height", "16px")
await expect(thought.locator('[data-slot="basic-tool-tool-subtitle"]')).toHaveText("7s")
await expect(thought).toHaveAttribute("aria-expanded", String(mode === "full"))
await expect(thought).not.toContainText("Inspecting stability")
await expect(part.locator('[data-component="text-shimmer"]')).toHaveAttribute("data-active", "false")
if (mode === "compact") await thought.click()
await expect(
part.getByText("I will inspect the timeline before changing its state.", { exact: true }),
).toBeVisible()
})
}
}
// Moved from packages/app/e2e/regression/session-timeline-reasoning-projection.spec.ts
story("does not infer reasoning visibility from provider identity", async ({ mount }) => {
const timeline = await mount("current-session-timeline-rows--conversation", {
args: { scenario: "reasoning", reasoning: "none", text: "No reasoning payload" },
})
await expect(timeline.locator('[data-timeline-row="Thinking"]')).toHaveCount(0)
await expect(timeline.locator('[data-timeline-part-id*="reasoning"]')).toHaveCount(0)
await expect(timeline.getByText("No reasoning payload", { exact: true })).toBeVisible()
})