Skip to content

Commit a217007

Browse files
feat(fallback): add fallback logic and error hint for invalid model (#144)
* feat(fallback): add fallback logic and error hint for invalid model * test(coverage): add testcase to improve test coverage
1 parent f347240 commit a217007

File tree

6 files changed

+116
-1
lines changed

6 files changed

+116
-1
lines changed

__test__/Model/error.multi.spec.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/// <reference path="../index.d.ts" />
2+
import { renderHook } from '@testing-library/react-hooks'
3+
// @ts-ignore
4+
import { ErrorModel as EM } from './errorModel'
5+
import { Model } from '../../src'
6+
7+
describe('useStore', () => {
8+
test('create by single model error definition', async () => {
9+
let state: any
10+
let actions: any
11+
let count = 0
12+
const ErrorModel = Model(EM)
13+
// @ts-ignore
14+
const { useStore, subscribe, unsubscribe } = Model({ ErrorModel })
15+
renderHook(() => {
16+
;[state, actions] = useStore('ErrorModel')
17+
})
18+
expect(actions).toEqual({})
19+
expect(actions.increment).toBe(undefined)
20+
// await actions.increment(3)
21+
expect(state).toEqual({})
22+
// test subscribe
23+
// @ts-ignore
24+
subscribe('increment', () => (count += 1))
25+
expect(count).toBe(0)
26+
expect(state.count).toBe(undefined)
27+
// test unsubscribe
28+
// @ts-ignore
29+
unsubscribe('increment')
30+
expect(actions).toEqual({})
31+
expect(state.count).toBe(undefined)
32+
expect(count).toBe(0)
33+
})
34+
})

__test__/Model/error.spec.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/// <reference path="../index.d.ts" />
2+
import { renderHook } from '@testing-library/react-hooks'
3+
// @ts-ignore
4+
import { ErrorModel } from './errorModel'
5+
import { Model } from '../../src'
6+
7+
describe('useStore', () => {
8+
test('create by single model definition', async () => {
9+
let state: any
10+
let actions: any
11+
let count = 0
12+
// @ts-ignore
13+
const { useStore, subscribe, unsubscribe } = Model(ErrorModel)
14+
renderHook(() => {
15+
;[state, actions] = useStore()
16+
})
17+
expect(state).toEqual({})
18+
expect(actions.increment).toBe(undefined)
19+
// await actions.increment(3)
20+
expect(state).toEqual({})
21+
// test subscribe
22+
subscribe('increment', () => (count += 1))
23+
expect(actions).toEqual({})
24+
expect(count).toBe(0)
25+
expect(state.count).toBe(undefined)
26+
// test unsubscribe
27+
unsubscribe('increment')
28+
expect(actions).toEqual({})
29+
expect(state.count).toBe(undefined)
30+
expect(count).toBe(0)
31+
})
32+
})

__test__/Model/errorModel.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Use to simulate a error model.js file
2+
export const ErrorModel: any = {
3+
actions: {
4+
// @ts-ignore
5+
add: (params, { state }) => {
6+
return {
7+
count: state.count + params
8+
}
9+
},
10+
// @ts-ignore
11+
addCaller: (_, { actions }) => {
12+
actions.add(5)
13+
},
14+
// @ts-ignore
15+
increment: params => {
16+
// @ts-ignore
17+
return state => {
18+
state.count += params
19+
}
20+
},
21+
state: { count: 0 }
22+
}
23+
}

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-model",
3-
"version": "3.0.3",
3+
"version": "3.0.4",
44
"description": "The State management library for React",
55
"main": "./dist/react-model.js",
66
"umd:main": "./dist/react-model.umd.js",

src/index.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ interface Models<State = any, ActionKeys = any, ExtContext extends {} = {}> {
102102

103103
interface API<MT extends ModelType = ModelType<any, any, {}>> {
104104
__id: string
105+
__ERROR__?: boolean
105106
useStore: (
106107
depActions?: Array<keyof MT['actions']>
107108
) => [Get<MT, 'state'>, getConsumerActionsType<Get<MT, 'actions'>>]
@@ -167,6 +168,7 @@ type ModelType<
167168
ActionKeys = any,
168169
ExtContext extends {} = {}
169170
> = {
171+
__ERROR__?: boolean
170172
actions: {
171173
[P in keyof ActionKeys]: Action<
172174
InitStateType,

src/index.tsx

+24
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,35 @@ function Model<M extends Models, MT extends ModelType, E>(
5959
useStore(hash, depActions as (string[] | undefined))
6060
}
6161
} else {
62+
if (models.actions) {
63+
console.error('invalid model(s) schema: ', models)
64+
const errorFn = (fakeReturnVal?: unknown) => (..._: unknown[]) => {
65+
return fakeReturnVal
66+
}
67+
// Fallback Functions
68+
return {
69+
__ERROR__: true,
70+
actions: errorFn({}),
71+
getActions: errorFn({}),
72+
getInitialState: errorFn({}),
73+
getState: errorFn({}),
74+
subscribe: errorFn(),
75+
unsubscribe: errorFn(),
76+
useStore: errorFn([{}, {}])
77+
} as any
78+
}
6279
if (initialState) {
6380
Global.State = initialState || {}
6481
}
6582
extContext && (Global.Context['__global'] = extContext)
6683
Object.entries(models).forEach(([name, model]) => {
84+
if (model.__ERROR__) {
85+
// Fallback State and Actions when model schema is invalid
86+
console.error(name + " model's schema is invalid")
87+
Global.State[name] = {}
88+
Global.Actions[name] = {}
89+
return
90+
}
6791
if (!isAPI(model)) {
6892
if (!Global.State[name]) {
6993
Global.State[name] = model.state

0 commit comments

Comments
 (0)