|
1 | 1 | import { Database } from "bun:sqlite" |
| 2 | +import { mkdir, symlink } from "node:fs/promises" |
| 3 | +import os from "node:os" |
2 | 4 | import path from "node:path" |
3 | | -import { expect, test } from "bun:test" |
4 | | -import { offsetToPosition, resolveZedSelection } from "../../../src/cli/cmd/tui/context/editor-zed" |
| 5 | +import { expect, spyOn, test } from "bun:test" |
| 6 | +import { offsetToPosition, resolveZedDbPath, resolveZedSelection } from "../../../src/cli/cmd/tui/context/editor-zed" |
5 | 7 | import { tmpdir } from "../../fixture/fixture" |
6 | 8 |
|
7 | 9 | type ZedFixtureOptions = { |
@@ -66,6 +68,23 @@ test("offsetToPosition converts Zed offsets to 1-based editor positions", () => |
66 | 68 | }) |
67 | 69 | }) |
68 | 70 |
|
| 71 | +test("resolveZedDbPath skips candidates that cannot be stated", async () => { |
| 72 | + await using tmp = await tmpdir() |
| 73 | + const loop = path.join(tmp.path, "loop") |
| 74 | + await symlink(loop, loop) |
| 75 | + const home = spyOn(os, "homedir").mockImplementation(() => tmp.path) |
| 76 | + const previous = process.env.OPENCODE_ZED_DB |
| 77 | + process.env.OPENCODE_ZED_DB = loop |
| 78 | + |
| 79 | + try { |
| 80 | + expect(resolveZedDbPath()).toBeUndefined() |
| 81 | + } finally { |
| 82 | + if (previous === undefined) delete process.env.OPENCODE_ZED_DB |
| 83 | + else process.env.OPENCODE_ZED_DB = previous |
| 84 | + home.mockRestore() |
| 85 | + } |
| 86 | +}) |
| 87 | + |
69 | 88 | test("resolveZedSelection returns active editor selection", async () => { |
70 | 89 | await using tmp = await tmpdir() |
71 | 90 | const fixture = await writeZedFixture(tmp.path) |
@@ -251,6 +270,71 @@ test("resolveZedSelection returns empty when no workspace matches", async () => |
251 | 270 | expect(await resolveZedSelection(fixture.dbPath, tmp.path)).toEqual({ type: "empty" }) |
252 | 271 | }) |
253 | 272 |
|
| 273 | +test("resolveZedSelection matches a Zed workspace that contains the session directory", async () => { |
| 274 | + await using tmp = await tmpdir() |
| 275 | + const fixture = await writeZedFixture(tmp.path) |
| 276 | + |
| 277 | + expect(await resolveZedSelection(fixture.dbPath, path.join(tmp.path, "packages", "app"))).toEqual({ |
| 278 | + type: "selection", |
| 279 | + selection: { |
| 280 | + filePath: fixture.filePath, |
| 281 | + source: "zed", |
| 282 | + ranges: [ |
| 283 | + { |
| 284 | + text: "two", |
| 285 | + selection: { |
| 286 | + start: { line: 2, character: 1 }, |
| 287 | + end: { line: 2, character: 4 }, |
| 288 | + }, |
| 289 | + }, |
| 290 | + ], |
| 291 | + }, |
| 292 | + }) |
| 293 | +}) |
| 294 | + |
| 295 | +test("resolveZedSelection prefers the most specific containing Zed workspace", async () => { |
| 296 | + await using tmp = await tmpdir() |
| 297 | + const fixture = await writeZedFixture(tmp.path) |
| 298 | + const child = path.join(tmp.path, "packages") |
| 299 | + const childFile = path.join(child, "child.ts") |
| 300 | + await mkdir(child, { recursive: true }) |
| 301 | + await Bun.write(childFile, "child") |
| 302 | + |
| 303 | + const db = new Database(fixture.dbPath) |
| 304 | + db.run("insert into workspaces values (2, ?, ?)", [JSON.stringify([child]), "2026-01-01"]) |
| 305 | + db.run("insert into panes values (2, 2, 1)") |
| 306 | + db.run("insert into items values (2, 2, 2, 1, ?)", ["Editor"]) |
| 307 | + db.run("insert into editors values (2, 2, ?, ?)", [childFile, "child"]) |
| 308 | + db.run("insert into editor_selections values (2, 2, 0, 5)") |
| 309 | + db.close() |
| 310 | + |
| 311 | + expect(await resolveZedSelection(fixture.dbPath, path.join(child, "app"))).toEqual({ |
| 312 | + type: "selection", |
| 313 | + selection: { |
| 314 | + filePath: childFile, |
| 315 | + source: "zed", |
| 316 | + ranges: [ |
| 317 | + { |
| 318 | + text: "child", |
| 319 | + selection: { |
| 320 | + start: { line: 1, character: 1 }, |
| 321 | + end: { line: 1, character: 6 }, |
| 322 | + }, |
| 323 | + }, |
| 324 | + ], |
| 325 | + }, |
| 326 | + }) |
| 327 | +}) |
| 328 | + |
| 329 | +test("resolveZedSelection ignores a Zed workspace nested inside the session directory", async () => { |
| 330 | + await using tmp = await tmpdir() |
| 331 | + const child = path.join(tmp.path, "effect-lab") |
| 332 | + await mkdir(child, { recursive: true }) |
| 333 | + const fixture = await writeZedFixture(child) |
| 334 | + |
| 335 | + expect(await resolveZedSelection(fixture.dbPath, tmp.path)).toEqual({ type: "empty" }) |
| 336 | +}) |
| 337 | + |
254 | 338 | test("resolveZedSelection returns unavailable when a Zed terminal is active", async () => { |
255 | 339 | await using tmp = await tmpdir() |
256 | 340 | const fixture = await writeZedFixture(tmp.path, { itemKind: "Terminal", editor: false }) |
|
0 commit comments