toast-owner.test.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { beforeEach, describe, expect, test } from "bun:test"
  2. import { createSignal, type JSX } from "solid-js"
  3. import { showToastV2, toasterV2 } from "@opencode-ai/ui/v2/toast-v2"
  4. describe("showToastV2", () => {
  5. // The toast registry is module state, so each test starts from an empty stack.
  6. beforeEach(() => {
  7. toasterV2.dismiss()
  8. })
  9. test("coalesces exact active content", () => {
  10. const first = showToastV2({ title: "Repeated error", description: "Try again" })
  11. const second = showToastV2({ title: "Repeated error", description: "Try again" })
  12. const different = showToastV2({ title: "Repeated error", description: "A different error" })
  13. expect(second).toBe(first)
  14. expect(different).not.toBe(first)
  15. toasterV2.dismiss(first)
  16. toasterV2.dismiss(different)
  17. })
  18. test("allows dismissed content to appear again", () => {
  19. const first = showToastV2("Dismiss and retry")
  20. toasterV2.dismiss(first)
  21. const second = showToastV2("Dismiss and retry")
  22. expect(second).not.toBe(first)
  23. toasterV2.dismiss(second)
  24. })
  25. test("recreates matching content when it is not the topmost toast", () => {
  26. const first = showToastV2("First toast")
  27. const topmost = showToastV2("Topmost toast")
  28. const repeated = showToastV2("First toast")
  29. expect(repeated).not.toBe(first)
  30. toasterV2.dismiss(topmost)
  31. toasterV2.dismiss(repeated)
  32. })
  33. test("creates no reactive computations at call time", () => {
  34. const [tick, setTick] = createSignal(0)
  35. let reads = 0
  36. const icon = (() => {
  37. reads++
  38. tick()
  39. return undefined
  40. }) as unknown as JSX.Element
  41. const id = showToastV2({ description: "test", icon })
  42. // Resolving the icon at call time creates an ownerless computation that is
  43. // never disposed and tracks its dependencies forever; it must only resolve
  44. // once the toast component renders.
  45. expect(reads).toBe(0)
  46. setTick(1)
  47. expect(reads).toBe(0)
  48. toasterV2.dismiss(id)
  49. })
  50. })