solid.test.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { describe, expect, it } from "bun:test"
  2. import { createComputed, createRoot, createSignal } from "solid-js"
  3. import { Computed, Keyed, State, Transaction, type Readable } from "../src"
  4. import { useSlot, useValue } from "../src/solid"
  5. describe("Solid adapter", () => {
  6. it("bridges Quark values into Solid ownership", () => {
  7. const left = State.make(1)
  8. const right = State.make(2)
  9. const total = Computed.make(() => left() + right())
  10. const values: number[] = []
  11. createRoot((dispose) => {
  12. const value = useValue(total)
  13. createComputed(() => values.push(value()))
  14. Transaction.run(() => {
  15. left.set(2)
  16. right.set(3)
  17. })
  18. dispose()
  19. })
  20. left.set(4)
  21. expect(values).toEqual([3, 5])
  22. })
  23. it("preserves function values", () => {
  24. const first = () => 1
  25. const second = () => 2
  26. const state = State.make(first)
  27. let value = first
  28. createRoot((dispose) => {
  29. const current = useValue(state)
  30. createComputed(() => (value = current()))
  31. state.set(second)
  32. dispose()
  33. })
  34. expect(value).toBe(second)
  35. })
  36. it("accepts a plain constant key", () => {
  37. const keyed = Keyed.make<{ readonly id: number; readonly value: string }, number>({ key: (value) => value.id })
  38. keyed.set([{ id: 1, value: "one" }])
  39. const values: Array<string | undefined> = []
  40. createRoot((dispose) => {
  41. const value = useSlot(keyed, 1)
  42. createComputed(() => values.push(value()?.value))
  43. keyed.modify(1, (item) => ({ ...item, value: "ONE" }))
  44. dispose()
  45. })
  46. expect(values).toEqual(["one", "ONE"])
  47. })
  48. it("switches keyed slots and releases obsolete subscriptions", () => {
  49. const keyed = Keyed.make<{ readonly id: number; readonly value: string }, number>({ key: (value) => value.id })
  50. keyed.set([
  51. { id: 1, value: "one" },
  52. { id: 2, value: "two" },
  53. ])
  54. const active = [0, 0]
  55. track(keyed.get(1)!, 0)
  56. track(keyed.get(2)!, 1)
  57. const values: Array<string | undefined> = []
  58. createRoot((dispose) => {
  59. const [key, setKey] = createSignal(1)
  60. const value = useSlot(keyed, key)
  61. createComputed(() => values.push(value()?.value))
  62. keyed.modify(1, (item) => ({ ...item, value: "ONE" }))
  63. keyed.insert({ id: 3, value: "three" })
  64. setKey(2)
  65. keyed.modify(1, (item) => ({ ...item, value: "ignored" }))
  66. keyed.modify(2, (item) => ({ ...item, value: "TWO" }))
  67. expect(active).toEqual([0, 1])
  68. dispose()
  69. })
  70. expect(active).toEqual([0, 0])
  71. expect(values).toEqual(["one", "ONE", "two", "TWO"])
  72. function track(slot: Readable<{ readonly id: number; readonly value: string }>, index: number) {
  73. const subscribe = slot.subscribe.bind(slot)
  74. slot.subscribe = (listener) => {
  75. active[index]++
  76. const dispose = subscribe(listener)
  77. return () => {
  78. active[index]--
  79. dispose()
  80. }
  81. }
  82. }
  83. })
  84. })