| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /** @jsxImportSource @opentui/solid */
- import { describe, expect, test } from "bun:test"
- import { testRender } from "@opentui/solid"
- import type { Event, GlobalEvent } from "@kilocode/sdk/v2"
- import { onMount } from "solid-js"
- import { ProjectProvider, useProject } from "../../../src/cli/cmd/tui/context/project"
- import { SDKProvider } from "../../../src/cli/cmd/tui/context/sdk"
- import { useEvent } from "../../../src/cli/cmd/tui/context/event"
- async function wait(fn: () => boolean, timeout = 2000) {
- const start = Date.now()
- while (!fn()) {
- if (Date.now() - start > timeout) throw new Error("timed out waiting for condition")
- await Bun.sleep(10)
- }
- }
- function event(payload: Event, input: { directory: string; workspace?: string }): GlobalEvent {
- return {
- directory: input.directory,
- workspace: input.workspace,
- payload,
- }
- }
- function vcs(branch: string): Event {
- return {
- type: "vcs.branch.updated",
- properties: {
- branch,
- },
- }
- }
- function update(version: string): Event {
- return {
- type: "installation.update-available",
- properties: {
- version,
- },
- }
- }
- function createSource() {
- let fn: ((event: GlobalEvent) => void) | undefined
- return {
- source: {
- subscribe: async (handler: (event: GlobalEvent) => void) => {
- fn = handler
- return () => {
- if (fn === handler) fn = undefined
- }
- },
- },
- emit(evt: GlobalEvent) {
- if (!fn) throw new Error("event source not ready")
- fn(evt)
- },
- }
- }
- async function mount() {
- const source = createSource()
- const seen: Event[] = []
- let project!: ReturnType<typeof useProject>
- let done!: () => void
- const ready = new Promise<void>((resolve) => {
- done = resolve
- })
- const app = await testRender(() => (
- <SDKProvider url="http://test" directory="/tmp/root" events={source.source}>
- <ProjectProvider>
- <Probe
- onReady={(ctx) => {
- project = ctx.project
- done()
- }}
- seen={seen}
- />
- </ProjectProvider>
- </SDKProvider>
- ))
- await ready
- return { app, emit: source.emit, project, seen }
- }
- function Probe(props: { seen: Event[]; onReady: (ctx: { project: ReturnType<typeof useProject> }) => void }) {
- const project = useProject()
- const event = useEvent()
- onMount(() => {
- event.subscribe((evt) => {
- props.seen.push(evt)
- })
- props.onReady({ project })
- })
- return <box />
- }
- describe("useEvent", () => {
- test("delivers matching directory events without an active workspace", async () => {
- const { app, emit, seen } = await mount()
- try {
- emit(event(vcs("main"), { directory: "/tmp/root" }))
- await wait(() => seen.length === 1)
- expect(seen).toEqual([vcs("main")])
- } finally {
- app.renderer.destroy()
- }
- })
- test("ignores non-matching directory events without an active workspace", async () => {
- const { app, emit, seen } = await mount()
- try {
- emit(event(vcs("other"), { directory: "/tmp/other" }))
- await Bun.sleep(30)
- expect(seen).toHaveLength(0)
- } finally {
- app.renderer.destroy()
- }
- })
- test("delivers matching workspace events when a workspace is active", async () => {
- const { app, emit, project, seen } = await mount()
- try {
- project.workspace.set("ws_a")
- emit(event(vcs("ws"), { directory: "/tmp/other", workspace: "ws_a" }))
- await wait(() => seen.length === 1)
- expect(seen).toEqual([vcs("ws")])
- } finally {
- app.renderer.destroy()
- }
- })
- test("ignores non-matching workspace events when a workspace is active", async () => {
- const { app, emit, project, seen } = await mount()
- try {
- project.workspace.set("ws_a")
- emit(event(vcs("ws"), { directory: "/tmp/root", workspace: "ws_b" }))
- await Bun.sleep(30)
- expect(seen).toHaveLength(0)
- } finally {
- app.renderer.destroy()
- }
- })
- test("delivers truly global events even when a workspace is active", async () => {
- const { app, emit, project, seen } = await mount()
- try {
- project.workspace.set("ws_a")
- emit(event(update("1.2.3"), { directory: "global" }))
- await wait(() => seen.length === 1)
- expect(seen).toEqual([update("1.2.3")])
- } finally {
- app.renderer.destroy()
- }
- })
- })
|