project-picker-recent-search.spec.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import { expect, test } from "@playwright/test"
  2. import type { Page } from "@playwright/test"
  3. import { fixture, pageMessages } from "../smoke/session-timeline.fixture"
  4. import { mockOpenCodeServer } from "../utils/mock-server"
  5. import { expectAppVisible } from "../utils/waits"
  6. const NAMES = ["alpha-service", "bravo-web", "charlie-api", "delta-tools", "echo-infra", "foxtrot-docs"]
  7. const worktrees = NAMES.map((name) => `/opencode-demo/${name}`)
  8. // The sixth project sits outside the five-item recent cap, so it is only reachable if the
  9. // dialog hands every recent project to the list filter instead of a pre-truncated slice.
  10. const OUTSIDE_CAP = "foxtrot-docs"
  11. // Dialog rows carry data-directory-path; the sidebar project list does not, so this
  12. // scopes assertions to the picker instead of matching the sidebar entry of the same name.
  13. const rows = (page: Page) => page.locator("[data-directory-path]")
  14. const row = (page: Page, name: string) => page.locator(`[data-directory-path*="${name}"]`)
  15. async function openProjectDialog(page: Page) {
  16. await mockOpenCodeServer(page, {
  17. sessions: fixture.sessions,
  18. provider: fixture.provider,
  19. directory: fixture.directory,
  20. project: fixture.project,
  21. pageMessages,
  22. fileList: () => [],
  23. findFiles: () => [],
  24. })
  25. await page.addInitScript((dirs) => {
  26. localStorage.setItem(
  27. "opencode.global.dat:server",
  28. JSON.stringify({
  29. projects: { local: dirs.map((worktree: string) => ({ worktree, expanded: false })) },
  30. lastProject: {},
  31. }),
  32. )
  33. }, worktrees)
  34. await page.goto("/")
  35. const add = page.getByRole("button", { name: "Add project" }).first()
  36. await expectAppVisible(add)
  37. await add.click()
  38. await expect(rows(page)).toHaveCount(5)
  39. return page.getByRole("textbox").last()
  40. }
  41. test("searches every recent project, not just the five most recent", async ({ page }) => {
  42. const search = await openProjectDialog(page)
  43. await expect(row(page, OUTSIDE_CAP)).toHaveCount(0)
  44. await search.fill("foxtrot")
  45. await expect(row(page, OUTSIDE_CAP)).toHaveCount(1)
  46. })
  47. test("still caps the idle recent list at five projects", async ({ page }) => {
  48. await openProjectDialog(page)
  49. await expect(row(page, NAMES[4])).toHaveCount(1)
  50. await expect(row(page, OUTSIDE_CAP)).toHaveCount(0)
  51. })