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: React.FC = ({ children }) => {children} ;
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
{sharedText}
;
};
const UpdateComponent = () => {
const [, setSharedText] = useSharedText();
return (
setSharedText('changed')}>
UPDATE
);
};
it('should be in sync when under the same provider', () => {
const { baseElement, getByText } = render(
);
expect(baseElement.innerHTML).toBe(
''
);
fireEvent.click(getByText('UPDATE'));
expect(baseElement.innerHTML).toBe(
''
);
});
it('should be in update independently when under different providers', () => {
const { baseElement, getByText } = render(
<>
>
);
expect(baseElement.innerHTML).toBe(
''
);
fireEvent.click(getByText('UPDATE'));
expect(baseElement.innerHTML).toBe(
''
);
});
it('should not update component that do not use the state context', () => {
let renderCount = 0;
const StaticComponent = () => {
renderCount++;
return static
;
};
const { baseElement, getByText } = render(
<>
>
);
expect(baseElement.innerHTML).toBe(
''
);
fireEvent.click(getByText('UPDATE'));
expect(baseElement.innerHTML).toBe(
''
);
expect(renderCount).toBe(1);
});
it('should override initialValue', () => {
const { baseElement } = render(
<>
>
);
expect(baseElement.innerHTML).toBe('');
});
});