Created
February 5, 2016 19:53
-
-
Save reneviering/5a52ea721b86ea1657e3 to your computer and use it in GitHub Desktop.
Simple redux todo implementation with mocha tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var expect = require('chai').expect; | |
// store | |
const createStore = (reducer) => { | |
let listeners = []; | |
let state; | |
const getState = () => state; | |
const subscribe = (listener) => { | |
listeners.push(listener); | |
return () => { | |
listeners = listeners.filter(l => l !== listener); | |
}; | |
}; | |
const dispatch = (action) => { | |
state = reducer(state, action); | |
listeners.forEach(listener => listener()); | |
}; | |
dispatch({}); | |
return { getState, subscribe, dispatch }; | |
}; | |
// reducer composition | |
const combineReducers = (reducers) => { | |
return (state = {}, action) => { | |
return Object.keys(reducers).reduce((wholeState, key) => { | |
wholeState[key] = reducers[key](state[key], action); | |
return wholeState; | |
}, {}); | |
}; | |
}; | |
// the reducers | |
const todo = (state, action) => { | |
switch(action.type) { | |
case 'ADD_TODO': | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
}; | |
case 'TOGGLE_TODO': | |
if(state.id !== action.id) { | |
return state; | |
} | |
return Object.assign({}, state, { | |
completed: !state.completed | |
}); | |
default: | |
return state; | |
} | |
} | |
const todos = (state = [], action) => { | |
switch(action.type) { | |
case 'ADD_TODO': | |
return [ | |
...state, | |
todo(undefined, action) | |
]; | |
case 'TOGGLE_TODO': | |
return state.map(s => todo(s, action)); | |
default: | |
return state; | |
} | |
}; | |
const createActionCreator = (store) => { | |
let countTodo = 0; | |
const addTodo = (text) => { | |
// async stuff here... on success callback dispatch... | |
store.dispatch({ | |
type: 'ADD_TODO', | |
id: ++countTodo, | |
text: text | |
}); | |
}; | |
const toggleTodo = (id) => { | |
store.dispatch({ | |
type: 'TOGGLE_TODO', | |
id: id | |
}); | |
}; | |
return {addTodo, toggleTodo}; | |
} | |
var todoApp = combineReducers({todos}); | |
describe('todolist', () => { | |
let store; | |
let actionCreator; | |
beforeEach(() => { | |
store = createStore(todoApp); | |
actionCreator = createActionCreator(store); | |
}); | |
it('is empty initially', () => { | |
expect(store.getState().todos).to.deep.equal([]); | |
}); | |
describe('Scenario: Adding a new todo to the todolist', () => { | |
it('rocks', () => { | |
actionCreator.addTodo('Blaaa'); | |
var expectedState = [ | |
{ | |
id: 1, | |
text: 'Blaaa', | |
completed: false | |
} | |
]; | |
expect(store.getState().todos).to.deep.equal(expectedState); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment