128 lines
3.1 KiB
JavaScript
128 lines
3.1 KiB
JavaScript
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 },
|
|
}),
|
|
);
|
|
});
|