Isolating Selector Logic for Testing
Create a small suite of selectors that are easy to test in isolation, demonstrating how to structure selectors to hide the state shape and facilitate testing.
// Selector to get all todos
const selectTodos = state => state.todos;
// Selector to get completed todos
const selectCompletedTodos = createSelector(
[selectTodos],
todos => todos.filter(todo => todo.completed)
);
// Selector to get the number of completed todos
const selectNumCompletedTodos = createSelector(
[selectCompletedTodos],
completedTodos => completedTodos.length
);
Defines basic selectors for a todo application. `selectTodos` is a basic selector to get all todos. `selectCompletedTodos` uses `selectTodos` to filter and get only completed todos. `selectNumCompletedTodos` uses `selectCompletedTodos` to count how many todos are completed.
// Selector to get todos with a specific tag
const selectTodosByTag = (state, tag) => state.todos.filter(todo => todo.tags.includes(tag));
Defines a selector `selectTodosByTag` that filters todos by a specific tag. It's not memoized as it receives a dynamic parameter `tag`.
// Testing selectors
// Mock state for testing
const mockState = {
todos: [
{ id: 1, text: 'Learn Redux', completed: false, tags: ['coding', 'study'] },
{ id: 2, text: 'Read 1984', completed: true, tags: ['reading'] },
{ id: 3, text: 'Buy groceries', completed: true, tags: [] }
]
};
// Test selectCompletedTodos
console.assert(JSON.stringify(selectCompletedTodos(mockState)) === '[{"id":2,"text":"Read 1984","completed":true,"tags":["reading"]},{"id":3,"text":"Buy groceries","completed":true,"tags":[]}]', 'selectCompletedTodos test failed');
// Test selectNumCompletedTodos
console.assert(selectNumCompletedTodos(mockState) === 2, 'selectNumCompletedTodos test failed');
Provides an example of how to test the selectors using a mock state. The `selectCompletedTodos` and `selectNumCompletedTodos` selectors are tested against expected results.