import {F1} from "functools-ts" import {expect} from "chai" import {Dispatch, UpdateFn, DispatchSymbol, isPromise, isObservable, childDispatch} from "./index" interface State { value: A } const createSetState = (initial: S): [State, (newState: S | F1) => void] => { let state: State = {value: initial} const setState = (newState: S | F1) => { if (typeof newState === "function") state.value = (newState as F1)(state.value) else state.value = newState as S } return [state, setState] } const testDispatch = (setState: (state: S | F1) => void): Dispatch => { let dispatch = (( updateFn: UpdateFn, _name?: string, _noReplay?: boolean ) => { setState((state: S) => { const ret = updateFn(state) if (isPromise(ret)) { ret.then(d => setState((state: S) => d(state))) return state } else if (isObservable(ret)) { ret.subscribe(d => setState((state: S) => d(state))) return state } else { return ret } }) }) as Dispatch dispatch[DispatchSymbol] = true return dispatch } interface User { name: string } interface App { user: User } describe("dispatch", () => { it("should update the state", () => { const [state, setState] = createSetState({user: {name: "test"}}) const dispatch = childDispatch(testDispatch(setState), "user") const setName = (name: string) => (_: User): User => ({name}) dispatch(setName("newname")) expect(state.value.user.name).eql("newname") }) it("should update the state with an async function", () => { const [state, setState] = createSetState({user: {name: "test"}}) const dispatch = childDispatch(testDispatch(setState), "user") const setName = (name: string) => async (_: User) => Promise.resolve((_: User): User => ({name})) dispatch(setName("newuser")) setTimeout(() => expect(state.value.user.name).eql("newuser"), 0) }) })