2
0

session.spec.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import { test, expect } from "../fixtures"
  2. import {
  3. openSidebar,
  4. openSessionMoreMenu,
  5. clickMenuItem,
  6. confirmDialog,
  7. openSharePopover,
  8. withSession,
  9. } from "../actions"
  10. import { sessionItemSelector, inlineInputSelector } from "../selectors"
  11. const shareDisabled = process.env.OPENCODE_DISABLE_SHARE === "true" || process.env.OPENCODE_DISABLE_SHARE === "1"
  12. type Sdk = Parameters<typeof withSession>[0]
  13. async function seedMessage(sdk: Sdk, sessionID: string) {
  14. await sdk.session.promptAsync({
  15. sessionID,
  16. noReply: true,
  17. parts: [{ type: "text", text: "e2e seed" }],
  18. })
  19. await expect
  20. .poll(
  21. async () => {
  22. const messages = await sdk.session.messages({ sessionID, limit: 1 }).then((r) => r.data ?? [])
  23. return messages.length
  24. },
  25. { timeout: 30_000 },
  26. )
  27. .toBeGreaterThan(0)
  28. }
  29. test("session can be renamed via header menu", async ({ page, sdk, gotoSession }) => {
  30. const stamp = Date.now()
  31. const originalTitle = `e2e rename test ${stamp}`
  32. const renamedTitle = `e2e renamed ${stamp}`
  33. await withSession(sdk, originalTitle, async (session) => {
  34. await seedMessage(sdk, session.id)
  35. await gotoSession(session.id)
  36. await expect(page.getByRole("heading", { level: 1 }).first()).toHaveText(originalTitle)
  37. const menu = await openSessionMoreMenu(page, session.id)
  38. await clickMenuItem(menu, /rename/i)
  39. const input = page.locator(".scroll-view__viewport").locator(inlineInputSelector).first()
  40. await expect(input).toBeVisible()
  41. await expect(input).toBeFocused()
  42. await input.fill(renamedTitle)
  43. await expect(input).toHaveValue(renamedTitle)
  44. await input.press("Enter")
  45. await expect
  46. .poll(
  47. async () => {
  48. const data = await sdk.session.get({ sessionID: session.id }).then((r) => r.data)
  49. return data?.title
  50. },
  51. { timeout: 30_000 },
  52. )
  53. .toBe(renamedTitle)
  54. await expect(page.getByRole("heading", { level: 1 }).first()).toHaveText(renamedTitle)
  55. })
  56. })
  57. test("session can be archived via header menu", async ({ page, sdk, gotoSession }) => {
  58. const stamp = Date.now()
  59. const title = `e2e archive test ${stamp}`
  60. await withSession(sdk, title, async (session) => {
  61. await seedMessage(sdk, session.id)
  62. await gotoSession(session.id)
  63. const menu = await openSessionMoreMenu(page, session.id)
  64. await clickMenuItem(menu, /archive/i)
  65. await expect
  66. .poll(
  67. async () => {
  68. const data = await sdk.session.get({ sessionID: session.id }).then((r) => r.data)
  69. return data?.time?.archived
  70. },
  71. { timeout: 30_000 },
  72. )
  73. .not.toBeUndefined()
  74. await openSidebar(page)
  75. await expect(page.locator(sessionItemSelector(session.id))).toHaveCount(0)
  76. })
  77. })
  78. test("session can be deleted via header menu", async ({ page, sdk, gotoSession }) => {
  79. const stamp = Date.now()
  80. const title = `e2e delete test ${stamp}`
  81. await withSession(sdk, title, async (session) => {
  82. await seedMessage(sdk, session.id)
  83. await gotoSession(session.id)
  84. const menu = await openSessionMoreMenu(page, session.id)
  85. await clickMenuItem(menu, /delete/i)
  86. await confirmDialog(page, /delete/i)
  87. await expect
  88. .poll(
  89. async () => {
  90. const data = await sdk.session
  91. .get({ sessionID: session.id })
  92. .then((r) => r.data)
  93. .catch(() => undefined)
  94. return data?.id
  95. },
  96. { timeout: 30_000 },
  97. )
  98. .toBeUndefined()
  99. await openSidebar(page)
  100. await expect(page.locator(sessionItemSelector(session.id))).toHaveCount(0)
  101. })
  102. })
  103. test("session can be shared and unshared via header button", async ({ page, sdk, gotoSession }) => {
  104. test.skip(shareDisabled, "Share is disabled in this environment (OPENCODE_DISABLE_SHARE).")
  105. const stamp = Date.now()
  106. const title = `e2e share test ${stamp}`
  107. await withSession(sdk, title, async (session) => {
  108. await seedMessage(sdk, session.id)
  109. await gotoSession(session.id)
  110. const shared = await openSharePopover(page)
  111. const publish = shared.popoverBody.getByRole("button", { name: "Publish" }).first()
  112. await expect(publish).toBeVisible({ timeout: 30_000 })
  113. await publish.click()
  114. await expect(shared.popoverBody.getByRole("button", { name: "Unpublish" }).first()).toBeVisible({
  115. timeout: 30_000,
  116. })
  117. await expect
  118. .poll(
  119. async () => {
  120. const data = await sdk.session.get({ sessionID: session.id }).then((r) => r.data)
  121. return data?.share?.url || undefined
  122. },
  123. { timeout: 30_000 },
  124. )
  125. .not.toBeUndefined()
  126. const unpublish = shared.popoverBody.getByRole("button", { name: "Unpublish" }).first()
  127. await expect(unpublish).toBeVisible({ timeout: 30_000 })
  128. await unpublish.click()
  129. await expect(shared.popoverBody.getByRole("button", { name: "Publish" }).first()).toBeVisible({
  130. timeout: 30_000,
  131. })
  132. await expect
  133. .poll(
  134. async () => {
  135. const data = await sdk.session.get({ sessionID: session.id }).then((r) => r.data)
  136. return data?.share?.url || undefined
  137. },
  138. { timeout: 30_000 },
  139. )
  140. .toBeUndefined()
  141. const unshared = await openSharePopover(page)
  142. await expect(unshared.popoverBody.getByRole("button", { name: "Publish" }).first()).toBeVisible({
  143. timeout: 30_000,
  144. })
  145. })
  146. })