prompt.spec.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { test, expect } from "./fixtures"
  2. import { promptSelector } from "./utils"
  3. function sessionIDFromUrl(url: string) {
  4. const match = /\/session\/([^/?#]+)/.exec(url)
  5. return match?.[1]
  6. }
  7. test("can send a prompt and receive a reply", async ({ page, sdk, gotoSession }) => {
  8. test.setTimeout(120_000)
  9. const pageErrors: string[] = []
  10. const onPageError = (err: Error) => {
  11. pageErrors.push(err.message)
  12. }
  13. page.on("pageerror", onPageError)
  14. await gotoSession()
  15. const token = `E2E_OK_${Date.now()}`
  16. const prompt = page.locator(promptSelector)
  17. await prompt.click()
  18. await page.keyboard.type(`Reply with exactly: ${token}`)
  19. await page.keyboard.press("Enter")
  20. await expect(page).toHaveURL(/\/session\/[^/?#]+/, { timeout: 30_000 })
  21. const sessionID = (() => {
  22. const id = sessionIDFromUrl(page.url())
  23. if (!id) throw new Error(`Failed to parse session id from url: ${page.url()}`)
  24. return id
  25. })()
  26. try {
  27. await expect
  28. .poll(
  29. async () => {
  30. const messages = await sdk.session.messages({ sessionID, limit: 50 }).then((r) => r.data ?? [])
  31. return messages
  32. .filter((m) => m.info.role === "assistant")
  33. .flatMap((m) => m.parts)
  34. .filter((p) => p.type === "text")
  35. .map((p) => p.text)
  36. .join("\n")
  37. },
  38. { timeout: 90_000 },
  39. )
  40. .toContain(token)
  41. const reply = page.locator('[data-slot="session-turn-summary-section"]').filter({ hasText: token }).first()
  42. await expect(reply).toBeVisible({ timeout: 90_000 })
  43. } finally {
  44. page.off("pageerror", onPageError)
  45. await sdk.session.delete({ sessionID }).catch(() => undefined)
  46. }
  47. if (pageErrors.length > 0) {
  48. throw new Error(`Page error(s):\n${pageErrors.join("\n")}`)
  49. }
  50. })