rcrx
Version:
Rcrx is a lightweight library that provides Rx.js utilities for React applications.
116 lines (93 loc) • 3.05 kB
text/typescript
import { act, renderHook } from "@testing-library/react-hooks";
import { Observable } from "rxjs";
import { describe, expect, it } from "vitest";
import { useSubscribe } from "./subscribe";
describe("useSubscribe", () => {
it("should return default value initially and map subsequent emissions", () => {
let observer: any;
const observable = new Observable<number>((obs) => {
observer = obs;
});
const { result } = renderHook(() =>
useSubscribe<number, number>(observable, (v) => v * 2, 100)
);
expect(result.current).toBe(100);
act(() => {
observer.next(3);
});
expect(result.current).toBe(6);
});
it("should update mapping function without resubscribing", () => {
let observer: any;
let subscribeCount = 0;
let unsubscribeCount = 0;
const observable = new Observable<number>((obs) => {
subscribeCount++;
observer = obs;
return () => {
unsubscribeCount++;
};
});
const { result, rerender, unmount } = renderHook(
({ fn }: { fn: (v: number) => string }) =>
useSubscribe<number, string>(observable, fn, ""),
{ initialProps: { fn: (v: number) => `a${v}` } }
);
act(() => {
observer.next(1);
});
expect(result.current).toBe("a1");
rerender({ fn: (v: number) => `b${v}` });
act(() => {
observer.next(2);
});
expect(result.current).toBe("b2");
expect(subscribeCount).toBe(1);
expect(unsubscribeCount).toBe(0);
unmount();
expect(unsubscribeCount).toBe(1);
});
it("should resubscribe when observable changes and cleanup previous subscription", () => {
const makeObs = () => {
let observer: any;
let subscribeCount = 0;
let unsubscribeCount = 0;
const observable = new Observable<number>((obs) => {
subscribeCount++;
observer = obs;
return () => {
unsubscribeCount++;
};
});
return {
observable,
getObserver: () => observer,
getCounts: () => ({ subscribeCount, unsubscribeCount }),
} as const;
};
const o1 = makeObs();
const o2 = makeObs();
const { result, rerender, unmount } = renderHook(
({ observable }: { observable: Observable<number> }) =>
useSubscribe<number, number>(observable, (v) => v, -1),
{ initialProps: { observable: o1.observable } }
);
expect(result.current).toBe(-1);
act(() => {
o1.getObserver().next(5);
});
expect(result.current).toBe(5);
expect(o1.getCounts().subscribeCount).toBe(1);
expect(o1.getCounts().unsubscribeCount).toBe(0);
rerender({ observable: o2.observable });
// switching observables should cleanup previous and subscribe to new
expect(o1.getCounts().unsubscribeCount).toBe(1);
expect(o2.getCounts().subscribeCount).toBe(1);
act(() => {
o2.getObserver().next(10);
});
expect(result.current).toBe(10);
unmount();
expect(o2.getCounts().unsubscribeCount).toBe(1);
});
});