mirror of
https://github.com/streamich/react-use.git
synced 2025-12-08 18:02:14 +00:00
153 lines
4.3 KiB
TypeScript
153 lines
4.3 KiB
TypeScript
import React from 'react';
|
|
import { render, fireEvent } from '@testing-library/react';
|
|
import { act, renderHook } from '@testing-library/react-hooks';
|
|
import createStateContext from '../src/factory/createStateContext';
|
|
|
|
it('should create a hook and a provider', () => {
|
|
const [useSharedNumber, SharedNumberProvider] = createStateContext(0);
|
|
expect(useSharedNumber).toBeInstanceOf(Function);
|
|
expect(SharedNumberProvider).toBeInstanceOf(Function);
|
|
});
|
|
|
|
describe('when using created hook', () => {
|
|
it('should throw out of a provider', () => {
|
|
const [useSharedText] = createStateContext('init');
|
|
const { result } = renderHook(() => useSharedText());
|
|
expect(result.error).toEqual(new Error('useStateContext must be used inside a StateProvider.'));
|
|
});
|
|
|
|
const setUp = () => {
|
|
const [useSharedText, SharedTextProvider] = createStateContext('init');
|
|
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
<SharedTextProvider>{children}</SharedTextProvider>
|
|
);
|
|
return renderHook(() => useSharedText(), { wrapper });
|
|
};
|
|
|
|
it('should init state and updater', () => {
|
|
const { result } = setUp();
|
|
const [sharedText, setSharedText] = result.current;
|
|
|
|
expect(sharedText).toEqual('init');
|
|
expect(setSharedText).toBeInstanceOf(Function);
|
|
});
|
|
|
|
it('should update the state', () => {
|
|
const { result } = setUp();
|
|
const [, setSharedText] = result.current;
|
|
|
|
act(() => setSharedText('changed'));
|
|
|
|
const [sharedText] = result.current;
|
|
|
|
expect(sharedText).toEqual('changed');
|
|
});
|
|
});
|
|
|
|
describe('when using among multiple components', () => {
|
|
const [useSharedText, SharedTextProvider] = createStateContext('init');
|
|
|
|
const DisplayComponent = () => {
|
|
const [sharedText] = useSharedText();
|
|
return <p>{sharedText}</p>;
|
|
};
|
|
|
|
const UpdateComponent = () => {
|
|
const [, setSharedText] = useSharedText();
|
|
return (
|
|
<button type="button" onClick={() => setSharedText('changed')}>
|
|
UPDATE
|
|
</button>
|
|
);
|
|
};
|
|
|
|
it('should be in sync when under the same provider', () => {
|
|
const { baseElement, getByText } = render(
|
|
<SharedTextProvider>
|
|
<DisplayComponent />
|
|
<DisplayComponent />
|
|
<UpdateComponent />
|
|
</SharedTextProvider>
|
|
);
|
|
|
|
expect(baseElement.innerHTML).toBe(
|
|
'<div><p>init</p><p>init</p><button type="button">UPDATE</button></div>'
|
|
);
|
|
|
|
fireEvent.click(getByText('UPDATE'));
|
|
|
|
expect(baseElement.innerHTML).toBe(
|
|
'<div><p>changed</p><p>changed</p><button type="button">UPDATE</button></div>'
|
|
);
|
|
});
|
|
|
|
it('should be in update independently when under different providers', () => {
|
|
const { baseElement, getByText } = render(
|
|
<>
|
|
<SharedTextProvider>
|
|
<DisplayComponent />
|
|
</SharedTextProvider>
|
|
<SharedTextProvider>
|
|
<DisplayComponent />
|
|
<UpdateComponent />
|
|
</SharedTextProvider>
|
|
</>
|
|
);
|
|
|
|
expect(baseElement.innerHTML).toBe(
|
|
'<div><p>init</p><p>init</p><button type="button">UPDATE</button></div>'
|
|
);
|
|
|
|
fireEvent.click(getByText('UPDATE'));
|
|
|
|
expect(baseElement.innerHTML).toBe(
|
|
'<div><p>init</p><p>changed</p><button type="button">UPDATE</button></div>'
|
|
);
|
|
});
|
|
|
|
it('should not update component that do not use the state context', () => {
|
|
let renderCount = 0;
|
|
const StaticComponent = () => {
|
|
renderCount++;
|
|
return <p>static</p>;
|
|
};
|
|
|
|
const { baseElement, getByText } = render(
|
|
<>
|
|
<SharedTextProvider>
|
|
<StaticComponent />
|
|
<DisplayComponent />
|
|
<UpdateComponent />
|
|
</SharedTextProvider>
|
|
</>
|
|
);
|
|
|
|
expect(baseElement.innerHTML).toBe(
|
|
'<div><p>static</p><p>init</p><button type="button">UPDATE</button></div>'
|
|
);
|
|
|
|
fireEvent.click(getByText('UPDATE'));
|
|
|
|
expect(baseElement.innerHTML).toBe(
|
|
'<div><p>static</p><p>changed</p><button type="button">UPDATE</button></div>'
|
|
);
|
|
|
|
expect(renderCount).toBe(1);
|
|
});
|
|
|
|
it('should override initialValue', () => {
|
|
const { baseElement } = render(
|
|
<>
|
|
<SharedTextProvider>
|
|
<DisplayComponent />
|
|
</SharedTextProvider>
|
|
<SharedTextProvider initialValue={'other'}>
|
|
<DisplayComponent />
|
|
</SharedTextProvider>
|
|
</>
|
|
);
|
|
|
|
expect(baseElement.innerHTML).toBe('<div><p>init</p><p>other</p></div>');
|
|
});
|
|
});
|