wip
This commit is contained in:
parent
931377b584
commit
4c0d7b366f
@ -1,6 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
"roots": [
|
"roots": [
|
||||||
"./src"
|
"./dist"
|
||||||
],
|
],
|
||||||
"transform": {
|
"transform": {
|
||||||
"^.+\\.ts$": "ts-jest",
|
"^.+\\.ts$": "ts-jest",
|
||||||
|
@ -1,228 +1,277 @@
|
|||||||
import Updux, { actionCreator } from ".";
|
import Updux, { actionCreator } from '.';
|
||||||
import u from "updeep";
|
import u from 'updeep';
|
||||||
|
import mwUpdux from './middleware_aux';
|
||||||
|
|
||||||
test("simple effect", () => {
|
test('simple effect', () => {
|
||||||
const tracer = jest.fn();
|
const tracer = jest.fn();
|
||||||
|
|
||||||
const store = new Updux({
|
const store = new Updux({
|
||||||
effects: {
|
|
||||||
foo: (api: any) => (next: any) => (action: any) => {
|
|
||||||
tracer();
|
|
||||||
next(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).createStore();
|
|
||||||
|
|
||||||
expect(tracer).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
store.dispatch({ type: "bar" });
|
|
||||||
|
|
||||||
expect(tracer).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
store.dispatch.foo();
|
|
||||||
|
|
||||||
expect(tracer).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("effect and sub-effect", () => {
|
|
||||||
const tracer = jest.fn();
|
|
||||||
|
|
||||||
const tracerEffect = (signature: string) => (api: any) => (next: any) => (
|
|
||||||
action: any
|
|
||||||
) => {
|
|
||||||
tracer(signature);
|
|
||||||
next(action);
|
|
||||||
};
|
|
||||||
|
|
||||||
const store = new Updux({
|
|
||||||
effects: {
|
|
||||||
foo: tracerEffect("root")
|
|
||||||
},
|
|
||||||
subduxes: {
|
|
||||||
zzz: {
|
|
||||||
effects: {
|
effects: {
|
||||||
foo: tracerEffect("child")
|
foo: (api: any) => (next: any) => (action: any) => {
|
||||||
}
|
tracer();
|
||||||
}
|
next(action);
|
||||||
}
|
},
|
||||||
}).createStore();
|
|
||||||
|
|
||||||
expect(tracer).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
store.dispatch({ type: "bar" });
|
|
||||||
|
|
||||||
expect(tracer).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
store.dispatch.foo();
|
|
||||||
|
|
||||||
expect(tracer).toHaveBeenNthCalledWith(1, "root");
|
|
||||||
expect(tracer).toHaveBeenNthCalledWith(2, "child");
|
|
||||||
});
|
|
||||||
|
|
||||||
test('"*" effect', () => {
|
|
||||||
const tracer = jest.fn();
|
|
||||||
|
|
||||||
const store = new Updux({
|
|
||||||
effects: {
|
|
||||||
"*": api => next => action => {
|
|
||||||
tracer();
|
|
||||||
next(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).createStore();
|
|
||||||
|
|
||||||
expect(tracer).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
store.dispatch({ type: "bar" });
|
|
||||||
|
|
||||||
expect(tracer).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("async effect", async () => {
|
|
||||||
function timeout(ms: number) {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
const tracer = jest.fn();
|
|
||||||
|
|
||||||
const store = new Updux({
|
|
||||||
effects: {
|
|
||||||
foo: api => next => async action => {
|
|
||||||
next(action);
|
|
||||||
await timeout(1000);
|
|
||||||
tracer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).createStore();
|
|
||||||
|
|
||||||
expect(tracer).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
store.dispatch.foo();
|
|
||||||
|
|
||||||
expect(tracer).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
await timeout(1000);
|
|
||||||
|
|
||||||
expect(tracer).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("getState is local", () => {
|
|
||||||
let childState;
|
|
||||||
let rootState;
|
|
||||||
let rootFromChild;
|
|
||||||
|
|
||||||
const child = new Updux({
|
|
||||||
initial: { alpha: 12 },
|
|
||||||
effects: {
|
|
||||||
doIt: ({ getState, getRootState }) => next => action => {
|
|
||||||
childState = getState();
|
|
||||||
rootFromChild = getRootState();
|
|
||||||
next(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const root = new Updux({
|
|
||||||
initial: { beta: 24 },
|
|
||||||
subduxes: { child },
|
|
||||||
effects: {
|
|
||||||
doIt: ({ getState }) => next => action => {
|
|
||||||
rootState = getState();
|
|
||||||
next(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = root.createStore();
|
|
||||||
store.dispatch.doIt();
|
|
||||||
|
|
||||||
expect(rootState).toEqual({ beta: 24, child: { alpha: 12 } });
|
|
||||||
expect(rootFromChild).toEqual({ beta: 24, child: { alpha: 12 } });
|
|
||||||
expect(childState).toEqual({ alpha: 12 });
|
|
||||||
});
|
|
||||||
|
|
||||||
test("middleware as map", () => {
|
|
||||||
let childState;
|
|
||||||
let rootState;
|
|
||||||
let rootFromChild;
|
|
||||||
|
|
||||||
const doIt = actionCreator("doIt");
|
|
||||||
|
|
||||||
const child = new Updux({
|
|
||||||
initial: "",
|
|
||||||
effects: [
|
|
||||||
[
|
|
||||||
doIt,
|
|
||||||
() => next => action => {
|
|
||||||
next(u({ payload: (p: string) => p + "Child" }, action) as any);
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const root = new Updux({
|
|
||||||
initial: { message: "" },
|
|
||||||
subduxes: { child },
|
|
||||||
effects: [
|
|
||||||
[
|
|
||||||
"^",
|
|
||||||
() => next => action => {
|
|
||||||
next(u({ payload: (p: string) => p + "Pre" }, action) as any);
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
doIt,
|
|
||||||
() => next => action => {
|
|
||||||
next(u({ payload: (p: string) => p + "Root" }, action) as any);
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"*",
|
|
||||||
() => next => action => {
|
|
||||||
next(u({ payload: (p: string) => p + "After" }, action) as any);
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"$",
|
|
||||||
() => next => action => {
|
|
||||||
next(u({ payload: (p: string) => p + "End" }, action) as any);
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
mutations: [[doIt, (message: any) => () => ({ message })]]
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = root.createStore();
|
|
||||||
store.dispatch.doIt("");
|
|
||||||
|
|
||||||
expect(store.getState()).toEqual({ message: "PreRootAfterChildEnd" });
|
|
||||||
});
|
|
||||||
|
|
||||||
test("generator", () => {
|
|
||||||
const updux = new Updux({
|
|
||||||
initial: 0,
|
|
||||||
mutations: [["doIt", payload => () => payload]],
|
|
||||||
effects: [
|
|
||||||
[
|
|
||||||
"doIt",
|
|
||||||
() => {
|
|
||||||
let i = 0;
|
|
||||||
return () => (next: any) => (action: any) =>
|
|
||||||
next({ ...action, payload: ++i });
|
|
||||||
},
|
},
|
||||||
true
|
}).createStore();
|
||||||
]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const store1 = updux.createStore();
|
expect(tracer).not.toHaveBeenCalled();
|
||||||
store1.dispatch.doIt();
|
|
||||||
expect(store1.getState()).toEqual(1);
|
|
||||||
store1.dispatch.doIt();
|
|
||||||
expect(store1.getState()).toEqual(2);
|
|
||||||
updux.actions;
|
|
||||||
|
|
||||||
const store2 = updux.createStore();
|
store.dispatch({ type: 'bar' });
|
||||||
store2.dispatch.doIt();
|
|
||||||
expect(store2.getState()).toEqual(1);
|
expect(tracer).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
store.dispatch.foo();
|
||||||
|
|
||||||
|
expect(tracer).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('effect and sub-effect', () => {
|
||||||
|
const tracer = jest.fn();
|
||||||
|
|
||||||
|
const tracerEffect = (signature: string) => (api: any) => (next: any) => (
|
||||||
|
action: any
|
||||||
|
) => {
|
||||||
|
tracer(signature);
|
||||||
|
next(action);
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = new Updux({
|
||||||
|
effects: {
|
||||||
|
foo: tracerEffect('root'),
|
||||||
|
},
|
||||||
|
subduxes: {
|
||||||
|
zzz: {
|
||||||
|
effects: {
|
||||||
|
foo: tracerEffect('child'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).createStore();
|
||||||
|
|
||||||
|
expect(tracer).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
store.dispatch({ type: 'bar' });
|
||||||
|
|
||||||
|
expect(tracer).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
store.dispatch.foo();
|
||||||
|
|
||||||
|
expect(tracer).toHaveBeenNthCalledWith(1, 'root');
|
||||||
|
expect(tracer).toHaveBeenNthCalledWith(2, 'child');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('"*" effect', () => {
|
||||||
|
test('from the constructor', () => {
|
||||||
|
const tracer = jest.fn();
|
||||||
|
|
||||||
|
const store = new Updux({
|
||||||
|
effects: {
|
||||||
|
'*': api => next => action => {
|
||||||
|
tracer();
|
||||||
|
next(action);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).createStore();
|
||||||
|
|
||||||
|
expect(tracer).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
store.dispatch({ type: 'bar' });
|
||||||
|
|
||||||
|
expect(tracer).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('from addEffect', () => {
|
||||||
|
const tracer = jest.fn();
|
||||||
|
|
||||||
|
const updux = new Updux({});
|
||||||
|
|
||||||
|
updux.addEffect('*', api => next => action => {
|
||||||
|
tracer();
|
||||||
|
next(action);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tracer).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
updux.createStore().dispatch({ type: 'bar' });
|
||||||
|
|
||||||
|
expect(tracer).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('action can be modified', () => {
|
||||||
|
|
||||||
|
const mw = mwUpdux.middleware;
|
||||||
|
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
mw({dispatch:{}} as any)(next as any)({type: 'bar'});
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(next.mock.calls[0][0]).toMatchObject({meta: 'gotcha'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('async effect', async () => {
|
||||||
|
function timeout(ms: number) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
const tracer = jest.fn();
|
||||||
|
|
||||||
|
const store = new Updux({
|
||||||
|
effects: {
|
||||||
|
foo: api => next => async action => {
|
||||||
|
next(action);
|
||||||
|
await timeout(1000);
|
||||||
|
tracer();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).createStore();
|
||||||
|
|
||||||
|
expect(tracer).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
store.dispatch.foo();
|
||||||
|
|
||||||
|
expect(tracer).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
await timeout(1000);
|
||||||
|
|
||||||
|
expect(tracer).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getState is local', () => {
|
||||||
|
let childState;
|
||||||
|
let rootState;
|
||||||
|
let rootFromChild;
|
||||||
|
|
||||||
|
const child = new Updux({
|
||||||
|
initial: { alpha: 12 },
|
||||||
|
effects: {
|
||||||
|
doIt: ({ getState, getRootState }) => next => action => {
|
||||||
|
childState = getState();
|
||||||
|
rootFromChild = getRootState();
|
||||||
|
next(action);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const root = new Updux({
|
||||||
|
initial: { beta: 24 },
|
||||||
|
subduxes: { child },
|
||||||
|
effects: {
|
||||||
|
doIt: ({ getState }) => next => action => {
|
||||||
|
rootState = getState();
|
||||||
|
next(action);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const store = root.createStore();
|
||||||
|
store.dispatch.doIt();
|
||||||
|
|
||||||
|
expect(rootState).toEqual({ beta: 24, child: { alpha: 12 } });
|
||||||
|
expect(rootFromChild).toEqual({ beta: 24, child: { alpha: 12 } });
|
||||||
|
expect(childState).toEqual({ alpha: 12 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('middleware as map', () => {
|
||||||
|
let childState;
|
||||||
|
let rootState;
|
||||||
|
let rootFromChild;
|
||||||
|
|
||||||
|
const doIt = actionCreator('doIt');
|
||||||
|
|
||||||
|
const child = new Updux({
|
||||||
|
initial: '',
|
||||||
|
effects: [
|
||||||
|
[
|
||||||
|
doIt,
|
||||||
|
() => next => action => {
|
||||||
|
next(
|
||||||
|
u(
|
||||||
|
{ payload: (p: string) => p + 'Child' },
|
||||||
|
action
|
||||||
|
) as any
|
||||||
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const root = new Updux({
|
||||||
|
initial: { message: '' },
|
||||||
|
subduxes: { child },
|
||||||
|
effects: [
|
||||||
|
[
|
||||||
|
'^',
|
||||||
|
() => next => action => {
|
||||||
|
next(
|
||||||
|
u({ payload: (p: string) => p + 'Pre' }, action) as any
|
||||||
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
doIt,
|
||||||
|
() => next => action => {
|
||||||
|
next(
|
||||||
|
u({ payload: (p: string) => p + 'Root' }, action) as any
|
||||||
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'*',
|
||||||
|
() => next => action => {
|
||||||
|
next(
|
||||||
|
u(
|
||||||
|
{ payload: (p: string) => p + 'After' },
|
||||||
|
action
|
||||||
|
) as any
|
||||||
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'$',
|
||||||
|
() => next => action => {
|
||||||
|
next(
|
||||||
|
u({ payload: (p: string) => p + 'End' }, action) as any
|
||||||
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
mutations: [[doIt, (message: any) => () => ({ message })]],
|
||||||
|
});
|
||||||
|
|
||||||
|
const store = root.createStore();
|
||||||
|
store.dispatch.doIt('');
|
||||||
|
|
||||||
|
expect(store.getState()).toEqual({ message: 'PreRootAfterChildEnd' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('generator', () => {
|
||||||
|
const updux = new Updux({
|
||||||
|
initial: 0,
|
||||||
|
mutations: [['doIt', payload => () => payload]],
|
||||||
|
effects: [
|
||||||
|
[
|
||||||
|
'doIt',
|
||||||
|
() => {
|
||||||
|
let i = 0;
|
||||||
|
return () => (next: any) => (action: any) =>
|
||||||
|
next({ ...action, payload: ++i });
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const store1 = updux.createStore();
|
||||||
|
store1.dispatch.doIt();
|
||||||
|
expect(store1.getState()).toEqual(1);
|
||||||
|
store1.dispatch.doIt();
|
||||||
|
expect(store1.getState()).toEqual(2);
|
||||||
|
updux.actions;
|
||||||
|
|
||||||
|
const store2 = updux.createStore();
|
||||||
|
store2.dispatch.doIt();
|
||||||
|
expect(store2.getState()).toEqual(1);
|
||||||
});
|
});
|
||||||
|
13
src/middleware_aux.ts
Normal file
13
src/middleware_aux.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import Updux from '.';
|
||||||
|
|
||||||
|
const updux = new Updux({
|
||||||
|
subduxes: {
|
||||||
|
foo: { initial: "banana" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updux.addEffect('*', api => next => action => {
|
||||||
|
next({...action, meta: "gotcha" });
|
||||||
|
});
|
||||||
|
|
||||||
|
export default updux;
|
Loading…
Reference in New Issue
Block a user