fixtures.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import { test as base, expect, type Page } from "@playwright/test"
  2. import { cleanupSession, cleanupTestProject, createTestProject, seedProjects, sessionIDFromUrl } from "./actions"
  3. import { promptSelector } from "./selectors"
  4. import { createSdk, dirSlug, getWorktree, sessionPath } from "./utils"
  5. export const settingsKey = "settings.v3"
  6. type TestFixtures = {
  7. sdk: ReturnType<typeof createSdk>
  8. gotoSession: (sessionID?: string) => Promise<void>
  9. withProject: <T>(
  10. callback: (project: {
  11. directory: string
  12. slug: string
  13. gotoSession: (sessionID?: string) => Promise<void>
  14. trackSession: (sessionID: string, directory?: string) => void
  15. trackDirectory: (directory: string) => void
  16. }) => Promise<T>,
  17. options?: { extra?: string[] },
  18. ) => Promise<T>
  19. }
  20. type WorkerFixtures = {
  21. directory: string
  22. slug: string
  23. }
  24. export const test = base.extend<TestFixtures, WorkerFixtures>({
  25. directory: [
  26. async ({}, use) => {
  27. const directory = await getWorktree()
  28. await use(directory)
  29. },
  30. { scope: "worker" },
  31. ],
  32. slug: [
  33. async ({ directory }, use) => {
  34. await use(dirSlug(directory))
  35. },
  36. { scope: "worker" },
  37. ],
  38. sdk: async ({ directory }, use) => {
  39. await use(createSdk(directory))
  40. },
  41. gotoSession: async ({ page, directory }, use) => {
  42. await seedStorage(page, { directory })
  43. const gotoSession = async (sessionID?: string) => {
  44. await page.goto(sessionPath(directory, sessionID))
  45. await expect(page.locator(promptSelector)).toBeVisible()
  46. }
  47. await use(gotoSession)
  48. },
  49. withProject: async ({ page }, use) => {
  50. await use(async (callback, options) => {
  51. const root = await createTestProject()
  52. const slug = dirSlug(root)
  53. const sessions = new Map<string, string>()
  54. const dirs = new Set<string>()
  55. await seedStorage(page, { directory: root, extra: options?.extra })
  56. const gotoSession = async (sessionID?: string) => {
  57. await page.goto(sessionPath(root, sessionID))
  58. await expect(page.locator(promptSelector)).toBeVisible()
  59. const current = sessionIDFromUrl(page.url())
  60. if (current) trackSession(current)
  61. }
  62. const trackSession = (sessionID: string, directory?: string) => {
  63. sessions.set(sessionID, directory ?? root)
  64. }
  65. const trackDirectory = (directory: string) => {
  66. if (directory !== root) dirs.add(directory)
  67. }
  68. try {
  69. await gotoSession()
  70. return await callback({ directory: root, slug, gotoSession, trackSession, trackDirectory })
  71. } finally {
  72. await Promise.allSettled(
  73. Array.from(sessions, ([sessionID, directory]) => cleanupSession({ sessionID, directory })),
  74. )
  75. await Promise.allSettled(Array.from(dirs, (directory) => cleanupTestProject(directory)))
  76. await cleanupTestProject(root)
  77. }
  78. })
  79. },
  80. })
  81. async function seedStorage(page: Page, input: { directory: string; extra?: string[] }) {
  82. await seedProjects(page, input)
  83. await page.addInitScript(() => {
  84. localStorage.setItem(
  85. "opencode.global.dat:model",
  86. JSON.stringify({
  87. recent: [{ providerID: "opencode", modelID: "big-pickle" }],
  88. user: [],
  89. variant: {},
  90. }),
  91. )
  92. })
  93. }
  94. export { expect }