ARTICLE AD BOX
I am trying to learn unit testing with React but having some issues. I am trying to load a component and just ensure it loads in before running other tests. Here is the code for my test:
import { render, screen } from "@testing-library/react"; import { Landing } from "../features/landing/Landing"; import { CouponSearch } from "../features/coupon/search/CouponSearch"; import { MemoryRouter } from "react-router-dom"; import { configureStore } from "@reduxjs/toolkit"; import { Provider } from "react-redux"; import { rootReducer } from "../app/store"; test("renders couponsearch", () => { const store = configureStore({ reducer: rootReducer, }); const Wrapper = ({ children }) => { return ( <Provider store={store}> <MemoryRouter initialEntries={["/"]}>{children}</MemoryRouter> </Provider> ); }; render(<CouponSearch showBanner={true} />, { wrapper: Wrapper }); const linkElement = screen.getByText("Select a coupon or search"); expect(linkElement).toBeInTheDocument(); });My CouponSearch is also exported properly:
export const CouponSearch = ({ showBanner, navbar, ...props }) => { const dispatch = useDispatch(); const { search } = useParams(); const navigate = useNavigate(); ... }Here is the full error:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
This error starts showing up with <MemoryRouter> being used, with or without the <Provider>. Not sure how to resolve it, as my components are exported properly.
Here is my package.json imports if it helps:
"dependencies": { "@axe-core/react": "^4.11.0", "@fortawesome/fontawesome-svg-core": "^6.1.1", "@hookform/resolvers": "^2.8.2", "@reduxjs/toolkit": "^1.6.2", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "ace-builds": "^1.4.12", "bootstrap": "^5.2.0-beta1", "browserify": "^17.0.0", "content-disposition": "^0.5.4", "cross-env": "^7.0.3", "downloadjs": "^1.4.7", "fabric": "^5.2.1", "fontfaceobserver": "^2.1.0", "html-react-parser": "^1.4.14", "moment": "^2.29.1", "oidc-client-ts": "^2.0.3", "query-string": "^7.1.1", "rc-tooltip": "^5.1.1", "react": "^17.0.2", "react-accessible-accordion": "^4.0.0", "react-ace": "^9.4.1", "react-bootstrap": "^2.0.0-rc.0", "react-copy-to-clipboard": "^5.0.4", "react-dates": "^21.8.0", "react-device-detect": "^2.1.2", "react-dom": "^17.0.2", "react-dropzone": "^11.4.2", "react-ga4": "^1.4.1", "react-hook-form": "^7.17.5", "react-html-parser": "^2.0.2", "react-intersection-observer": "^8.32.1", "react-oidc-context": "^2.1.0", "react-redux": "^7.2.5", "react-router-dom": "^6.2.2", "react-scripts": "^5.0.1", "styled-components": "^5.3.1", "svgo": "^2.7.0", "tinycolor2": "^1.4.2", "web-vitals": "^1.0.1", "yup": "^0.32.9" }, ``` And here is roughly what my CouponSearch.js looks like: import React, { useEffect, useState } from "react"; import { useDispatch } from "react-redux"; import { useNavigate, useParams } from "react-router-dom"; import styled, { css } from "styled-components"; import { CouponList } from "./components/CouponList"; import { Search } from "./components/Search"; // styled-components... const FirstArrivalContainer = ({ onSearch, onSetFilters, ...props }) => { return ( <SearchContainer> <Title>Select a coupon or search</Title> <Search onSearch={onSearch} onSetFilters={onSetFilters} /> </SearchContainer> ); }; const HasResultsContainer = ({ ...props }) => { return ( // relevant JSX ); }; export const CouponSearch = ({ showBanner, navbar, ...props }) => { const dispatch = useDispatch(); const { search } = useParams(); const navigate = useNavigate(); const [sortType, setSort] = useState(null); const [colorsType, setColors] = useState(null); const [keywordType, setKeyword] = useState(null); const [showFilterList, setShowFilterList] = useState(false); useEffect(() => { if ((colorsType && colorsType.length > 0) || sortType || keywordType) { setShowFilterList(true); } else { setShowFilterList(false); } }, [colorsType, sortType, keywordType, setShowFilterList]); const onSetFilters = (filters) => { // ... }; const onSearch = (search) => { // ... }; return ( <Container aria-label="Coupon Search" {...props}> {showBanner ? ( <FirstArrivalContainer onSearch={onSearch} onSetFilters={onSetFilters} /> ) : ( <HasResultsContainer // props /> )} <CouponList // props /> </Container> ); };