File size: 3,967 Bytes
3e05655 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | import { describe, expect, test } from "bun:test"
import { createStore } from "solid-js/store"
import type { PromptInputV2PersistedState } from "./types"
import { createPromptInputV2Store } from "./store"
function createPromptStore() {
return createPromptInputV2Store(
createStore<PromptInputV2PersistedState>({
prompt: [
{ type: "text", content: "old", start: 0, end: 3 },
{
type: "image",
id: "attachment-1",
filename: "notes.txt",
mime: "text/plain",
blob: { id: "a", url: "blob:a" },
},
],
cursor: 3,
model: { providerID: "anthropic", modelID: "claude-sonnet", variant: null },
context: { items: [] },
}),
)
}
describe("prompt input v2 store", () => {
test("accepts an accessor for the backing store", () => {
const [state, setState] = createStore<PromptInputV2PersistedState>({
prompt: [{ type: "text", content: "", start: 0, end: 0 }],
cursor: 0,
context: { items: [] },
})
const prompt = createPromptInputV2Store([() => state, setState])
prompt.setText("accessed")
expect(prompt.state.prompt).toEqual([{ type: "text", content: "accessed", start: 0, end: 8 }])
expect(prompt.state.cursor).toBe(8)
})
test("updates prompt text and cursor together while preserving attachments", () => {
const prompt = createPromptStore()
prompt.setText("updated")
expect(prompt.state.prompt).toEqual([
{ type: "text", content: "updated", start: 0, end: 7 },
{
type: "image",
id: "attachment-1",
filename: "notes.txt",
mime: "text/plain",
blob: { id: "a", url: "blob:a" },
},
])
expect(prompt.state.cursor).toBe(7)
})
test("inserts text without flattening structured mentions", () => {
const [state, setState] = createStore<PromptInputV2PersistedState>({
prompt: [
{ type: "text", content: "A ", start: 0, end: 2 },
{ type: "file", path: "one", content: "@one", start: 2, end: 6 },
{ type: "text", content: " B", start: 6, end: 8 },
],
cursor: 2,
context: { items: [] },
})
const prompt = createPromptInputV2Store([state, setState])
prompt.addText("X\nY")
expect(prompt.state.prompt).toEqual([
{ type: "text", content: "A X\nY", start: 0, end: 5 },
{ type: "file", path: "one", content: "@one", start: 5, end: 9 },
{ type: "text", content: " B", start: 9, end: 11 },
])
expect(prompt.state.cursor).toBe(5)
})
test("mutates context, attachments, and model through shared actions", () => {
const prompt = createPromptStore()
const context = { key: "file:src/index.ts", type: "file" as const, path: "src/index.ts" }
prompt.addContext(context)
prompt.addContext(context)
prompt.addMention({ type: "file", path: "src/app.ts", content: "@src/app.ts", start: 0, end: 0 })
prompt.removeAttachment("attachment-1")
prompt.setVariant("thinking")
expect(prompt.state.context.items).toEqual([context])
expect(prompt.state.prompt).toEqual([
{ type: "text", content: "old", start: 0, end: 3 },
{ type: "file", path: "src/app.ts", content: "@src/app.ts", start: 3, end: 14 },
{ type: "text", content: " ", start: 14, end: 15 },
])
expect(prompt.state.model?.variant).toBe("thinking")
prompt.removeContext(context.key)
prompt.setPrompt([{ type: "text", content: "old", start: 0, end: 3 }], 3)
prompt.setModel(undefined)
expect(prompt.state.context.items).toEqual([])
expect(prompt.state.prompt).toEqual([{ type: "text", content: "old", start: 0, end: 3 }])
expect(prompt.state.model).toBeUndefined()
})
test("resets the prompt and cursor", () => {
const prompt = createPromptStore()
prompt.reset()
expect(prompt.state.prompt).toEqual([{ type: "text", content: "", start: 0, end: 0 }])
expect(prompt.state.cursor).toBe(0)
})
})
|