D. Wall
D. Wall

Reputation: 77

Can't get jest snapshot match to pass

I've been playing around with this for a couple days now but can't get a simple '.toMatchSnapshot' to pass. I clearly don't understand how this works. Should i be changing the setup of my code or my test?

the code:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ListGroup, ListGroupItem } from 'react-bootstrap';
import TodoItem from './TodoItem';
import TodoAPI from '../api/TodoAPI';

export class TodoList extends Component {
    renderTodos = () => {
        const { todos, toggleShowCompleted, searchInput } = this.props;
        if (todos.length === 0) {
            return (
                <div>
                    <p>Nothing Scheduled To Do</p>
                    <hr />
                </div>
            );
        }
        return TodoAPI.filterTodos(
            todos,
            toggleShowCompleted,
            searchInput
        ).map(todo => {
            return (
                <ListGroupItem key={todo.id}>
                    <TodoItem {...todo} />
                </ListGroupItem>
            );
        });
    };
    render() {
        return (
            <ListGroup>
                {this.renderTodos()}
            </ListGroup>
        );
    }
}

function mapStateToProps({ todos, toggleShowCompleted, searchInput }) {
    return { toggleShowCompleted, searchInput, todos };
}

export default connect(mapStateToProps)(TodoList);

the test:

import React from 'react';
import { shallow } from 'enzyme';
import { TodoList } from './TodoList';

describe('TodoList', () => {
    const props = {
        todos: { id: 1234, text: 'walk the cat' },
        toggleShowCompleted: false,
        searchInput: ''
    };
    const todoList = shallow(<TodoList {...props} />);

    it('renders properly', () => {
        expect(todoList).toMatchSnapshot();
    });
});

the error:

FAIL src\components\TodoList.test.js ● TodoList › encountered a declaration exception

FAIL src\components\TodoList.test.js ● TodoList › encountered a declaration exception

TypeError: filteredTodos.filter is not a function

  at Object.filterTodos (src/api/TodoAPI.js:27:33)

so it's erroring over my TodoAPI but i'm not sure how to fix this issue. here is the code for over in the 'TodoAPI.js'

const APIFunctions = {
    setTodos(todos) {
        if (Array.isArray(todos)) {
            localStorage.setItem('todos', JSON.stringify(todos));
            // return original array if if fails
            return todos;
        }
    },

    getTodos() {
        const stringTodos = localStorage.getItem('todos');
        let todos = [];

        try {
            todos = JSON.parse(stringTodos);
        } catch (e) {
            // stick with default array
        }

        // insure we actaully have an array and not any malicious code
        return Array.isArray(todos) ? todos : [];
    },

    filterTodos(todos, showCompleted, searchInput) {
        var filteredTodos = todos;
        // filter by showCompleted
        filteredTodos = filteredTodos.filter(todo => {
            // if todo.completed === false continue to show the todo OR if showCompleted === true continue to show todo
            return !todo.completed || showCompleted;
        });
        // filter by searchText
        filteredTodos = filteredTodos.filter(todo => {
            const text = todo.text.toLowerCase();
            return searchInput.length === 0 || todo.text.indexOf(searchInput) > -1;
        });
        // sort todos with non-completed first
        filteredTodos.sort((a, b) => {
            // if a is not completed and b is completed a should come before b
            if (!a.completed && b.completed) {
                return -1;
                // if a is completed and b isn't completed b should come before b
            } else if (a.completed && !b.completed) {
                return 1;
            } else {
                // a is equal to b and thus, no reason to sort
                return 0;
            }
        });
        return filteredTodos;
    }, ...

Upvotes: 1

Views: 2377

Answers (1)

stevejay
stevejay

Reputation: 884

Your unit test sets the prop todos to be an object but your TodoAPI. filterTodos method seems to be expecting an array instead. An object in JavaScript does not have a filter method, hence the error message, whereas an array does.

My advice:

  • Use propTypes on your components to catch these kind of errors at the earliest opportunity.
  • Prefer to mock methods like TodoAPI.filterTodos. In a snapshot test, you're normally wanting to test the component rather than functions in other modules, like filterTodos, that the component invokes. Such functions can be tested with their own unit tests.

Upvotes: 3

Related Questions