Add missing tests in modules/ui/utilities/recoil-scope (#3581)

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Matheus <matheus_benini@hotmail.com>
This commit is contained in:
gitstart-twenty
2024-01-23 14:16:50 +01:00
committed by GitHub
parent 562cdc563f
commit e0943b15c4
5 changed files with 359 additions and 0 deletions

View File

@ -0,0 +1,44 @@
import { createContext } from 'react';
import { renderHook } from '@testing-library/react';
import { useScopeInternalContextOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow';
import { ScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopeInternalContext';
const mockedContextValue = 'mocked-scope-id';
const MockedContext = createContext<string | null>(mockedContextValue);
const nullContext = createContext<string | null>(null);
const ERROR_MESSAGE =
'Using a scope context without a ScopeInternalContext.Provider wrapper for context';
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<MockedContext.Provider value={mockedContextValue}>
{children}
</MockedContext.Provider>
);
describe('useScopeInternalContextOrThrow', () => {
it('should work as expected', () => {
const { result } = renderHook(
() =>
useScopeInternalContextOrThrow(
MockedContext as ScopeInternalContext<{ scopeId: string }>,
),
{
wrapper: Wrapper,
},
);
expect(result.current).toBe(mockedContextValue);
});
it('should throw an error when used outside of the specified context', () => {
expect(() => {
renderHook(() =>
useScopeInternalContextOrThrow(
nullContext as ScopeInternalContext<{ scopeId: string }>,
),
);
}).toThrow(ERROR_MESSAGE);
});
});

View File

@ -0,0 +1,192 @@
import { expect } from '@storybook/test';
import { act, renderHook } from '@testing-library/react';
import {
atomFamily,
RecoilRoot,
selector,
useRecoilCallback,
useRecoilState,
useRecoilValue,
} from 'recoil';
import { StateScopeMapKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/StateScopeMapKey';
import { createFamilyStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createFamilyStateScopeMap';
import { getFamilyScopeInjector } from '@/ui/utilities/recoil-scope/utils/getFamilyScopeInjector';
import { getScopeInjector } from '@/ui/utilities/recoil-scope/utils/getScopeInjector';
import { getSelectorScopeInjector } from '@/ui/utilities/recoil-scope/utils/getSelectorScopeInjector';
import { useScopedState } from '../useScopedState';
const scopeId = 'scopeId';
// scoped state
const defaultScopedState = 'defaultString';
const scopedState = atomFamily<string, StateScopeMapKey>({
key: 'ScopedStateKey',
default: defaultScopedState,
});
const scopedStateScopeInjector = getScopeInjector(scopedState);
// scoped selector
const anotherScopedState = atomFamily<number[], StateScopeMapKey>({
key: 'ScopedStateKey',
default: [1, 2, 3, 4, 5],
});
const scopedSelector = ({ scopeId }: StateScopeMapKey) =>
selector({
key: 'FilteredState',
get: ({ get }) => {
const scopedStateValue = get(anotherScopedState({ scopeId }));
return scopedStateValue.filter((value) => value % 2 === 0);
},
});
const selectorScopeInjector = getSelectorScopeInjector(scopedSelector);
// family state
const defaultValue = 'defaultString';
const scopedFamilyState = createFamilyStateScopeMap<string, string>({
key: 'FamilyStateKey',
defaultValue,
});
const familyScopeInjector = getFamilyScopeInjector(scopedFamilyState);
describe('useScopedState', () => {
it('should get scoped state', () => {
const {
result: {
current: { getScopedState },
},
} = renderHook(() => useScopedState(scopeId));
const scopedState = getScopedState(scopedStateScopeInjector);
const { result } = renderHook(
() => {
const [scoped, setScoped] = useRecoilState(scopedState);
return { scoped, setScoped };
},
{
wrapper: RecoilRoot,
},
);
expect(result.current.scoped).toBe(defaultScopedState);
const newValue = 'anotherValue';
act(() => {
result.current.setScoped(newValue);
});
expect(result.current.scoped).toBe(newValue);
});
it('should get scoped snapshot value', () => {
const {
result: {
current: { getScopedSnapshotValue },
},
} = renderHook(() => useScopedState(scopeId));
const { result } = renderHook(
() =>
useRecoilCallback(
({ snapshot }) =>
() =>
getScopedSnapshotValue(snapshot, scopedStateScopeInjector),
)(),
{ wrapper: RecoilRoot },
);
expect(result.current).toBe(defaultScopedState);
});
it('should get scoped selector', () => {
const {
result: {
current: { getScopedSelector },
},
} = renderHook(() => useScopedState(scopeId));
const recoilValue = getScopedSelector(selectorScopeInjector);
const { result } = renderHook(() => useRecoilValue(recoilValue), {
wrapper: RecoilRoot,
});
expect(result.current).toEqual([2, 4]);
});
it('should get scoped selector snapshot value', () => {
const {
result: {
current: { getScopedSelectorSnapshotValue },
},
} = renderHook(() => useScopedState(scopeId));
const { result } = renderHook(
() =>
useRecoilCallback(
({ snapshot }) =>
() =>
getScopedSelectorSnapshotValue(snapshot, selectorScopeInjector),
)(),
{ wrapper: RecoilRoot },
);
expect(result.current).toEqual([2, 4]);
});
it('should get scoped family state', () => {
const {
result: {
current: { getScopedFamilyState },
},
} = renderHook(() => useScopedState(scopeId));
const scopedFamilyState = getScopedFamilyState(familyScopeInjector);
const { result } = renderHook(
() => {
const [familyState, setFamilyState] = useRecoilState(
scopedFamilyState('familyKey'),
);
return { familyState, setFamilyState };
},
{
wrapper: RecoilRoot,
},
);
expect(result.current.familyState).toBe('defaultString');
const newValue = 'newValue';
act(() => {
result.current.setFamilyState(newValue);
});
expect(result.current.familyState).toBe(newValue);
});
it('should get scoped family snapshot value', () => {
const {
result: {
current: { getScopedFamilySnapshotValue },
},
} = renderHook(() => useScopedState(scopeId));
const { result } = renderHook(
() =>
useRecoilCallback(
({ snapshot }) =>
() =>
getScopedFamilySnapshotValue(snapshot, familyScopeInjector),
)(),
{ wrapper: RecoilRoot },
);
expect(result.current('sampleKey')).toBe('defaultString');
});
});

View File

@ -0,0 +1,40 @@
import { act, renderHook } from '@testing-library/react';
import { RecoilRoot, useRecoilState } from 'recoil';
import { createFamilyStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createFamilyStateScopeMap';
import { getFamilyScopeInjector } from '../getFamilyScopeInjector';
const defaultValue = 'defaultString';
const testState = createFamilyStateScopeMap<string, string>({
key: 'familyStateKey',
defaultValue,
});
describe('getFamilyScopeInjector', () => {
it('should return a scoped family state', () => {
const familyScopeInjector = getFamilyScopeInjector(testState);
const familyState = familyScopeInjector('scopeId', 'familyKey');
const { result } = renderHook(
() => {
const [family, setFamily] = useRecoilState(familyState);
return { family, setFamily };
},
{
wrapper: RecoilRoot,
},
);
expect(result.current.family).toBe(defaultValue);
const newValue = 'anotherValue';
act(() => {
result.current.setFamily(newValue);
});
expect(result.current.family).toBe(newValue);
});
});

View File

@ -0,0 +1,45 @@
import { act, renderHook } from '@testing-library/react';
import { atomFamily, RecoilRoot, useRecoilState } from 'recoil';
import { getScopeInjector } from '../getScopeInjector';
const defaultValue = 'defaultString';
const scopedState = atomFamily<
string,
{
scopeId: string;
}
>({
key: 'myStateKey',
default: defaultValue,
});
describe('getScopeInjector', () => {
it('should return the scoped state for the given scopeId', () => {
const scopeInjector = getScopeInjector(scopedState);
const scopeId = 'scopeId';
const recoilState = scopeInjector(scopeId);
const { result } = renderHook(
() => {
const [recoil, setRecoil] = useRecoilState(recoilState);
return { recoil, setRecoil };
},
{
wrapper: RecoilRoot,
},
);
expect(result.current.recoil).toBe(defaultValue);
const newValue = 'anotherValue';
act(() => {
result.current.setRecoil(newValue);
});
expect(result.current.recoil).toBe(newValue);
});
});

View File

@ -0,0 +1,38 @@
import { renderHook } from '@testing-library/react';
import { atomFamily, RecoilRoot, selector, useRecoilValue } from 'recoil';
import { StateScopeMapKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/StateScopeMapKey';
import { getSelectorScopeInjector } from '../getSelectorScopeInjector';
const scopedState = atomFamily<
number[],
{
scopeId: string;
}
>({
key: 'myStateKey',
default: [1, 2, 3, 4, 5],
});
const scopedSelector = ({ scopeId }: StateScopeMapKey) =>
selector({
key: 'FilteredState',
get: ({ get }) => {
const scopedStateValue = get(scopedState({ scopeId }));
return scopedStateValue.filter((value) => value % 2 === 0);
},
});
describe('getSelectorScopeInjector', () => {
it('should return a valid SelectorScopeInjector', () => {
const selectorScopeInjector = getSelectorScopeInjector(scopedSelector);
const recoilValue = selectorScopeInjector('scopeId');
const { result } = renderHook(() => useRecoilValue(recoilValue), {
wrapper: RecoilRoot,
});
expect(result.current).toEqual([2, 4]);
});
});