import { test, expect, vi, describe } from 'vitest'; import u from 'updeep'; import { Updux } from './Updux.js'; import { matches } from './utils'; const reactionSnitch = vi.fn(); const thingReactionSnitch = vi.fn(); const subThing = new Updux({ name: 'subThing', initial: 0, }); subThing.addReaction((api) => (state, previousState, unsubscribe) => { reactionSnitch({ ...api, state, previousState }); }); const thing = new Updux({ name: 'thing', initial: {}, subduxes: { '*': subThing, }, actions: { setSubThing: (id, value, thingId) => ({ thingId, id, value }), deleteSubThing: (id) => id, }, mutations: { setSubThing: ({ id, value }) => u.updateIn(id, value), deleteSubThing: (id) => u.updateIn(id, u.omitted), }, splatReactionMapper: ({ id }) => id, }); thing.addReaction((api) => (state, previousState, unsubscribe) => { thingReactionSnitch({ ...api, state, previousState }); }); const things = new Updux({ subduxes: { '*': thing, }, initial: {}, actions: { newThing: (id) => id }, splatReactionMapper: ({ id }) => id, mutations: { newThing: (id) => (state) => ({ ...state, [id]: thing.initial }), }, }); things.setMutation( 'setSubThing', ({ thingId }, action) => u.updateIn(thingId, thing.upreducer(action)), true, ); describe('just one level', () => { const store = thing.createStore(); test('set', async () => { store.dispatch.setSubThing('a', 13); expect(reactionSnitch).toHaveBeenCalledWith( expect.objectContaining({ state: 13 }), ); }); test('other key', async () => { reactionSnitch.mockReset(); store.dispatch.setSubThing('b', 23); expect(reactionSnitch).not.toHaveBeenCalledWith( expect.objectContaining({ state: 13 }), ); expect(reactionSnitch).toHaveBeenCalledWith( expect.objectContaining({ state: 23 }), ); }); test('delete', async () => { reactionSnitch.mockReset(); store.dispatch.deleteSubThing('a'); expect(reactionSnitch).toHaveBeenCalledOnce(); expect(reactionSnitch).toHaveBeenCalledWith( expect.objectContaining({ state: null }), ); }); test('context', async () => { expect(reactionSnitch).toHaveBeenCalledWith( expect.objectContaining({ context: { subThing: 'a' }, }), ); }); }); test('two levels', async () => { const store = things.createStore(); reactionSnitch.mockReset(); thingReactionSnitch.mockReset(); store.dispatch.newThing('alpha'); store.dispatch.newThing('beta'); store.dispatch.setSubThing('a', 13, 'alpha'); expect(reactionSnitch).toHaveBeenCalledWith( expect.objectContaining({ context: { thing: 'alpha', subThing: 'a' }, state: 13, }), ); expect(thingReactionSnitch).toHaveBeenCalledWith( expect.objectContaining({ context: { thing: 'alpha', }, state: { a: 13 }, }), ); });