Skip to content

Commit f653327

Browse files
committed
update & add test
1 parent 1202d87 commit f653327

File tree

6 files changed

+246
-8
lines changed

6 files changed

+246
-8
lines changed

.npmignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.babelrc
2+
.eslintrc.json
3+
.idea/
4+
node_modules/
5+
test/

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
language: node_js
2+
node_js:
3+
- "4"
4+
- "5.3.0"
5+
script:
6+
- npm run clean
7+
- npm run build
8+
- npm run test
9+
branches:
10+
only:
11+
- master

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
redux-on
22
==============
33

4+
[![build status](https://img.shields.io/travis/toplan/redux-on/master.svg?style=flat-square)](https://travis-ci.org/toplan/redux-on)
45
[![npm version](https://img.shields.io/npm/v/redux-on.svg?style=flat-square)](https://www.npmjs.com/package/redux-on)
56
[![npm downloads](https://img.shields.io/npm/dm/redux-on.svg?style=flat-square)](https://www.npmjs.com/package/redux-on)
67

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redux-on",
3-
"version": "0.1.0",
3+
"version": "0.1.2",
44
"description": "Store enhancer for redux which support accurately subscribe.",
55
"main": "lib/index.js",
66
"nextjs:main": "es/index.js",
@@ -12,8 +12,11 @@
1212
],
1313
"scripts": {
1414
"clean": "rimraf lib dist es",
15-
"lint": "eslint src",
1615
"build": "npm run build:commonjs && npm run build:umd && npm run build:umd:min && npm run build:es",
16+
"prepublish": "npm run clean && npm run test && npm run build",
17+
"posttest": "npm run lint",
18+
"lint": "eslint src",
19+
"test": "cross-env BABEL_ENV=commonjs mocha --compilers js:babel-core/register --reporter spec test/*.js",
1720
"build:commonjs": "cross-env BABEL_ENV=commonjs babel src --out-dir lib",
1821
"build:es": "cross-env BABEL_ENV=es babel src --out-dir es",
1922
"build:umd": "cross-env BABEL_ENV=commonjs NODE_ENV=development webpack",

src/index.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
export default function () {
1+
export default function ({
2+
getActionType = action => action && action.type,
3+
} = {}) {
4+
if (typeof getActionType !== 'function') {
5+
throw new TypeError('Expected option `getActionType` to be a function.')
6+
}
7+
28
return createStore => (reducer, preloadedState, enhancer) => {
39
let actionType
410
const store = createStore(reducer, preloadedState, enhancer)
511

612
const dispatch = (action) => {
7-
actionType = action && action.type
13+
actionType = getActionType(action)
814
store.dispatch(action)
915
}
1016

@@ -28,11 +34,9 @@ export default function () {
2834
let emitted = false
2935
let prevState = store.getState()
3036
const emitable = (state) => {
31-
if (!type) {
32-
return predicate.call(null, prevState, state)
33-
}
37+
if (!type) return predicate.call(null, prevState, state)
3438
if (type !== actionType) return false
35-
if (predicate !== 'function') return true
39+
if (typeof predicate !== 'function') return true
3640
return predicate.call(null, prevState, state)
3741
}
3842
const off = store.subscribe(() => {

test/index.js

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
/**
2+
* Created by toplan on 17/4/28.
3+
*/
4+
import { assert } from 'chai';
5+
import { createStore } from 'redux'
6+
import addOnAndOnceToStore from '../src/index'
7+
8+
const SET_USER = 'SET_USER'
9+
const INC_ID = 'INC_ID'
10+
const reducer = (prevState, action) => {
11+
if (!action || !action.type) return prevState
12+
if (action.type === SET_USER) return { ...prevState, user: action.payload }
13+
if (action.type === INC_ID) return { ...prevState, id: ++prevState.id }
14+
return prevState
15+
}
16+
const initState = {
17+
id: 0,
18+
user: null
19+
}
20+
21+
describe('redux-on enhancer', () => {
22+
it('throws if create enhancer with invalid option `getActionType`', () => {
23+
assert.throws(() => addOnAndOnceToStore({ getActionType: null }), TypeError)
24+
})
25+
26+
const enhancer = addOnAndOnceToStore()
27+
28+
it('must return a function as store enhancer', () => {
29+
assert.isFunction(enhancer)
30+
assert.strictEqual(enhancer.length, 1)
31+
})
32+
33+
describe('enhance store', () => {
34+
const store = createStore(reducer, initState, enhancer)
35+
36+
it('must return a store with methods `on` and `once`', () => {
37+
assert.isObject(store)
38+
assert.isFunction(store.getState)
39+
assert.isFunction(store.subscribe)
40+
assert.isFunction(store.dispatch)
41+
assert.isFunction(store.on)
42+
assert.isFunction(store.once)
43+
})
44+
45+
describe('listen change', () => {
46+
const user = { name: 'top lan', age: 20 }
47+
const user1 = { name: 'top lan 1', age: 21 }
48+
const user2 = { name: 'top lan 2', age: 22 }
49+
50+
it('throws if listen change without `predicate`', () => {
51+
assert.throws(() => store.on(), TypeError)
52+
assert.throws(() => store.on(null, () => {}), TypeError)
53+
assert.throws(() => store.on(null, null, () => {}), TypeError)
54+
})
55+
56+
it('throws if listen change without `handler`', () => {
57+
assert.throws(() => store.on(() => {}), TypeError)
58+
assert.throws(() => store.on(SET_USER, () => {}, 1), TypeError)
59+
})
60+
61+
describe('any time by predicate', () => {
62+
const store = createStore(reducer, initState, enhancer)
63+
let triggerCount = 0
64+
let currentUser = store.getState().user
65+
const off = store.on((prevState, state) => {
66+
return prevState.user !== state.user
67+
}, (prevState, state) => {
68+
triggerCount++
69+
currentUser = state.user
70+
})
71+
72+
it('must return a function for drop listener', () => {
73+
assert.isFunction(off)
74+
})
75+
76+
it('must handle once if dispatch once', () => {
77+
store.dispatch({ type: INC_ID })
78+
store.dispatch({ type: SET_USER, payload: user })
79+
store.dispatch({ type: INC_ID })
80+
assert.strictEqual(triggerCount, 1)
81+
assert.strictEqual(currentUser, user)
82+
})
83+
84+
it('must handle 3 times after more dispatches', () => {
85+
store.dispatch({ type: SET_USER, payload: user1 })
86+
store.dispatch({ type: INC_ID })
87+
store.dispatch({ type: SET_USER, payload: user2 })
88+
store.dispatch({ type: INC_ID })
89+
assert.strictEqual(triggerCount, 3)
90+
assert.strictEqual(currentUser, user2)
91+
})
92+
93+
it('must not handle change if drop listener', () => {
94+
off()
95+
store.dispatch({ type: SET_USER, payload: user })
96+
store.dispatch({ type: SET_USER, payload: user1 })
97+
assert.strictEqual(triggerCount, 3)
98+
assert.strictEqual(currentUser, user2)
99+
})
100+
})
101+
102+
describe('any time by action type', () => {
103+
const store = createStore(reducer, initState, enhancer)
104+
let triggerCount = 0
105+
let currentUser = store.getState().user
106+
const off = store.on(SET_USER, (prevState, state) => {
107+
triggerCount++
108+
currentUser = state.user
109+
})
110+
111+
it('must return a function for drop listener', () => {
112+
assert.isFunction(off)
113+
})
114+
115+
it('must handle once if dispatch once', () => {
116+
store.dispatch({ type: INC_ID })
117+
store.dispatch({ type: SET_USER, payload: user })
118+
store.dispatch({ type: INC_ID })
119+
assert.strictEqual(triggerCount, 1)
120+
assert.strictEqual(currentUser, user)
121+
})
122+
123+
it('must handle 3 times after more dispatches', () => {
124+
store.dispatch({ type: SET_USER, payload: user1 })
125+
store.dispatch({ type: INC_ID })
126+
store.dispatch({ type: SET_USER, payload: user2 })
127+
store.dispatch({ type: INC_ID })
128+
assert.strictEqual(triggerCount, 3)
129+
assert.strictEqual(currentUser, user2)
130+
})
131+
132+
it('must not handle change if drop listener', () => {
133+
off()
134+
store.dispatch({ type: SET_USER, payload: user })
135+
store.dispatch({ type: SET_USER, payload: user1 })
136+
assert.strictEqual(triggerCount, 3)
137+
assert.strictEqual(currentUser, user2)
138+
})
139+
})
140+
141+
describe('any time by action type and predicate', () => {
142+
const store = createStore(reducer, initState, enhancer)
143+
let triggerCount = 0
144+
let currentUser = store.getState().user
145+
const off = store.on(
146+
SET_USER,
147+
(prevState, state) => state.user.age <= 21,
148+
(prevState, state) => {
149+
triggerCount++
150+
currentUser = state.user
151+
}
152+
)
153+
154+
it('must return a function for drop listener', () => {
155+
assert.isFunction(off)
156+
})
157+
158+
it('must handle once if dispatch a user who age is 20', () => {
159+
store.dispatch({ type: SET_USER, payload: user })
160+
assert.strictEqual(triggerCount, 1)
161+
assert.strictEqual(currentUser, user)
162+
})
163+
164+
it('must not handle if dispatch a user who age is 22', () => {
165+
store.dispatch({ type: SET_USER, payload: user2 })
166+
assert.strictEqual(triggerCount, 1)
167+
assert.strictEqual(currentUser, user)
168+
})
169+
170+
it('must handle 3 times after more dispatches', () => {
171+
store.dispatch({ type: INC_ID })
172+
store.dispatch({ type: SET_USER, payload: user1 })
173+
store.dispatch({ type: SET_USER, payload: user })
174+
store.dispatch({ type: SET_USER, payload: user2 })
175+
assert.strictEqual(triggerCount, 3)
176+
assert.strictEqual(currentUser, user)
177+
})
178+
})
179+
180+
describe('only once by predicate', () => {
181+
const store = createStore(reducer, initState, enhancer)
182+
let triggerCount = 0
183+
let currentUser = store.getState().user
184+
const off = store.once((prevState, state) => {
185+
return prevState.user !== state.user
186+
}, (prevState, state) => {
187+
triggerCount++
188+
currentUser = state.user
189+
})
190+
191+
it('must return a function for drop listener', () => {
192+
assert.isFunction(off)
193+
})
194+
195+
it('must handle once if dispatch once', () => {
196+
store.dispatch({ type: INC_ID })
197+
store.dispatch({ type: SET_USER, payload: user })
198+
store.dispatch({ type: INC_ID })
199+
assert.strictEqual(triggerCount, 1)
200+
assert.strictEqual(currentUser, user)
201+
})
202+
203+
it('must handle once after more dispatches', () => {
204+
store.dispatch({ type: SET_USER, payload: user1 })
205+
store.dispatch({ type: INC_ID })
206+
store.dispatch({ type: SET_USER, payload: user2 })
207+
store.dispatch({ type: INC_ID })
208+
assert.strictEqual(triggerCount, 1)
209+
assert.strictEqual(currentUser, user)
210+
})
211+
})
212+
})
213+
})
214+
})

0 commit comments

Comments
 (0)