2021-10-16 15:41:04 +00:00
|
|
|
import { difference, omit } from 'lodash';
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
import { Updux } from './Updux';
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
test('initial', () => {
|
2021-10-12 13:42:30 +00:00
|
|
|
const dux = new Updux({
|
|
|
|
initial: {},
|
|
|
|
subduxes: {
|
|
|
|
'*': {
|
|
|
|
initial: { a: 1 },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(dux.initial).toMatchObject({});
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
test('actions', () => {
|
2021-10-12 13:42:30 +00:00
|
|
|
const dux = new Updux({
|
|
|
|
initial: {},
|
|
|
|
subduxes: {
|
|
|
|
'*': {
|
|
|
|
initial: { a: 1 },
|
|
|
|
actions: { foo: null },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(typeof dux.actions.foo).toBe('function');
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
test('selectors', () => {
|
2021-10-12 13:42:30 +00:00
|
|
|
const dux = new Updux({
|
|
|
|
initial: {},
|
|
|
|
subduxes: {
|
|
|
|
'*': {
|
|
|
|
initial: { a: 1 },
|
|
|
|
selectors: {
|
|
|
|
getA: ({ a }) => a,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(dux.selectors).toMatchObject({});
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
const getInner = (state) => (index) => state[index];
|
2021-10-16 15:41:04 +00:00
|
|
|
dux.setMappedSelector('getInner', getInner);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(typeof dux.selectors.getInner).toBe('function');
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(
|
2021-10-12 13:42:30 +00:00
|
|
|
dux.selectors.getInner({
|
|
|
|
one: { a: 1 },
|
|
|
|
two: { a: 2 },
|
2021-10-16 15:41:04 +00:00
|
|
|
})('one')()
|
|
|
|
).toMatchObject({ a: 1 });
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(
|
2021-10-12 13:42:30 +00:00
|
|
|
dux.selectors
|
|
|
|
.getInner({
|
|
|
|
one: { a: 1 },
|
|
|
|
two: { a: 2 },
|
|
|
|
})('one')
|
2021-10-16 15:41:04 +00:00
|
|
|
.getA()
|
|
|
|
).toBe(1);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
// and now with the store
|
|
|
|
const store = dux.createStore({
|
|
|
|
one: { a: 1 },
|
|
|
|
two: { a: 2 },
|
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(store.getState.getInner('two')()).toMatchObject({ a: 2 });
|
|
|
|
expect(store.getState.getInner('two').getA()).toEqual(2);
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
test('splat middleware', () => {
|
|
|
|
const snitch = jest.fn(() => true);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
const dux = new Updux({
|
|
|
|
initial: {},
|
|
|
|
subduxes: {
|
|
|
|
'*': {
|
|
|
|
initial: { a: 1 },
|
|
|
|
actions: { foo: null },
|
|
|
|
effects: {
|
|
|
|
foo: (api) => (next) => (action) => {
|
|
|
|
snitch();
|
|
|
|
next(action);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const store = dux.createStore({ one: { a: 1 }, two: { a: 2 } });
|
|
|
|
store.dispatch.foo();
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).not.toBeCalled();
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
test('splat subscriptions', () => {
|
|
|
|
const snitch = jest.fn(() => true);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
const dux = new Updux({
|
|
|
|
initial: {},
|
|
|
|
subduxes: {
|
|
|
|
'*': {
|
|
|
|
initial: { a: 1 },
|
|
|
|
actions: { foo: null },
|
|
|
|
mutations: {
|
|
|
|
foo: (id) => (state) =>
|
|
|
|
state.a === i ? { ...state, b: 1 } : state,
|
|
|
|
},
|
|
|
|
subscriptions: [
|
|
|
|
(store) => (state, previous, unsub) => {
|
|
|
|
snitch(state);
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const store = dux.createStore({ one: { a: 1 }, two: { a: 2 } });
|
|
|
|
store.dispatch({ type: 'noop' });
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).not.toBeCalled();
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
test('splat subscriptions, more', () => {
|
|
|
|
const snitch = jest.fn(() => true);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
const inner = new Updux({
|
|
|
|
initial: { a: 1 },
|
|
|
|
actions: { foo: null, incAll: null },
|
|
|
|
mutations: {
|
2021-10-16 15:41:04 +00:00
|
|
|
foo: (id) => (state) =>
|
|
|
|
state.a === id ? { ...state, b: 1 } : state,
|
2021-10-12 13:42:30 +00:00
|
|
|
incAll: () => (state) => ({ ...state, a: state.a + 1 }),
|
|
|
|
},
|
2021-10-16 15:41:04 +00:00
|
|
|
reactions: [() => snitch],
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
const dux = new Updux({
|
|
|
|
initial: {},
|
|
|
|
actions: {
|
|
|
|
delete: null,
|
|
|
|
newEntry: null,
|
|
|
|
},
|
|
|
|
mutations: {
|
|
|
|
delete: (id) => (state) => omit(state, id),
|
|
|
|
newEntry: (name) => (state) => ({ ...state, [name]: { a: 10 } }),
|
|
|
|
},
|
2021-10-16 15:41:04 +00:00
|
|
|
mappedReaction: true,
|
2021-10-12 13:42:30 +00:00
|
|
|
subduxes: {
|
|
|
|
'*': inner,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const store = dux.createStore({ one: { a: 1 }, two: { a: 2 } });
|
|
|
|
store.dispatch({ type: 'noop' });
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalledTimes(2);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalledWith(
|
|
|
|
{ a: 1 },
|
|
|
|
undefined,
|
|
|
|
expect.anything()
|
|
|
|
);
|
|
|
|
expect(snitch).toHaveBeenCalledWith(
|
|
|
|
{ a: 2 },
|
|
|
|
undefined,
|
|
|
|
expect.anything()
|
|
|
|
);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
snitch.mockReset();
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
store.dispatch.foo(2);
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalledWith(
|
|
|
|
{ a: 2, b: 1 },
|
|
|
|
expect.anything(),
|
|
|
|
expect.anything()
|
|
|
|
);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
snitch.mockReset();
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
store.dispatch.delete('one');
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(store.getState()).toMatchObject({
|
2021-10-12 13:42:30 +00:00
|
|
|
two: { a: 2, b: 1 },
|
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalledTimes(1);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalledWith(
|
|
|
|
undefined,
|
|
|
|
{ a: 1 },
|
|
|
|
expect.anything()
|
2021-10-12 13:42:30 +00:00
|
|
|
);
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
// only one subscriber left
|
|
|
|
snitch.mockReset();
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
store.dispatch.incAll();
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalledTimes(1);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalledWith(
|
|
|
|
{ a: 3, b: 1 },
|
|
|
|
{ a: 2, b: 1 },
|
|
|
|
expect.anything()
|
|
|
|
);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
// new entry gets subscribed
|
|
|
|
snitch.mockReset();
|
|
|
|
store.dispatch.newEntry('newbie');
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalledTimes(1);
|
|
|
|
|
|
|
|
expect(snitch).toHaveBeenCalledWith(
|
|
|
|
{ a: 10 },
|
|
|
|
undefined,
|
|
|
|
expect.anything()
|
|
|
|
);
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
test('many levels down', () => {
|
|
|
|
const snitch = jest.fn(() => true);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
const dux = new Updux({
|
2021-10-16 15:41:04 +00:00
|
|
|
mappedReaction: true,
|
2021-10-12 13:42:30 +00:00
|
|
|
actions: { remove: null },
|
|
|
|
mutations: {
|
|
|
|
remove: () => (state) => ({}),
|
|
|
|
},
|
|
|
|
subduxes: {
|
|
|
|
'*': {
|
|
|
|
subduxes: {
|
|
|
|
a: {
|
|
|
|
initial: 1,
|
|
|
|
actions: {
|
|
|
|
add: null,
|
|
|
|
},
|
|
|
|
mutations: {
|
|
|
|
add: () => (x) => x + 1,
|
|
|
|
},
|
2021-10-16 15:41:04 +00:00
|
|
|
reactions: [
|
2021-10-12 13:42:30 +00:00
|
|
|
(store) => (state) => snitch(state, store),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const store = dux.createStore({ one: { a: 1 } });
|
|
|
|
store.dispatch({ type: 'foo' });
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toHaveBeenCalled();
|
|
|
|
expect(snitch).toHaveBeenCalledWith(1, expect.anything());
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
snitch.mockReset();
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
store.dispatch.remove();
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toBeCalled();
|
|
|
|
expect(snitch).toHaveBeenCalledWith(undefined, expect.anything());
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
test('inherit info via the store', () => {
|
|
|
|
const snitch = jest.fn(() => true);
|
|
|
|
const splatSnitch = jest.fn(() => true);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
|
|
|
const dux = new Updux({
|
2021-10-16 15:41:04 +00:00
|
|
|
mappedReaction: (store, key) => {
|
2021-10-12 13:42:30 +00:00
|
|
|
store.itemId = key;
|
|
|
|
|
|
|
|
splatSnitch();
|
|
|
|
return { itemId: key };
|
|
|
|
},
|
|
|
|
subduxes: {
|
|
|
|
'*': {
|
|
|
|
subduxes: {
|
|
|
|
a: {
|
|
|
|
initial: 1,
|
|
|
|
actions: {
|
|
|
|
add: null,
|
|
|
|
},
|
|
|
|
mutations: {
|
|
|
|
add: () => (x) => x + 1,
|
|
|
|
},
|
2021-10-16 15:41:04 +00:00
|
|
|
reactions: [
|
2021-10-12 13:42:30 +00:00
|
|
|
(store) => (state) => snitch(state, store.itemId),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const store = dux.createStore({
|
|
|
|
one: { a: 1 },
|
|
|
|
two: { a: 2 },
|
|
|
|
});
|
|
|
|
|
|
|
|
store.dispatch({ type: 'noop' });
|
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(splatSnitch).toBeCalledTimes(2);
|
2021-10-12 13:42:30 +00:00
|
|
|
|
2021-10-16 15:41:04 +00:00
|
|
|
expect(snitch).toBeCalledTimes(2);
|
|
|
|
expect(snitch).toHaveBeenCalledWith(1, 'one');
|
|
|
|
expect(snitch).toHaveBeenCalledWith(2, 'two');
|
2021-10-12 13:42:30 +00:00
|
|
|
});
|