Skip to content

Commit

Permalink
refactor store generation
Browse files Browse the repository at this point in the history
  • Loading branch information
SKarolFolio committed Dec 2, 2024
1 parent 2c88a04 commit 62e7550
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 76 deletions.
18 changes: 7 additions & 11 deletions src/store/loadingState.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import { IS_PROD_MODE } from '@common/constants/bundle.constants';
import { StateCreator } from 'zustand';
import { createBaseSlice, SliceState } from './utils/slice';
import { generateStore } from './utils/storeCreator';

export type LoadingState = SliceState<'isLoading', boolean>;

const STORE_NAME = 'LoadingState';

export const useLoadingStateStore = create<LoadingState>()(
devtools(
(...args) => ({
...createBaseSlice({ basic: 'isLoading' }, false)(...args),
}),
{ name: 'Linked Data Editor', store: STORE_NAME, enabled: !IS_PROD_MODE },
),
);
const loadingStateStore: StateCreator<LoadingState, [['zustand/devtools', never]], []> = (...args) => ({
...createBaseSlice({ basic: 'isLoading' }, false)(...args),
});

export const useLoadingStateStore = generateStore(loadingStateStore, STORE_NAME);
22 changes: 9 additions & 13 deletions src/store/marcPreview.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import { IS_PROD_MODE } from '@common/constants/bundle.constants';
import { StateCreator } from 'zustand';
import { createBaseSlice, SliceState } from './utils/slice';
import { generateStore } from './utils/storeCreator';

type MarcPreviewData = MarcDTO | null;
type MarcPreviewMetaData = MarcPreviewMetadata | null;
Expand All @@ -12,13 +11,10 @@ export type MarcPreviewState = SliceState<'basicValue', any> &

const STORE_NAME = 'MarcPreview';

export const useMarcPreviewStore = create<MarcPreviewState>()(
devtools(
(...args) => ({
...createBaseSlice({ basic: 'basicValue' }, null)(...args),
...createBaseSlice({ basic: 'complexValue' }, null as MarcPreviewData)(...args),
...createBaseSlice({ basic: 'metaData' }, null as MarcPreviewMetaData)(...args),
}),
{ name: 'Linked Data Editor', store: STORE_NAME, enabled: !IS_PROD_MODE },
),
);
const marcPreviewStore: StateCreator<MarcPreviewState, [['zustand/devtools', never]], []> = (...args) => ({
...createBaseSlice({ basic: 'basicValue' }, null)(...args),
...createBaseSlice({ basic: 'complexValue' }, null as MarcPreviewData)(...args),
...createBaseSlice({ basic: 'metaData' }, null as MarcPreviewMetaData)(...args),
});

export const useMarcPreviewStore = generateStore(marcPreviewStore, STORE_NAME);
32 changes: 14 additions & 18 deletions src/store/status.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import { IS_PROD_MODE } from '@common/constants/bundle.constants';
import { StateCreator } from 'zustand';
import { createBaseSlice, SliceState } from './utils/slice';
import { generateStore } from './utils/storeCreator';

type LastSavedRecordId = string | null;

Expand All @@ -12,18 +11,15 @@ export type StatusState = SliceState<'lastSavedRecordId', LastSavedRecordId> &

const STORE_NAME = 'Status';

export const useStatusStore = create<StatusState>()(
devtools(
(...args) => ({
...createBaseSlice({ basic: 'lastSavedRecordId' }, null as LastSavedRecordId)(...args),
...createBaseSlice({ basic: 'isEditedRecord' }, false)(...args),
...createBaseSlice({ basic: 'recordStatus' }, { type: undefined } as RecordStatus)(...args),
...createBaseSlice<'statusMessages', StatusEntry[], 'statusMessage', StatusEntry>(
{ basic: 'statusMessages', singleItem: 'statusMessage' },
[] as StatusEntry[],
true,
)(...args),
}),
{ name: 'Linked Data Editor', store: STORE_NAME, enabled: !IS_PROD_MODE },
),
);
const statusStore: StateCreator<StatusState, [['zustand/devtools', never]], []> = (...args) => ({
...createBaseSlice({ basic: 'lastSavedRecordId' }, null as LastSavedRecordId)(...args),
...createBaseSlice({ basic: 'isEditedRecord' }, false)(...args),
...createBaseSlice({ basic: 'recordStatus' }, { type: undefined } as RecordStatus)(...args),
...createBaseSlice<'statusMessages', StatusEntry[], 'statusMessage', StatusEntry>(
{ basic: 'statusMessages', singleItem: 'statusMessage' },
[] as StatusEntry[],
true,
)(...args),
});

export const useStatusStore = generateStore(statusStore, STORE_NAME);
8 changes: 8 additions & 0 deletions src/store/utils/storeCreator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IS_PROD_MODE } from '@common/constants/bundle.constants';
import { create, StateCreator } from 'zustand';
import { devtools } from 'zustand/middleware';

const STORE_NAME = 'Linked Data Editor';

export const generateStore = <T>(store: StateCreator<T, [['zustand/devtools', never]], []>, name: string) =>
create<T>()(devtools(store, { name: STORE_NAME, store: name, enabled: !IS_PROD_MODE }));
55 changes: 21 additions & 34 deletions src/test/__tests__/store/utils/slice.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { createBaseSlice } from '@src/store/utils/slice';
describe('createBaseSlice', () => {
type KeyBasic = 'testKey';
type KeySingleItem = 'item';

const keys = { basic: 'testKey' };
const initialValue = 'initialValue';
const set = jest.fn();
const get = jest.fn();
let store: any;
Expand All @@ -12,40 +15,28 @@ describe('createBaseSlice', () => {
});

test('"set" method updates the state', () => {
const keys = { basic: 'testKey' };
const initialValue = 'initialValue';
const sliceTitle = 'testSlice';
const baseSlice = createBaseSlice(keys, initialValue, sliceTitle)(set, get, store);
const baseSlice = createBaseSlice(keys, initialValue)(set, get, store);

baseSlice.setTestKey('newValue');
expect(set).toHaveBeenCalledWith({ testKey: 'newValue' }, false, 'testSlice/setTestKey');
expect(set).toHaveBeenCalledWith({ testKey: 'newValue' }, false, 'setTestKey');
});

test('"reset" method resets the state to initial value', () => {
const keys = { basic: 'testKey' };
const initialValue = 'initialValue';
const sliceTitle = 'testSlice';
const baseSlice = createBaseSlice(keys, initialValue, sliceTitle)(set, get, store);
const baseSlice = createBaseSlice(keys, initialValue)(set, get, store);

baseSlice.resetTestKey();
expect(set).toHaveBeenCalledWith({ testKey: initialValue }, false, 'testSlice/resetTestKey');
expect(set).toHaveBeenCalledWith({ testKey: initialValue }, false, 'resetTestKey');
});

describe('"add" method', () => {
const keys = { basic: 'testKey' as KeyBasic, singleItem: 'item' as KeySingleItem };

test('updates the state when canAddSingleItem is true', () => {
const initialValue = ['initialValue'];
const sliceTitle = 'testSlice';
const baseSlice = createBaseSlice<'testKey', string[], 'item', string>(
keys,
initialValue,
sliceTitle,
true,
)(set, get, store);
const baseSlice = createBaseSlice<'testKey', string[], 'item', string>(keys, initialValue, true)(set, get, store);

baseSlice.addItem?.('newItem');
expect(set).toHaveBeenCalledWith(expect.any(Function), false, 'testSlice/addTestKey');
expect(set).toHaveBeenCalledWith(expect.any(Function), false, 'addTestKey');

const state = { testKey: ['initialValue'] };
const updater = set.mock.calls[0][0];
Expand All @@ -55,16 +46,14 @@ describe('createBaseSlice', () => {
test('updates the state when value is an object', () => {
type StateEntry = Record<string, string>;
const initialValue = { key1: 'value_1' } as StateEntry;
const sliceTitle = 'testSlice';
const baseSlice = createBaseSlice<KeyBasic, StateEntry, KeySingleItem, StateEntry>(
keys,
initialValue,
sliceTitle,
true,
)(set, get, store);
const baseSlice = createBaseSlice<KeyBasic, StateEntry, KeySingleItem, StateEntry>(keys, initialValue, true)(
set,
get,
store,
);

baseSlice.addItem?.({ key2: 'value_2' });
expect(set).toHaveBeenCalledWith(expect.any(Function), false, 'testSlice/addTestKey');
expect(set).toHaveBeenCalledWith(expect.any(Function), false, 'addTestKey');

const state = { testKey: { key1: 'value_1' } };
const updater = set.mock.calls[0][0];
Expand All @@ -75,16 +64,14 @@ describe('createBaseSlice', () => {

test('updates the state when value is a Set', () => {
const initialValue = new Set(['value_1']);
const sliceTitle = 'testSlice';
const baseSlice = createBaseSlice<KeyBasic, Set<string>, KeySingleItem, string>(
keys,
initialValue,
sliceTitle,
true,
)(set, get, store);
const baseSlice = createBaseSlice<KeyBasic, Set<string>, KeySingleItem, string>(keys, initialValue, true)(
set,
get,
store,
);

baseSlice.addItem?.('value_2');
expect(set).toHaveBeenCalledWith(expect.any(Function), false, 'testSlice/addTestKey');
expect(set).toHaveBeenCalledWith(expect.any(Function), false, 'addTestKey');

const state = { testKey: new Set(['value_1']) };
const updater = set.mock.calls[0][0];
Expand Down

0 comments on commit 62e7550

Please sign in to comment.