2 years ago

#37176

test-img

nagehan

How to test a component that renders conditional display?

I try to test a functional component which use useSelector hook to get data from state and renders according to the state. I wrote a test for that component. It seems logical to me and it works. But I'm not sure if it's the correct approach. Here is my test file:

import React from "react";
import ExpensesSummary from "../ExpensesSummary";
import { render, screen } from "@testing-library/react";
import { Provider } from "react-redux";
import expenses from "../../fixtures/expenses";
import { filters } from "../../fixtures/filters";
import configureStore from "redux-mock-store";

test("should correctly render ExpensesSummary with 1 expense", () => {
  const initialState = {
    expenses: [expenses[0]],
    filters,
  };
  const mockStore = configureStore();
  render(
    <Provider store={mockStore(initialState)}>
      <ExpensesSummary />
    </Provider>
  );
  const text = screen.getByText("Viewing 1 expense totaling € 1.95");
  expect(text).toBeInTheDocument();
});

test("should correctly render ExpensesSummary with multiple expenses", () => {
  const initialState = {
    expenses,
    filters,
  };
  const mockStore = configureStore();
  render(
    <Provider store={mockStore(initialState)}>
      <ExpensesSummary />
    </Provider>
  );
  const text = screen.getByText("Viewing 3 expenses totaling € 1,141.95");
  expect(text).toBeInTheDocument();
});

Here is my component that I want to test:

import React from "react";
import { useSelector } from "react-redux";
import numeral from "numeral";
import "numeral/locales/nl-nl";
import {
  selectVisibleExpenses,
  selectTotalExpense,
} from "../store/expenses/selectors";

const ExpensesSummary = () => {
  const visibleExpenses = useSelector(selectVisibleExpenses);
  const totalExpense = useSelector(selectTotalExpense);
  numeral.locale("nl-nl");
  const expenseWord = visibleExpenses.length === 1 ? "expense" : "expenses";
  const formattedExpensesTotal = numeral(totalExpense / 100).format("$0,0.00");

  return (
    <div>
      <h1>
        Viewing {visibleExpenses.length} {expenseWord} totaling {formattedExpensesTotal}
      </h1>
    </div>
  );
};

export default ExpensesSummary;

And the selector file:

export const selectExpenses = (state) => state.expenses;
export const selectVisibleExpenses = (state) =>
  getVisibleExpenses(state.expenses, state.filters);

export const selectTotalExpense = (state) =>
  getTotalExpense(getVisibleExpenses(state.expenses, state.filters));

export const getVisibleExpenses = (
  expenses,
  { text, sortBy, startDate, endDate }
) => {
  return expenses
    .filter((expense) => {
      const createdAtMoment = new Date(expense.createdAt);
      const startDateMatch = startDate ? createdAtMoment >= startDate : true;
      const endDateMatch = endDate ? createdAtMoment <= endDate : true;
      const textMatch = expense.description
        .toLowerCase()
        .includes(text.toLowerCase());

      return startDateMatch && endDateMatch && textMatch;
    })
    .sort((a, b) => {
      if (sortBy === "date") {
        // return -1 if a come first, 1 if b come first
        // most recent expense up top
        return a.createdAt < b.createdAt ? 1 : -1;
      } else if (sortBy === "amount") {
        return a.amount < b.amount ? 1 : -1;
      } else {
        return null;
      }
    });
};

export const getTotalExpense = (expenses) => {
  return expenses
    .map((expense) => expense.amount)
    .reduce((previousValue, currentValue) => previousValue + currentValue, 0);
};

I've tried to mock useSelector but I couldn't test each condition with it. I want to test if I have 1 expense and if I have multiple expenses. Any idea if the test file is correct or not? How should I write tests for a component like this?

Please advise how should I write tests such components.

Thanks in advance.

reactjs

react-redux

react-hooks

jestjs

conditional-rendering

reactjs

react-redux

react-hooks

jestjs

conditional-rendering

0 Answers

Your Answer

Accepted video resources