summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/app/src')
-rw-r--r--packages/app/src/components/prompt-input.tsx2
-rw-r--r--packages/app/src/components/prompt-input/submit.test.ts175
-rw-r--r--packages/app/src/components/prompt-input/submit.ts4
3 files changed, 178 insertions, 3 deletions
diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx
index da45c351e..4f495d27d 100644
--- a/packages/app/src/components/prompt-input.tsx
+++ b/packages/app/src/components/prompt-input.tsx
@@ -787,7 +787,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
},
setMode: (mode) => setStore("mode", mode),
setPopover: (popover) => setStore("popover", popover),
- newSessionWorktree: props.newSessionWorktree,
+ newSessionWorktree: () => props.newSessionWorktree,
onNewSessionWorktreeReset: props.onNewSessionWorktreeReset,
onSubmit: props.onSubmit,
})
diff --git a/packages/app/src/components/prompt-input/submit.test.ts b/packages/app/src/components/prompt-input/submit.test.ts
new file mode 100644
index 000000000..475a0e20f
--- /dev/null
+++ b/packages/app/src/components/prompt-input/submit.test.ts
@@ -0,0 +1,175 @@
+import { beforeAll, beforeEach, describe, expect, mock, test } from "bun:test"
+import type { Prompt } from "@/context/prompt"
+
+let createPromptSubmit: typeof import("./submit").createPromptSubmit
+
+const createdClients: string[] = []
+const createdSessions: string[] = []
+const sentShell: string[] = []
+const syncedDirectories: string[] = []
+
+let selected = "/repo/worktree-a"
+
+const promptValue: Prompt = [{ type: "text", content: "ls", start: 0, end: 2 }]
+
+const clientFor = (directory: string) => ({
+ session: {
+ create: async () => {
+ createdSessions.push(directory)
+ return { data: { id: `session-${createdSessions.length}` } }
+ },
+ shell: async () => {
+ sentShell.push(directory)
+ return { data: undefined }
+ },
+ prompt: async () => ({ data: undefined }),
+ command: async () => ({ data: undefined }),
+ abort: async () => ({ data: undefined }),
+ },
+ worktree: {
+ create: async () => ({ data: { directory: `${directory}/new` } }),
+ },
+})
+
+beforeAll(async () => {
+ const rootClient = clientFor("/repo/main")
+
+ mock.module("@solidjs/router", () => ({
+ useNavigate: () => () => undefined,
+ useParams: () => ({}),
+ }))
+
+ mock.module("@opencode-ai/sdk/v2/client", () => ({
+ createOpencodeClient: (input: { directory: string }) => {
+ createdClients.push(input.directory)
+ return clientFor(input.directory)
+ },
+ }))
+
+ mock.module("@opencode-ai/ui/toast", () => ({
+ showToast: () => 0,
+ }))
+
+ mock.module("@opencode-ai/util/encode", () => ({
+ base64Encode: (value: string) => value,
+ }))
+
+ mock.module("@/context/local", () => ({
+ useLocal: () => ({
+ model: {
+ current: () => ({ id: "model", provider: { id: "provider" } }),
+ variant: { current: () => undefined },
+ },
+ agent: {
+ current: () => ({ name: "agent" }),
+ },
+ }),
+ }))
+
+ mock.module("@/context/prompt", () => ({
+ usePrompt: () => ({
+ current: () => promptValue,
+ reset: () => undefined,
+ set: () => undefined,
+ context: {
+ add: () => undefined,
+ remove: () => undefined,
+ items: () => [],
+ },
+ }),
+ }))
+
+ mock.module("@/context/layout", () => ({
+ useLayout: () => ({
+ handoff: {
+ setTabs: () => undefined,
+ },
+ }),
+ }))
+
+ mock.module("@/context/sdk", () => ({
+ useSDK: () => ({
+ directory: "/repo/main",
+ client: rootClient,
+ url: "http://localhost:4096",
+ }),
+ }))
+
+ mock.module("@/context/sync", () => ({
+ useSync: () => ({
+ data: { command: [] },
+ session: {
+ optimistic: {
+ add: () => undefined,
+ remove: () => undefined,
+ },
+ },
+ set: () => undefined,
+ }),
+ }))
+
+ mock.module("@/context/global-sync", () => ({
+ useGlobalSync: () => ({
+ child: (directory: string) => {
+ syncedDirectories.push(directory)
+ return [{}, () => undefined]
+ },
+ }),
+ }))
+
+ mock.module("@/context/platform", () => ({
+ usePlatform: () => ({
+ fetch: fetch,
+ }),
+ }))
+
+ mock.module("@/context/language", () => ({
+ useLanguage: () => ({
+ t: (key: string) => key,
+ }),
+ }))
+
+ const mod = await import("./submit")
+ createPromptSubmit = mod.createPromptSubmit
+})
+
+beforeEach(() => {
+ createdClients.length = 0
+ createdSessions.length = 0
+ sentShell.length = 0
+ syncedDirectories.length = 0
+ selected = "/repo/worktree-a"
+})
+
+describe("prompt submit worktree selection", () => {
+ test("reads the latest worktree accessor value per submit", async () => {
+ const submit = createPromptSubmit({
+ info: () => undefined,
+ imageAttachments: () => [],
+ commentCount: () => 0,
+ mode: () => "shell",
+ working: () => false,
+ editor: () => undefined,
+ queueScroll: () => undefined,
+ promptLength: (value) => value.reduce((sum, part) => sum + ("content" in part ? part.content.length : 0), 0),
+ addToHistory: () => undefined,
+ resetHistoryNavigation: () => undefined,
+ setMode: () => undefined,
+ setPopover: () => undefined,
+ newSessionWorktree: () => selected,
+ onNewSessionWorktreeReset: () => undefined,
+ onSubmit: () => undefined,
+ })
+
+ const event = { preventDefault: () => undefined } as unknown as Event
+
+ await submit.handleSubmit(event)
+ selected = "/repo/worktree-b"
+ await submit.handleSubmit(event)
+
+ expect(createdClients).toEqual(["/repo/worktree-a", "/repo/worktree-b"])
+ expect(createdSessions).toEqual(["/repo/worktree-a", "/repo/worktree-b"])
+ expect(sentShell).toEqual(["/repo/worktree-a", "/repo/worktree-b"])
+ expect(syncedDirectories).toEqual(["/repo/worktree-a", "/repo/worktree-b"])
+ })
+})
diff --git a/packages/app/src/components/prompt-input/submit.ts b/packages/app/src/components/prompt-input/submit.ts
index c118f8cb2..49d75a95e 100644
--- a/packages/app/src/components/prompt-input/submit.ts
+++ b/packages/app/src/components/prompt-input/submit.ts
@@ -37,7 +37,7 @@ type PromptSubmitInput = {
resetHistoryNavigation: () => void
setMode: (mode: "normal" | "shell") => void
setPopover: (popover: "at" | "slash" | null) => void
- newSessionWorktree?: string
+ newSessionWorktree?: Accessor<string | undefined>
onNewSessionWorktreeReset?: () => void
onSubmit?: () => void
}
@@ -137,7 +137,7 @@ export function createPromptSubmit(input: PromptSubmitInput) {
const projectDirectory = sdk.directory
const isNewSession = !params.id
- const worktreeSelection = input.newSessionWorktree || "main"
+ const worktreeSelection = input.newSessionWorktree?.() || "main"
let sessionDirectory = projectDirectory
let client = sdk.client