updux/src/splatReactions.test.js

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 },
}),
);
});