diff --git a/__test__/Model/error.multi.spec.ts b/__test__/Model/error.multi.spec.ts new file mode 100644 index 0000000..4a54398 --- /dev/null +++ b/__test__/Model/error.multi.spec.ts @@ -0,0 +1,34 @@ +/// +import { renderHook } from '@testing-library/react-hooks' +// @ts-ignore +import { ErrorModel as EM } from './errorModel' +import { Model } from '../../src' + +describe('useStore', () => { + test('create by single model error definition', async () => { + let state: any + let actions: any + let count = 0 + const ErrorModel = Model(EM) + // @ts-ignore + const { useStore, subscribe, unsubscribe } = Model({ ErrorModel }) + renderHook(() => { + ;[state, actions] = useStore('ErrorModel') + }) + expect(actions).toEqual({}) + expect(actions.increment).toBe(undefined) + // await actions.increment(3) + expect(state).toEqual({}) + // test subscribe + // @ts-ignore + subscribe('increment', () => (count += 1)) + expect(count).toBe(0) + expect(state.count).toBe(undefined) + // test unsubscribe + // @ts-ignore + unsubscribe('increment') + expect(actions).toEqual({}) + expect(state.count).toBe(undefined) + expect(count).toBe(0) + }) +}) diff --git a/__test__/Model/error.spec.ts b/__test__/Model/error.spec.ts new file mode 100644 index 0000000..e801937 --- /dev/null +++ b/__test__/Model/error.spec.ts @@ -0,0 +1,32 @@ +/// +import { renderHook } from '@testing-library/react-hooks' +// @ts-ignore +import { ErrorModel } from './errorModel' +import { Model } from '../../src' + +describe('useStore', () => { + test('create by single model definition', async () => { + let state: any + let actions: any + let count = 0 + // @ts-ignore + const { useStore, subscribe, unsubscribe } = Model(ErrorModel) + renderHook(() => { + ;[state, actions] = useStore() + }) + expect(state).toEqual({}) + expect(actions.increment).toBe(undefined) + // await actions.increment(3) + expect(state).toEqual({}) + // test subscribe + subscribe('increment', () => (count += 1)) + expect(actions).toEqual({}) + expect(count).toBe(0) + expect(state.count).toBe(undefined) + // test unsubscribe + unsubscribe('increment') + expect(actions).toEqual({}) + expect(state.count).toBe(undefined) + expect(count).toBe(0) + }) +}) diff --git a/__test__/Model/errorModel.ts b/__test__/Model/errorModel.ts new file mode 100644 index 0000000..65a5c50 --- /dev/null +++ b/__test__/Model/errorModel.ts @@ -0,0 +1,23 @@ +// Use to simulate a error model.js file +export const ErrorModel: any = { + actions: { + // @ts-ignore + add: (params, { state }) => { + return { + count: state.count + params + } + }, + // @ts-ignore + addCaller: (_, { actions }) => { + actions.add(5) + }, + // @ts-ignore + increment: params => { + // @ts-ignore + return state => { + state.count += params + } + }, + state: { count: 0 } + } +} diff --git a/package.json b/package.json index 0d44413..cca7261 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-model", - "version": "3.0.3", + "version": "3.0.4", "description": "The State management library for React", "main": "./dist/react-model.js", "umd:main": "./dist/react-model.umd.js", diff --git a/src/index.d.ts b/src/index.d.ts index b379dec..7fbb3df 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -102,6 +102,7 @@ interface Models { interface API> { __id: string + __ERROR__?: boolean useStore: ( depActions?: Array ) => [Get, getConsumerActionsType>] @@ -167,6 +168,7 @@ type ModelType< ActionKeys = any, ExtContext extends {} = {} > = { + __ERROR__?: boolean actions: { [P in keyof ActionKeys]: Action< InitStateType, diff --git a/src/index.tsx b/src/index.tsx index e0a8dbb..706c4bc 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -59,11 +59,35 @@ function Model( useStore(hash, depActions as (string[] | undefined)) } } else { + if (models.actions) { + console.error('invalid model(s) schema: ', models) + const errorFn = (fakeReturnVal?: unknown) => (..._: unknown[]) => { + return fakeReturnVal + } + // Fallback Functions + return { + __ERROR__: true, + actions: errorFn({}), + getActions: errorFn({}), + getInitialState: errorFn({}), + getState: errorFn({}), + subscribe: errorFn(), + unsubscribe: errorFn(), + useStore: errorFn([{}, {}]) + } as any + } if (initialState) { Global.State = initialState || {} } extContext && (Global.Context['__global'] = extContext) Object.entries(models).forEach(([name, model]) => { + if (model.__ERROR__) { + // Fallback State and Actions when model schema is invalid + console.error(name + " model's schema is invalid") + Global.State[name] = {} + Global.Actions[name] = {} + return + } if (!isAPI(model)) { if (!Global.State[name]) { Global.State[name] = model.state