react-rxjs/test/connectObservable.test.tsx
Josep M Sobrepere 64989d0cee v0.2.0-alpha.1
2020-05-29 01:32:37 +02:00

110 lines
3.2 KiB
TypeScript

import { connectObservable } from "../src"
import { NEVER, from, of, defer, Subject } from "rxjs"
import { renderHook, act } from "@testing-library/react-hooks"
import { useState, useLayoutEffect } from "react"
const wait = (ms: number) => new Promise(res => setTimeout(res, ms))
describe("connectObservable", () => {
it("returns the initial value when the stream has not emitted anything", async () => {
const [useSomething] = connectObservable(NEVER, "initialValue")
const { result } = renderHook(() => useSomething())
await act(async () => {
await wait(0)
})
expect(result.current).toBe("initialValue")
})
it("returns the latest emitted value", async () => {
const [useNumber] = connectObservable(of(1), 0)
const { result } = renderHook(() => useNumber())
await act(async () => {
await wait(0)
})
expect(result.current).toBe(1)
})
it("sets the initial state synchronously if it's available", async () => {
const observable$ = of(1)
const [useLatestNumber] = connectObservable(observable$, 0)
const { result, unmount } = renderHook(() => useLatestNumber())
expect(result.current).toEqual(1)
unmount()
})
it("batches synchronous updates", async () => {
const observable$ = new Subject<number>()
const [useLatestNumber] = connectObservable(observable$, 0)
const useLatestNumberTest = () => {
const latestNumber = useLatestNumber()
const [emittedValues, setEmittedValues] = useState<number[]>([])
useLayoutEffect(() => {
setEmittedValues(prev => [...prev, latestNumber])
}, [latestNumber])
return emittedValues
}
const { result } = renderHook(() => useLatestNumberTest())
expect(result.current).toEqual([0])
await act(async () => {
observable$.next(0)
observable$.next(1)
observable$.next(2)
observable$.next(3)
observable$.next(4)
observable$.next(5)
await wait(0)
})
expect(result.current).toEqual([0, 5])
})
it("shares the source subscription until the refCount has stayed at zero for the grace-period", async () => {
let nInitCount = 0
const observable$ = defer(() => {
nInitCount += 1
return from([1, 2, 3, 4, 5])
})
const [useLatestNumber] = connectObservable(observable$, 0, {
unsubscribeGraceTime: 100,
})
const { unmount } = renderHook(() => useLatestNumber())
await act(async () => {
await wait(0)
})
const { unmount: unmount2 } = renderHook(() => useLatestNumber())
await act(async () => {
await wait(0)
})
const { unmount: unmount3 } = renderHook(() => useLatestNumber())
await act(async () => {
await wait(0)
})
expect(nInitCount).toBe(1)
unmount()
unmount2()
unmount3()
await act(async () => {
await wait(90)
})
const { unmount: unmount4 } = renderHook(() => useLatestNumber())
await act(async () => {
await wait(0)
})
expect(nInitCount).toBe(1)
unmount4()
await act(async () => {
await wait(101)
})
renderHook(() => useLatestNumber())
await act(async () => {
await wait(0)
})
expect(nInitCount).toBe(2)
})
})