recoil
Version:
Recoil - A state management library for React
192 lines (188 loc) • 5.83 kB
Flow
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails oncall+recoil
* @flow strict-local
* @format
*/
;
import type { RecoilValue } from '../../core/Recoil_RecoilValue';
import type { Store } from '../../core/Recoil_State';
const {
getRecoilTestFn
} = require('../../__test_utils__/Recoil_TestingUtils');
let React, useState, act, getRecoilValueAsLoadable, setRecoilValue, subscribeToRecoilValue, useRecoilState, useSetUnvalidatedAtomValues, componentThatReadsAndWritesAtom, renderElements, atom, constSelector, store: Store;
let fallbackAtom: RecoilValue<number>, hasFallbackAtom: RecoilValue<number>;
let id = 0;
const testRecoil = getRecoilTestFn(() => {
const {
makeStore
} = require('../../__test_utils__/Recoil_TestingUtils');
React = require('react');
({
useState
} = require('react'));
({
act
} = require('ReactTestUtils'));
({
getRecoilValueAsLoadable,
setRecoilValue,
subscribeToRecoilValue
} = require('../../core/Recoil_RecoilValueInterface'));
({
useRecoilState,
useSetUnvalidatedAtomValues
} = require('../../hooks/Recoil_Hooks'));
({
componentThatReadsAndWritesAtom,
renderElements
} = require('../../__test_utils__/Recoil_TestingUtils'));
atom = require('../Recoil_atom');
constSelector = require('../Recoil_constSelector');
store = makeStore();
fallbackAtom = atom<number>({
key: `fallback${id}`,
default: 1
});
hasFallbackAtom = atom<number>({
key: `hasFallback${id++}`,
default: fallbackAtom
});
subscribeToRecoilValue(store, hasFallbackAtom, () => undefined);
});
declare function get(recoilValue: any): any;
declare function set(recoilValue: any, value: any): any;
testRecoil('atomWithFallback', () => {
expect(get(hasFallbackAtom)).toBe(1);
set(fallbackAtom, 2);
expect(get(hasFallbackAtom)).toBe(2);
set(hasFallbackAtom, 3);
expect(get(hasFallbackAtom)).toBe(3);
});
describe('ReturnDefaultOrFallback', () => {
testRecoil('Returns the default', () => {
let theAtom = null;
let setUnvalidatedAtomValues;
declare function SetsUnvalidatedAtomValues(): any;
let setVisible;
declare function Switch(arg0: any): any;
declare function MyReadsAtom(arg0: any): any;
const container = renderElements(<>
<SetsUnvalidatedAtomValues />
<Switch>
<MyReadsAtom getAtom={() => theAtom} />
</Switch>
</>);
act(() => {
setUnvalidatedAtomValues(new Map().set('notDefinedYetAtomValidator', 123));
});
theAtom = atom({
key: 'notDefinedYetAtomValidator',
default: 456,
persistence_UNSTABLE: {
type: 'url',
validator: (_, returnFallback) => returnFallback
}
});
act(() => {
setVisible(true);
});
expect(container.textContent).toBe('456');
});
testRecoil('Returns the fallback', () => {
let theAtom = null;
let setUnvalidatedAtomValues;
declare function SetsUnvalidatedAtomValues(): any;
let setVisible;
declare function Switch(arg0: any): any;
declare function MyReadsAtom(arg0: any): any;
const container = renderElements(<>
<SetsUnvalidatedAtomValues />
<Switch>
<MyReadsAtom getAtom={() => theAtom} />
</Switch>
</>);
act(() => {
setUnvalidatedAtomValues(new Map().set('notDefinedYetAtomWithFallback', 123));
});
const fallback = atom<number>({
key: 'notDefinedYetAtomFallback',
default: 222
});
theAtom = atom({
key: 'notDefinedYetAtomWithFallback',
default: fallback,
persistence_UNSTABLE: {
type: 'url',
validator: (_, returnFallback) => returnFallback
}
});
act(() => {
setVisible(true);
});
expect(container.textContent).toBe('222');
});
});
testRecoil('Atom with atom fallback can store null and undefined', () => {
const myFallbackAtom = atom<?string>({
key: 'fallback for null undefined',
default: 'FALLBACK'
});
const myAtom = atom<?string>({
key: 'fallback atom with undefined',
default: myFallbackAtom
});
expect(get(myAtom)).toBe('FALLBACK');
act(() => set(myAtom, 'VALUE'));
expect(get(myAtom)).toBe('VALUE');
act(() => set(myAtom, null));
expect(get(myAtom)).toBe(null);
act(() => set(myAtom, undefined));
expect(get(myAtom)).toBe(undefined);
act(() => set(myAtom, 'VALUE'));
expect(get(myAtom)).toBe('VALUE');
});
testRecoil('Atom with selector fallback can store null and undefined', () => {
const fallbackSelector = constSelector('FALLBACK');
const myAtom = atom<?string>({
key: 'fallback selector with undefined',
default: fallbackSelector
});
expect(get(myAtom)).toBe('FALLBACK');
act(() => set(myAtom, 'VALUE'));
expect(get(myAtom)).toBe('VALUE');
act(() => set(myAtom, null));
expect(get(myAtom)).toBe(null);
act(() => set(myAtom, undefined));
expect(get(myAtom)).toBe(undefined);
act(() => set(myAtom, 'VALUE'));
expect(get(myAtom)).toBe('VALUE');
});
testRecoil('Effects', () => {
let inited = false;
const myFallbackAtom = atom({
key: 'atom with fallback effects init fallback',
default: 'FALLBACK'
});
const myAtom = atom<string>({
key: 'atom with fallback effects init',
default: myFallbackAtom,
effects_UNSTABLE: [({
setSelf
}) => {
inited = true;
setSelf('INIT');
}]
});
expect(get(myAtom)).toEqual('INIT');
expect(inited).toEqual(true);
const [ReadsWritesAtom, _, reset] = componentThatReadsAndWritesAtom(myAtom);
const c = renderElements(<ReadsWritesAtom />);
expect(c.textContent).toEqual('"INIT"');
act(reset);
expect(c.textContent).toEqual('"FALLBACK"');
});