From 007f684dec6ef919bb9c69d99c8a28a323fecc2f Mon Sep 17 00:00:00 2001 From: streamich Date: Sun, 23 Jun 2019 12:45:59 +0200 Subject: [PATCH] =?UTF-8?q?test:=20=F0=9F=92=8D=20improve=20useObservable?= =?UTF-8?q?=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/__tests__/useObservable-layout.spec.ts | 21 ++++++ src/__tests__/useObservable.test.tsx | 74 +++++++++++++++++++++- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/__tests__/useObservable-layout.spec.ts diff --git a/src/__tests__/useObservable-layout.spec.ts b/src/__tests__/useObservable-layout.spec.ts new file mode 100644 index 00000000..28dd0c77 --- /dev/null +++ b/src/__tests__/useObservable-layout.spec.ts @@ -0,0 +1,21 @@ +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import { Subject } from 'rxjs'; +import { useObservable } from '..'; +import useIsomorphicLayoutEffect from '../useIsomorphicLayoutEffect'; + +jest.mock('../useIsomorphicLayoutEffect'); + +test('uses', async () => { + const subject = new Subject(); + const container = document.createElement('div'); + + const Demo = ({ obs }) => { + const value = useObservable(obs); + return React.createElement(React.Fragment, {}, value); + }; + + expect(useIsomorphicLayoutEffect).toHaveBeenCalledTimes(0); + ReactDOM.render(React.createElement(Demo, { obs: subject }), container); + expect(useIsomorphicLayoutEffect).toHaveBeenCalledTimes(1); +}); diff --git a/src/__tests__/useObservable.test.tsx b/src/__tests__/useObservable.test.tsx index 6bba8c87..4166c986 100644 --- a/src/__tests__/useObservable.test.tsx +++ b/src/__tests__/useObservable.test.tsx @@ -1,7 +1,21 @@ +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; import { act, renderHook } from 'react-hooks-testing-library'; import { Subject } from 'rxjs'; import { useObservable } from '..'; +let container: HTMLDivElement | null; + +beforeEach(() => { + container = document.createElement('div'); + document.body.appendChild(container); +}); + +afterEach(() => { + document.body.removeChild(container!); + container = null; +}); + test('default initial value is undefined', () => { const subject$ = new Subject(); const { result } = renderHook(() => useObservable(subject$)); @@ -32,4 +46,62 @@ test('returns the latest value of observables', () => { expect(result.current).toBe(400); }); -xtest('subscribes to observable only once', () => {}); +test('subscribes to observable only once', async () => { + const subject = new Subject(); + const spy = jest.spyOn(subject, 'subscribe'); + + expect(spy).toHaveBeenCalledTimes(0); + + const Demo = ({ obs }) => { + const value = useObservable(obs); + return <>{value}; + }; + + ReactDOM.render(, container); + + expect(spy).toHaveBeenCalledTimes(1); + + await new Promise(r => setTimeout(r, 1)); + act(() => { + subject.next('a'); + }); + await new Promise(r => setTimeout(r, 1)); + act(() => { + subject.next('b'); + }); + + expect(spy).toHaveBeenCalledTimes(1); +}); + +test('re-renders component as obsevable changes', async () => { + const subject = new Subject(); + + let cnt = 0; + const Demo = ({ obs }) => { + cnt++; + const value = useObservable(obs); + return <>{value}; + }; + + ReactDOM.render(, container); + + await new Promise(r => setTimeout(r, 1)); + expect(cnt).toBe(1); + expect(container.innerHTML).toBe(''); + + act(() => { + subject.next('a'); + }); + + await new Promise(r => setTimeout(r, 1)); + expect(cnt).toBe(2); + expect(container.innerHTML).toBe('a'); + + act(() => { + subject.next('b'); + }); + + await new Promise(r => setTimeout(r, 1)); + expect(cnt).toBe(3); + expect(container.innerHTML).toBe('b'); +});