Skip to content

Commit

Permalink
Refactor TodoSearch with Redux
Browse files Browse the repository at this point in the history
  • Loading branch information
ashleydb committed Feb 6, 2017
1 parent ff55d31 commit acec9f6
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 35 deletions.
4 changes: 0 additions & 4 deletions app/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ store.subscribe(() => {
console.log('New state', store.getState());
});

store.dispatch(actions.addTodo('Clean up'));
store.dispatch(actions.setSearchText('up'));
store.dispatch(actions.toggleShowCompleted());

//Use jQuery to start foundation
$(document).foundation();

Expand Down
2 changes: 1 addition & 1 deletion app/components/TodoApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var moment = require('moment');
// Get the default React version of the TodoList component
import TodoList from 'TodoList';
import AddTodo from 'AddTodo';
var TodoSearch = require('TodoSearch');
import TodoSearch from 'TodoSearch';
var TodoAPI = require('TodoAPI');

//Main component of this app, maintaining state
Expand Down
12 changes: 6 additions & 6 deletions app/components/TodoList.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
var React = require('react');
var {connect} = require('react-redux'); //Partner to Provider
import Todo from 'Todo';
var TodoAPI = require('TodoAPI');

export var TodoList = React.createClass({
render: function() {
var {todos} = this.props;
// All of these props come from the Redux state, setup in connect()
var {todos, showCompleted, searchText} = this.props;

var renderTodoList = () => {
if (todos.length === 0) {
Expand All @@ -13,7 +15,7 @@ export var TodoList = React.createClass({
)
}

return todos.map((todo) => {
return TodoAPI.filterTodos(todos, showCompleted, searchText).map((todo) => {
return (
<div className="row" key={todo.id}>
<div className="small-centered columns">
Expand All @@ -34,11 +36,9 @@ export var TodoList = React.createClass({

// Exports will make the TodoList avialable to be called elsewhere.
// Connect is providing access to state variables from the Redux store.
// This syntax means that we can use todos as if it were a prop on this component.
// This syntax means that we can use all properties of the Redux state as if there were props on this component.
export default connect(
(state) => {
return {
todos: state.todos
};
return state;
}
)(TodoList);
26 changes: 21 additions & 5 deletions app/components/TodoSearch.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
var React = require('react');
var {connect} = require('react-redux');
var actions = require('actions');

var TodoSearch = React.createClass({
export var TodoSearch = React.createClass({
handleSearch: function() {
var searchText = this.refs.searchText.value;
var showCompleted = this.refs.showCompleted.checked;
this.props.onSearch(searchText, showCompleted);
},
render: function() {
var {id, text, time, complete} = this.props;
// All of these props come from the Redux state, setup in connect()
var {dispatch, showCompleted, searchText} = this.props;
return (
<div className="container__header">
<div>
<input type="search" placeholder="Enter search filter" ref="searchText" onChange={this.handleSearch}/>
<input type="search" placeholder="Enter search filter" ref="searchText" value={searchText}
onChange={() => {
var searchText = this.refs.searchText.value;
dispatch(actions.setSearchText(searchText));
}}/>
</div>
<div>
<label>
<input type="checkbox" ref="showCompleted" onChange={this.handleSearch}/> Show Completed To Dos
<input type="checkbox" ref="showCompleted" checked={showCompleted}
onChange={() => {
dispatch(actions.toggleShowCompleted());
}}/> Show Completed To Dos
</label>
</div>
</div>
);
}
});

module.exports = TodoSearch;
export default connect(
(state) => {
return {
showCompleted: state.showCompleted,
searchText: state.searchText
};
})(TodoSearch);
2 changes: 1 addition & 1 deletion app/tests/components/TodoList.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('TodoList', () => {
{id: 3, text: 'profit', createdAt: 300, completedAt: undefined, complete: false},
];

var store = configureStore.configure({todos});
var store = configureStore.configure({todos, showCompleted: true});
var provider = TestUtils.renderIntoDocument(<Provider store={store}><ConnectedTodoList todos={todos}/></Provider>);

var todoList = TestUtils.scryRenderedComponentsWithType(provider, ConnectedTodoList)[0];
Expand Down
31 changes: 17 additions & 14 deletions app/tests/components/TodoSearch.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,48 @@ var expect = require('expect');
var $ = require('jQuery');
var TestUtils = require('react-addons-test-utils');

var TodoSearch = require('TodoSearch');
// Get the React version of the component
import {TodoSearch} from 'TodoSearch';

describe('TodoSearch', () => {
it('should exist', () => {
expect(TodoSearch).toExist();
});

it('should call onSearch as text is entered', () => {
it('should dispatch SET_SEARCH_TEXT when text is entered', () => {
//A spy is a function that we can watch, e.g. for callbacks
var spy = expect.createSpy();
var todoSearch = TestUtils.renderIntoDocument(<TodoSearch onSearch={spy}/>);

//Make sure we know what the checkbox value is, (should be false)
//var check = todoSearch.refs.showCompleted.checked;
var todoSearch = TestUtils.renderIntoDocument(<TodoSearch dispatch={spy}/>);

//Set the value in the form's text field
var testData = 'DOG';
todoSearch.refs.searchText.value = testData;
TestUtils.Simulate.change(todoSearch.refs.searchText);

var action = {
type: 'SET_SEARCH_TEXT',
searchText: testData
};

// The form was changed, so did our spy function get triggered?
//expect(spy).toHaveBeenCalledWith(testData, check);
expect(spy).toHaveBeenCalledWith(testData, false);
expect(spy).toHaveBeenCalledWith(action);
});

it('should call onSearch when completed checkbox is changed', () => {
it('should dispatch TOGGLE_SHOW_COMPLETED when completed checkbox is changed', () => {
//A spy is a function that we can watch, e.g. for callbacks
var spy = expect.createSpy();
var todoSearch = TestUtils.renderIntoDocument(<TodoSearch onSearch={spy}/>);

//Make sure we know what the text value is (should be '')
//var testData = todoSearch.refs.searchText.value;
var todoSearch = TestUtils.renderIntoDocument(<TodoSearch dispatch={spy}/>);

//Change the form's checkbox (should go from false to true)
todoSearch.refs.showCompleted.checked = true;
TestUtils.Simulate.change(todoSearch.refs.showCompleted);

var action = {
type: 'TOGGLE_SHOW_COMPLETED'
};

// The form was changed, so did our spy function get triggered?
//expect(spy).toHaveBeenCalledWith(testData, true);
expect(spy).toHaveBeenCalledWith('', true);
expect(spy).toHaveBeenCalledWith(action);
});
});
8 changes: 4 additions & 4 deletions public/bundle.js

Large diffs are not rendered by default.

0 comments on commit acec9f6

Please sign in to comment.