parent
f2ac75fff8
commit
96649fef63
3 changed files with 0 additions and 178 deletions
@ -1,53 +0,0 @@ |
|||||||
class Store { |
|
||||||
constructor(reducer, catcher) { |
|
||||||
this.reducer = reducer; |
|
||||||
this.catcher = catcher; |
|
||||||
this.subscribers = []; |
|
||||||
try { |
|
||||||
this.state = this.reducer(undefined, {}); |
|
||||||
} catch (e) { |
|
||||||
catcher(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
dispatch(action, sender) { |
|
||||||
if (action instanceof Promise) { |
|
||||||
action.then((a) => { |
|
||||||
this.transitNext(a, sender); |
|
||||||
}).catch((e) => { |
|
||||||
this.catcher(e, sender); |
|
||||||
}); |
|
||||||
} else { |
|
||||||
try { |
|
||||||
this.transitNext(action, sender); |
|
||||||
} catch (e) { |
|
||||||
this.catcher(e, sender); |
|
||||||
} |
|
||||||
} |
|
||||||
return action; |
|
||||||
} |
|
||||||
|
|
||||||
getState() { |
|
||||||
return this.state; |
|
||||||
} |
|
||||||
|
|
||||||
subscribe(callback) { |
|
||||||
this.subscribers.push(callback); |
|
||||||
} |
|
||||||
|
|
||||||
transitNext(action, sender) { |
|
||||||
let newState = this.reducer(this.state, action); |
|
||||||
if (JSON.stringify(this.state) !== JSON.stringify(newState)) { |
|
||||||
this.state = newState; |
|
||||||
this.subscribers.forEach(f => f(sender)); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const empty = () => {}; |
|
||||||
|
|
||||||
const createStore = (reducer, catcher = empty) => { |
|
||||||
return new Store(reducer, catcher); |
|
||||||
}; |
|
||||||
|
|
||||||
export { createStore }; |
|
@ -1,15 +0,0 @@ |
|||||||
import { h, Component } from 'preact'; |
|
||||||
|
|
||||||
class Provider extends Component { |
|
||||||
getChildContext() { |
|
||||||
return { store: this.props.store }; |
|
||||||
} |
|
||||||
|
|
||||||
render() { |
|
||||||
return <div> |
|
||||||
{ this.props.children } |
|
||||||
</div>; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default Provider; |
|
@ -1,110 +0,0 @@ |
|||||||
import { createStore } from 'shared/store'; |
|
||||||
|
|
||||||
describe("Store class", () => { |
|
||||||
const reducer = (state, action) => { |
|
||||||
if (state == undefined) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
return state + action; |
|
||||||
}; |
|
||||||
|
|
||||||
describe("#dispatch", () => { |
|
||||||
it('transit status by immediate action', () => { |
|
||||||
let store = createStore(reducer); |
|
||||||
store.dispatch(10); |
|
||||||
expect(store.getState()).to.equal(10); |
|
||||||
|
|
||||||
store.dispatch(-20); |
|
||||||
expect(store.getState()).to.equal(-10); |
|
||||||
}); |
|
||||||
|
|
||||||
it('returns next state by immediate action', () => { |
|
||||||
let store = createStore(reducer); |
|
||||||
let dispatchedAction = store.dispatch(11); |
|
||||||
expect(dispatchedAction).to.equal(11); |
|
||||||
}); |
|
||||||
|
|
||||||
it('transit status by Promise action', () => { |
|
||||||
let store = createStore(reducer); |
|
||||||
let p1 = Promise.resolve(10); |
|
||||||
|
|
||||||
return store.dispatch(p1).then(() => { |
|
||||||
expect(store.getState()).to.equal(10); |
|
||||||
}).then(() => { |
|
||||||
store.dispatch(Promise.resolve(-20)); |
|
||||||
}).then(() => { |
|
||||||
expect(store.getState()).to.equal(-10); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
it('returns next state by promise action', () => { |
|
||||||
let store = createStore(reducer); |
|
||||||
let dispatchedAction = store.dispatch(Promise.resolve(11)); |
|
||||||
return dispatchedAction.then((value) => { |
|
||||||
expect(value).to.equal(11); |
|
||||||
}); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
describe("#subscribe", () => { |
|
||||||
it('invoke callback', (done) => { |
|
||||||
let store = createStore(reducer); |
|
||||||
store.subscribe(() => { |
|
||||||
expect(store.getState()).to.equal(15); |
|
||||||
done(); |
|
||||||
}); |
|
||||||
store.dispatch(15); |
|
||||||
}); |
|
||||||
|
|
||||||
it('propagate sender object', (done) => { |
|
||||||
let store = createStore(reducer); |
|
||||||
store.subscribe((sender) => { |
|
||||||
expect(sender).to.equal('sender'); |
|
||||||
done(); |
|
||||||
}); |
|
||||||
store.dispatch(15, 'sender'); |
|
||||||
}); |
|
||||||
}) |
|
||||||
|
|
||||||
describe("catcher", () => { |
|
||||||
it('catch an error in reducer on initializing by immediate action', (done) => { |
|
||||||
let store = createStore(() => { |
|
||||||
throw new Error(); |
|
||||||
}, (e) => { |
|
||||||
expect(e).to.be.an('error'); |
|
||||||
done(); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
it('catch an error in reducer on initializing by immediate action', (done) => { |
|
||||||
let store = createStore((state, action) => { |
|
||||||
if (state === undefined) return 0; |
|
||||||
throw new Error(); |
|
||||||
}, (e) => { |
|
||||||
expect(e).to.be.an('error'); |
|
||||||
done(); |
|
||||||
}); |
|
||||||
store.dispatch(20); |
|
||||||
}); |
|
||||||
|
|
||||||
it('catch an error in reducer on initializing by promise action', (done) => { |
|
||||||
let store = createStore((state, action) => { |
|
||||||
if (state === undefined) return 0; |
|
||||||
throw new Error(); |
|
||||||
}, (e) => { |
|
||||||
expect(e).to.be.an('error'); |
|
||||||
done(); |
|
||||||
}); |
|
||||||
store.dispatch(Promise.resolve(20)); |
|
||||||
}); |
|
||||||
|
|
||||||
it('catch an error in promise action', (done) => { |
|
||||||
let store = createStore((state, action) => 0, (e) => { |
|
||||||
expect(e).to.be.an('error'); |
|
||||||
done(); |
|
||||||
}); |
|
||||||
store.dispatch(new Promise(() => { throw new Error() })); |
|
||||||
}); |
|
||||||
}) |
|
||||||
}); |
|
||||||
|
|
Reference in new issue