diff --git a/src/buildSelectors/index.ts b/src/buildSelectors/index.ts index 1dc3478..2949a23 100644 --- a/src/buildSelectors/index.ts +++ b/src/buildSelectors/index.ts @@ -1,6 +1,6 @@ import { map, mapValues, merge } from 'lodash'; -export function buildSelectors(localSelectors, splatSelector, subduxes) { +export function buildSelectors(localSelectors, splatSelector = {}, subduxes ={}) { const subSelectors = map(subduxes, ({ selectors }, slice) => { if (!selectors) return {}; if (slice === '*') return {}; @@ -9,11 +9,12 @@ export function buildSelectors(localSelectors, splatSelector, subduxes) { }); let splat = {}; - if (splatSelector) { - splat[splatSelector[0]] = + + for ( const name in splatSelector ) { + splat[name] = (state) => (...args) => { - const value = splatSelector[1](state)(...args); + const value = splatSelector[name](state)(...args); const res = () => value; return merge( @@ -24,7 +25,7 @@ export function buildSelectors(localSelectors, splatSelector, subduxes) { ) ); }; - } + } return merge({}, ...subSelectors, localSelectors, splat); } diff --git a/src/selectors.test.js b/src/selectors.test.js index 1db21ea..9f984cf 100644 --- a/src/selectors.test.js +++ b/src/selectors.test.js @@ -1,9 +1,7 @@ -import { test } from 'tap'; +import { Updux } from '.'; +import { action } from './actions'; -import { Updux } from './Updux.js'; -import { action } from './actions.js'; - -test('basic selectors', async (t) => { +test('basic selectors', () => { const updux = new Updux({ subduxes: { bogeys: new Updux({ @@ -24,11 +22,11 @@ test('basic selectors', async (t) => { }, }; - t.same(updux.selectors.bogeys(state), { foo: 1, bar: 2 }); - t.equal(updux.selectors.bogey(state)('foo'), 1); + expect(updux.selectors.bogeys(state)).toMatchObject({ foo: 1, bar: 2 }); + expect(updux.selectors.bogey(state)('foo')).toEqual(1); }); -test('available in the middleware', async (t) => { +test('available in the middleware', () => { const doIt = action('doIt'); const updux = new Updux({ @@ -60,10 +58,10 @@ test('available in the middleware', async (t) => { const store = updux.createStore(); store.dispatch(updux.actions.doIt()); - t.match(store.getState(), { payload: 'foo' }); + expect(store.getState()).toMatchObject({ payload: 'foo' }); }); -test('selector typescript', async (t) => { +test('selector typescript', () => { const bar = new Updux({ initial: { baz: 1 }, selectors: { @@ -73,40 +71,38 @@ test('selector typescript', async (t) => { }, }); - t.same(bar.selectors.getBaz(bar.initial), 1); - t.same(bar.selectors.getMultBaz({ baz: 3 })(2), 6); + expect(bar.selectors.getBaz(bar.initial)).toEqual(1); + expect(bar.selectors.getMultBaz({ baz: 3 })(2)).toEqual(6); - test('subduxes', async (t) => { - const foo = new Updux({ - subduxes: { bar }, - selectors: { - getRoot: () => 'root', - }, - }); - - t.same(foo.selectors.getBaz(foo.initial), 1); - t.same(foo.selectors.getMultBaz({ bar: { baz: 3 } })(2), 6); - - t.ok(foo.selectors.getRoot); + // subduxes + const foo = new Updux({ + subduxes: { bar }, + selectors: { + getRoot: () => 'root', + }, }); - test('no root selector', async (t) => { - const foo = new Updux({ - subduxes: { - quux: new Updux({}), - bar: new Updux({ - selectors: { - getBaz: () => 'baz', - }, - }), - }, - }); + expect(foo.selectors.getBaz(foo.initial)).toEqual(1); + expect(foo.selectors.getMultBaz({ bar: { baz: 3 } })(2)).toEqual(6); - t.ok(foo.selectors.getBaz); + expect(foo.selectors.getRoot).toBeTruthy(); + + /// no root selector + const foo3 = new Updux({ + subduxes: { + quux: new Updux({}), + bar: new Updux({ + selectors: { + getBaz: () => 'baz', + }, + }), + }, }); + + expect(foo3.selectors.getBaz).toBeTruthy(); }); -test('selector in mw', async (t) => { +test('selector in mw', () => { const myDux = new Updux({ initial: { stuff: 12 }, subduxes: { @@ -124,16 +120,16 @@ test('selector in mw', async (t) => { myDux.addEffect('*', ({ selectors, getState }) => () => () => { ['getStuff', 'getBar'].forEach((selector) => - t.type(selectors[selector], 'function') + expect(typeof selectors[selector]).toEqual('function') ); - t.equal(getState.getStuff(), 12); - t.equal(getState.getBar(), 'meh'); + expect(getState.getStuff()).toEqual(12); + expect(getState.getBar()).toEqual('meh'); ranEffect = true; }); myDux.createStore().dispatch({ type: 'foo' }); - t.ok(ranEffect); + expect(ranEffect).toBeTruthy(); }); diff --git a/src/splat.test.js b/src/splat.test.js index 1dc7842..5220460 100644 --- a/src/splat.test.js +++ b/src/splat.test.js @@ -1,10 +1,8 @@ -import { test } from 'tap'; -import sinon from 'sinon'; -import { difference, omit } from 'lodash-es'; +import { difference, omit } from 'lodash'; -import { Updux } from './Updux.js'; +import { Updux } from './Updux'; -test('initial', async (t) => { +test('initial', () => { const dux = new Updux({ initial: {}, subduxes: { @@ -14,10 +12,10 @@ test('initial', async (t) => { }, }); - t.same(dux.initial, {}); + expect(dux.initial).toMatchObject({}); }); -test('actions', async (t) => { +test('actions', () => { const dux = new Updux({ initial: {}, subduxes: { @@ -28,10 +26,10 @@ test('actions', async (t) => { }, }); - t.type(dux.actions.foo, 'function'); + expect(typeof dux.actions.foo).toBe('function'); }); -test('selectors', async (t) => { +test('selectors', () => { const dux = new Updux({ initial: {}, subduxes: { @@ -44,30 +42,28 @@ test('selectors', async (t) => { }, }); - t.same(dux.selectors, {}); + expect(dux.selectors).toMatchObject({}); const getInner = (state) => (index) => state[index]; - dux.setSplatSelector('getInner', getInner); + dux.setMappedSelector('getInner', getInner); - t.type(dux.selectors.getInner, 'function'); + expect(typeof dux.selectors.getInner).toBe('function'); - t.same( + expect( dux.selectors.getInner({ one: { a: 1 }, two: { a: 2 }, - })('one')(), - { a: 1 } - ); + })('one')() + ).toMatchObject({ a: 1 }); - t.same( + expect( dux.selectors .getInner({ one: { a: 1 }, two: { a: 2 }, })('one') - .getA(), - 1 - ); + .getA() + ).toBe(1); // and now with the store const store = dux.createStore({ @@ -75,12 +71,12 @@ test('selectors', async (t) => { two: { a: 2 }, }); - t.same(store.getState.getInner('two')(), { a: 2 }); - t.same(store.getState.getInner('two').getA(), 2); + expect(store.getState.getInner('two')()).toMatchObject({ a: 2 }); + expect(store.getState.getInner('two').getA()).toEqual(2); }); -test('splat middleware', async (t) => { - const snitch = sinon.fake(() => true); +test('splat middleware', () => { + const snitch = jest.fn(() => true); const dux = new Updux({ initial: {}, @@ -101,11 +97,11 @@ test('splat middleware', async (t) => { const store = dux.createStore({ one: { a: 1 }, two: { a: 2 } }); store.dispatch.foo(); - t.notOk(snitch.called); + expect(snitch).not.toBeCalled(); }); -test('splat subscriptions', async (t) => { - const snitch = sinon.fake(() => true); +test('splat subscriptions', () => { + const snitch = jest.fn(() => true); const dux = new Updux({ initial: {}, @@ -129,20 +125,21 @@ test('splat subscriptions', async (t) => { const store = dux.createStore({ one: { a: 1 }, two: { a: 2 } }); store.dispatch({ type: 'noop' }); - t.notOk(snitch.called); + expect(snitch).not.toBeCalled(); }); -test('splat subscriptions, more', async (t) => { - const snitch = sinon.fake(() => true); +test('splat subscriptions, more', () => { + const snitch = jest.fn(() => true); const inner = new Updux({ initial: { a: 1 }, actions: { foo: null, incAll: null }, mutations: { - foo: (id) => (state) => state.a === id ? { ...state, b: 1 } : state, + foo: (id) => (state) => + state.a === id ? { ...state, b: 1 } : state, incAll: () => (state) => ({ ...state, a: state.a + 1 }), }, - subscriptions: [() => snitch], + reactions: [() => snitch], }); const dux = new Updux({ @@ -155,7 +152,7 @@ test('splat subscriptions, more', async (t) => { delete: (id) => (state) => omit(state, id), newEntry: (name) => (state) => ({ ...state, [name]: { a: 10 } }), }, - splatReaction: 'whatev', + mappedReaction: true, subduxes: { '*': inner, }, @@ -164,72 +161,76 @@ test('splat subscriptions, more', async (t) => { const store = dux.createStore({ one: { a: 1 }, two: { a: 2 } }); store.dispatch({ type: 'noop' }); - t.equal(snitch.callCount, 2); + expect(snitch).toHaveBeenCalledTimes(2); - t.same(snitch.firstCall.args[0], { a: 1 }); - t.same(snitch.secondCall.args[0], { a: 2 }); + expect(snitch).toHaveBeenCalledWith( + { a: 1 }, + undefined, + expect.anything() + ); + expect(snitch).toHaveBeenCalledWith( + { a: 2 }, + undefined, + expect.anything() + ); - snitch.resetHistory(); + snitch.mockReset(); store.dispatch.foo(2); - t.equal(snitch.callCount, 1); + expect(snitch).toHaveBeenCalledWith( + { a: 2, b: 1 }, + expect.anything(), + expect.anything() + ); - t.same(snitch.firstCall.args[0], { a: 2, b: 1 }); + snitch.mockReset(); - snitch.resetHistory(); store.dispatch.delete('one'); - t.same(store.getState(), { + expect(store.getState()).toMatchObject({ two: { a: 2, b: 1 }, }); - t.equal(snitch.callCount, 1); + expect(snitch).toHaveBeenCalledTimes(1); - t.ok( - snitch.calledWithMatch( - undefined, - { a: 1 }, - sinon.match.typeOf('function') - ) + expect(snitch).toHaveBeenCalledWith( + undefined, + { a: 1 }, + expect.anything() ); - await t.test('only one subscriber left', async (t) => { - snitch.resetHistory(); - store.dispatch.incAll(); + // only one subscriber left + snitch.mockReset(); - t.equal(snitch.callCount, 1); + store.dispatch.incAll(); - t.ok( - snitch.calledWithMatch( - { a: 3, b: 1 }, - { a: 2, b: 1 }, - sinon.match.typeOf('function') - ) - ); - }); + expect(snitch).toHaveBeenCalledTimes(1); - await t.test('new entry gets subscribed', async (t) => { - snitch.resetHistory(); - store.dispatch.newEntry('newbie'); + expect(snitch).toHaveBeenCalledWith( + { a: 3, b: 1 }, + { a: 2, b: 1 }, + expect.anything() + ); - t.equal(snitch.callCount, 1); + // new entry gets subscribed + snitch.mockReset(); + store.dispatch.newEntry('newbie'); - t.ok( - snitch.calledWithMatch( - { a: 10 }, - undefined, - sinon.match.typeOf('function') - ) - ); - }); + expect(snitch).toHaveBeenCalledTimes(1); + + expect(snitch).toHaveBeenCalledWith( + { a: 10 }, + undefined, + expect.anything() + ); }); -test('many levels down', { only: false }, async (t) => { - const snitch = sinon.fake(() => true); +test('many levels down', () => { + const snitch = jest.fn(() => true); const dux = new Updux({ - splatReaction: 'potato', + mappedReaction: true, actions: { remove: null }, mutations: { remove: () => (state) => ({}), @@ -245,7 +246,7 @@ test('many levels down', { only: false }, async (t) => { mutations: { add: () => (x) => x + 1, }, - subscriptions: [ + reactions: [ (store) => (state) => snitch(state, store), ], }, @@ -257,23 +258,23 @@ test('many levels down', { only: false }, async (t) => { const store = dux.createStore({ one: { a: 1 } }); store.dispatch({ type: 'foo' }); - t.ok(snitch.calledOnce); - t.same(snitch.firstCall.firstArg, 1); + expect(snitch).toHaveBeenCalled(); + expect(snitch).toHaveBeenCalledWith(1, expect.anything()); - snitch.resetHistory(); + snitch.mockReset(); store.dispatch.remove(); - t.ok(snitch.calledOnce); - t.same(snitch.firstCall.firstArg, undefined); + expect(snitch).toBeCalled(); + expect(snitch).toHaveBeenCalledWith(undefined, expect.anything()); }); -test('inherit info via the store', async (t) => { - const snitch = sinon.fake(() => true); - const splatSnitch = sinon.fake(() => true); +test('inherit info via the store', () => { + const snitch = jest.fn(() => true); + const splatSnitch = jest.fn(() => true); const dux = new Updux({ - splatReaction: (store, key) => { + mappedReaction: (store, key) => { store.itemId = key; splatSnitch(); @@ -290,7 +291,7 @@ test('inherit info via the store', async (t) => { mutations: { add: () => (x) => x + 1, }, - subscriptions: [ + reactions: [ (store) => (state) => snitch(state, store.itemId), ], }, @@ -306,9 +307,9 @@ test('inherit info via the store', async (t) => { store.dispatch({ type: 'noop' }); - t.ok(splatSnitch.calledTwice); + expect(splatSnitch).toBeCalledTimes(2); - t.ok(snitch.calledTwice); - t.ok(snitch.calledWithMatch(1, 'one')); - t.ok(snitch.calledWithMatch(2, 'two')); + expect(snitch).toBeCalledTimes(2); + expect(snitch).toHaveBeenCalledWith(1, 'one'); + expect(snitch).toHaveBeenCalledWith(2, 'two'); });