fixtures.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { test as base, expect } from "@playwright/test"
  2. import { createSdk, dirSlug, getWorktree, promptSelector, serverUrl, sessionPath } from "./utils"
  3. type TestFixtures = {
  4. sdk: ReturnType<typeof createSdk>
  5. gotoSession: (sessionID?: string) => Promise<void>
  6. }
  7. type WorkerFixtures = {
  8. directory: string
  9. slug: string
  10. }
  11. export const test = base.extend<TestFixtures, WorkerFixtures>({
  12. directory: [
  13. async ({}, use) => {
  14. const directory = await getWorktree()
  15. await use(directory)
  16. },
  17. { scope: "worker" },
  18. ],
  19. slug: [
  20. async ({ directory }, use) => {
  21. await use(dirSlug(directory))
  22. },
  23. { scope: "worker" },
  24. ],
  25. sdk: async ({ directory }, use) => {
  26. await use(createSdk(directory))
  27. },
  28. gotoSession: async ({ page, directory }, use) => {
  29. await page.addInitScript(
  30. (input: { directory: string; serverUrl: string }) => {
  31. const key = "opencode.global.dat:server"
  32. const raw = localStorage.getItem(key)
  33. const parsed = (() => {
  34. if (!raw) return undefined
  35. try {
  36. return JSON.parse(raw) as unknown
  37. } catch {
  38. return undefined
  39. }
  40. })()
  41. const store = parsed && typeof parsed === "object" ? (parsed as Record<string, unknown>) : {}
  42. const list = Array.isArray(store.list) ? store.list : []
  43. const lastProject = store.lastProject && typeof store.lastProject === "object" ? store.lastProject : {}
  44. const projects = store.projects && typeof store.projects === "object" ? store.projects : {}
  45. const nextProjects = { ...(projects as Record<string, unknown>) }
  46. const add = (origin: string) => {
  47. const current = nextProjects[origin]
  48. const items = Array.isArray(current) ? current : []
  49. const existing = items.filter(
  50. (p): p is { worktree: string; expanded?: boolean } =>
  51. !!p &&
  52. typeof p === "object" &&
  53. "worktree" in p &&
  54. typeof (p as { worktree?: unknown }).worktree === "string",
  55. )
  56. if (existing.some((p) => p.worktree === input.directory)) return
  57. nextProjects[origin] = [{ worktree: input.directory, expanded: true }, ...existing]
  58. }
  59. add("local")
  60. add(input.serverUrl)
  61. localStorage.setItem(
  62. key,
  63. JSON.stringify({
  64. list,
  65. projects: nextProjects,
  66. lastProject,
  67. }),
  68. )
  69. },
  70. { directory, serverUrl },
  71. )
  72. const gotoSession = async (sessionID?: string) => {
  73. await page.goto(sessionPath(directory, sessionID))
  74. await expect(page.locator(promptSelector)).toBeVisible()
  75. }
  76. await use(gotoSession)
  77. },
  78. })
  79. export { expect }