recoil
Version:
Recoil - A state management library for React
124 lines (121 loc) • 3.96 kB
Flow
/**
* Copyright (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+recoil
* @flow strict-local
* @format
*/
;
import type { Store } from '../Recoil_State';
const {
getRecoilTestFn
} = require('../../testing/Recoil_TestingUtils');
let React, ReactDOM, act, useSetRecoilState, atom, constSelector, selector, ReadsAtom, renderElements, RecoilRoot, useStoreRef;
const testRecoil = getRecoilTestFn(() => {
React = require('React');
ReactDOM = require('ReactDOM');
({
act
} = require('ReactTestUtils'));
({
useSetRecoilState
} = require('../../hooks/Recoil_Hooks'));
atom = require('../../recoil_values/Recoil_atom');
constSelector = require('../../recoil_values/Recoil_constSelector');
selector = require('../../recoil_values/Recoil_selector');
({
ReadsAtom,
renderElements
} = require('../../testing/Recoil_TestingUtils'));
({
RecoilRoot
} = require('../Recoil_RecoilRoot.react'));
({
useStoreRef
} = require('../Recoil_RecoilRoot.react'));
});
describe('initializeState', () => {
testRecoil('initialize atom', () => {
const myAtom = atom({
key: 'RecoilRoot - initializeState - atom',
default: 'DEFAULT'
});
const mySelector = constSelector(myAtom);
declare function initializeState(arg0: any): any;
const container = document.createElement('div');
act(() => {
ReactDOM.render(<RecoilRoot initializeState={initializeState}>
<ReadsAtom atom={myAtom} />
<ReadsAtom atom={mySelector} />
</RecoilRoot>, container);
});
expect(container.textContent).toEqual('"INITIALIZE""INITIALIZE"');
});
testRecoil('initialize selector', () => {
const myAtom = atom({
key: 'RecoilRoot - initializeState - selector',
default: 'DEFAULT'
});
const mySelector = selector({
key: 'RecoilRoot - initializeState - selector selector',
get: ({
get
}) => get(myAtom),
set: ({
set
}, newValue) => set(myAtom, newValue)
});
declare function initializeState(arg0: any): any;
const container = document.createElement('div');
act(() => {
ReactDOM.render(<RecoilRoot initializeState={initializeState}>
<ReadsAtom atom={myAtom} />
<ReadsAtom atom={mySelector} />
</RecoilRoot>, container);
});
expect(container.textContent).toEqual('"INITIALIZE""INITIALIZE"');
});
testRecoil('initialize with nested store', () => {
declare var GetStore: (arg0: {
children: (Store) => React.Node
}) => any;
const container = document.createElement('div');
act(() => {
ReactDOM.render(<RecoilRoot>
<GetStore>
{storeA => <RecoilRoot store_INTERNAL={storeA}>
<GetStore>
{storeB => {
expect(storeA === storeB).toBe(true);
return 'NESTED_ROOT/';
}}
</GetStore>
</RecoilRoot>}
</GetStore>
ROOT
</RecoilRoot>, container);
});
expect(container.textContent).toEqual('NESTED_ROOT/ROOT');
});
});
testRecoil('Impure state updater functions that trigger atom updates are detected', () => {
// This test ensures that we throw a clean error rather than mysterious breakage
// if the user supplies a state updater function that triggers another update
// within its execution. These state updater functions are supposed to be pure.
// We can't detect all forms of impurity but this one in particular will make
// Recoil break, so we detect it and throw an error.
const atomA = atom({
key: 'RecoilRoot/impureUpdater/a',
default: 0
});
const atomB = atom({
key: 'RecoilRoot/impureUpdater/b',
default: 0
});
let update;
declare function Component(): any;
renderElements(<Component />);
expect(() => act(() => {
update();
})).toThrow('pure function');
});