import { buildEffectsMiddleware } from './effects.js'; import Updux, { createAction } from './index.js'; test('buildEffectsMiddleware', () => { let seen = 0; const mw = buildEffectsMiddleware([ (api) => (next) => (action) => { seen++; expect(api).toHaveProperty('getState'); expect(api.getState).toBeTypeOf('function'); expect(api.getState()).toEqual('the state'); expect(action).toHaveProperty('type'); expect(next).toBeTypeOf('function'); expect(api).toHaveProperty('actions'); expect(api.actions.action1()).toHaveProperty('type', 'action1'); api.dispatch.action1(); expect(api.selectors.getFoo(2)).toBe(2); expect(api.getState.getFoo()).toBe('the state'); expect(api.getState.getBar(2)).toBe('the state2'); next(action); }, ], { action1: createAction('action1'), }, { getFoo: (state) => state, getBar: (state) => (i) => state + i, }); expect(seen).toEqual(0); const dispatch = vi.fn(); mw({ getState: () => 'the state', dispatch })(() => { })({ type: 'noop', }); expect(seen).toEqual(1); expect(dispatch).toHaveBeenCalledWith({ type: 'action1' }); }); test('basic', () => { const dux = new Updux({ initialState: { loaded: true, }, actions: { foo: 0, }, }); let seen = 0; dux.addEffect((api) => (next) => (action) => { seen++; expect(api).toHaveProperty('getState'); expect(api.getState()).toHaveProperty('loaded'); expect(action).toHaveProperty('type'); expect(next).toBeTypeOf('function'); next(action); }); const store = dux.createStore(); expect(seen).toEqual(0); store.dispatch.foo(); expect(seen).toEqual(1); }); test('subdux', () => { const bar = new Updux({ initialState: 'bar state', actions: { foo: 0 }, }); let seen = 0; bar.addEffect((api) => (next) => (action) => { seen++; expect(api.getState()).toBe('bar state'); next(action); }); const dux = new Updux({ initialState: { loaded: true, }, subduxes: { bar, }, }); const store = dux.createStore(); expect(seen).toEqual(0); store.dispatch.foo(); expect(seen).toEqual(1); }); test('addEffect with actionCreator', () => { const dux = new Updux({ actions: { foo: null, bar: null, }, }); const next = vi.fn(); const spy = vi.fn(); const mw = dux.addEffect(dux.actions.foo, (api) => (next) => (action) => next(spy(action))); mw({})(next)(dux.actions.bar()); expect(next).toHaveBeenCalled(); expect(spy).not.toHaveBeenCalled(); next.mockReset(); mw({})(next)(dux.actions.foo()); expect(next).toHaveBeenCalled(); expect(spy).toHaveBeenCalled(); }); test('addEffect with function', () => { const dux = new Updux({ actions: { foo: () => { }, bar: () => { }, }, }); const next = vi.fn(); const spy = vi.fn(); const mw = dux.addEffect((action) => action.type[0] === 'f', (api) => (next) => (action) => next(spy(action))); mw({})(next)(dux.actions.bar()); expect(next).toHaveBeenCalled(); expect(spy).not.toHaveBeenCalled(); next.mockReset(); mw({})(next)(dux.actions.foo()); expect(next).toHaveBeenCalled(); expect(spy).toHaveBeenCalled(); }); // TODO subdux effects // TODO allow to subscribe / unsubscribe effects?