Не удается написать тест моментального снимка компонента, который вызывает метод moment в рендеринге

#javascript #reactjs #unit-testing #jestjs #enzyme

#javascript #reactjs #модульное тестирование #jestjs #enzyme

Вопрос:

Я пытаюсь протестировать следующий компонент:

 import React, { Component } from 'react';
import { connect } from 'react-redux'
import moment from 'moment'
import { SingleDatePicker } from 'react-dates'
import MealList from './MealList';
import { capitalize } from '../helpers/helpers'

export class MealSummary extends Component {
    state = {
        date: moment(),
        calendarFocused: false
    }
    onDateChange = date => {
        if (date) this.setState({ date })
    }
    onFocusChange = ({ focused }) => this.setState({ calendarFocused: focused })

    renderMealCategory = (mealCategory) => {
        return this.props.meals.filter(meal => meal.mealCategory === mealCategory amp;amp; meal.date.isSame(this.state.date, 'day'))
    }

    renderFilteredTotal = (mealCategory) => {
        return this.props.meals.filter(meal => meal.mealCategory === mealCategory amp;amp; meal.date.isSame(this.state.date, 'day'))
            .reduce((sum, n) => sum   n.calories, 0)
    }

    renderTotal = () => (this.props.meals.filter(meal => meal.date.isSame(this.state.date, 'day')).reduce((sum, n) => sum   n.calories, 0))

    renderMeals = () => {
        const categories = ['breakfast', 'lunch', 'dinner', 'snack']

        return categories.map(category => {
            return (
                <div key={category}>
                    <h1>{capitalize(category)}</h1>
                    <MealList meals={this.renderMealCategory(category)} />
                    <h4>Total: {this.renderFilteredTotal(category)}</h4>
                </div>
            )
        })
    }

    render() {
        return (
            <div>
                <h1>Summary Page</h1>
                <SingleDatePicker
                    date={this.state.date}
                    onDateChange={this.onDateChange}
                    focused={this.state.calendarFocused}
                    onFocusChange={this.onFocusChange}
                    numberOfMonths={1}
                    isOutsideRange={() => false}
                    id="caloriEat-meal-summary" />
                {this.renderMeals()}
                <div>
                    <h1>Total Calories Consumed: {this.renderTotal()}</h1>
                </div>
            </div>
        );
    }
}

const mapStateToProps = (state) => ({
    meals: state.meals
})

export default connect(mapStateToProps)(MealSummary)
  

Я написал следующий неудачный тест:

 import React from 'react';
import { shallow } from 'enzyme'
import { MealSummary } from '../../components/MealSummary'
import { meals } from '../fixtures/mealReducer'


describe('<MealSummary />', () => {
    test('should render MealSummary', () => {
        const renderMealCategory = jest.fn()
        const wrapper = shallow(<MealSummary meals={meals} />)
        expect(wrapper).toMatchSnapshot()
    })
})
  

Я получаю сообщение об ошибке:

     TypeError: meal.date.isSame is not a function

      17 | 
      18 |     renderMealCategory = (mealCategory) => {
    > 19 |         return this.props.meals.filter(meal => meal.mealCategory === mealCategory amp;amp; meal.date.isSame(this.state.date, 'day'))
         |                                                                                                ^
      20 |     }
      21 | 
      22 |     renderFilteredTotal = (mealCategory) => {
  

Объект meals обладает meals.date свойством, для которого вызывается метод moment isSame для сравнения даты в пределах состояния. У меня есть довольно много таких функций в отдельных вызовах для корректного рендеринга страницы. Почему функция не распознается? Я попытался передать фиктивную функцию для isSame const isSame = jest.fn() и передал ее в качестве поддержки MealSummary, но это не сработало. Как я могу заставить этот тест корректно работать с методом, который выполняется из другой библиотеки (moment), чтобы я мог заставить его создать снимок?

Ответ №1:

Вы передаете meals из import { meals } from '../fixtures/mealReducer' , нам нужно было бы посмотреть, что находится в редукторе, но я предполагаю, что у вас есть что-то вроде:

 const meals = [{ mealCategory: 'breakfast', date: new Date()}]
  

когда вы должны иметь

 const meals = [{ mealCategory: 'breakfast', date: moment()}]
  

Комментарии:

1. У меня есть ссылка на репозиторий github.com/altafmquadri/caloriEat/blob/master/src/tests /…

2. Дата сохраняется в виде строки moment date: '2020-08-17T18:36:13.173Z',

3. поэтому измените его на date: moment('2020-08-17T18:36:13.173Z'),

4. или сохраните его и измените компонент, чтобы сделать moment(meal.date).isSame

5. уточняющий параметр необязателен — isSame(someDate) проверит, все ли совпадает (год, месяц, день, час, минута, секунда и т.д.), isSame(someDate, 'day') проверит, все ли совпадает >= day (то есть, тот же год, месяц и день). Это просто зависит от того, что вы считаете «тем же», что вы должны использовать.