2 years ago
#37176

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