0
votes

I have a connected component which gets data from Redux store, so basically the component renders the data there is no action to dispatch. I am using antd for rendering the table, in order to set vertical height I am calculating the height and passing to the ref. Also I am using styled components for this sample app.

How can I do the testing using Jest and Enzyme. Most of the articles and sources shows with dispatching a button action and getting the data.

See the below component

table.js

import React, { useState, useEffect, useRef, useLayoutEffect } from "react";
import { Table, Alert, Icon } from "antd";
import { connect } from "react-redux";

import constants from "../constants";
import helpers from "../helpers";
import Style from "./style";
import hooks from "../hooks";
import Icon from "../DisabledIcon";

const {
    column_headings: { top_view, front_view },
    unique_keys: { TOP_VIEW },
} = constants;
const { transformRowData } = helpers;

const { TableContainer } = Style;

const { useWindowSize } = hooks;

const Table = props => {
    const {
        isTableDataLoading,
        tableData,
        selectedView,
        headerHeight,
        isTableError,
        tableErrorMessage,
    } = props;
    const [formattedTableData, setFormattedTableData] = useState([]);
    const [columnHeadings, setColumnHeadings] = useState([]);

    const tableRef = useRef(null);
    const size = useWindowSize();
    const [tableHeight, setTableHeight] = useState(118);

    useEffect(() => {
        if (tableData && tableRef.current) {
            let tableHead = document.querySelector(
                `.${tableRef.current.classList[0]} table > thead`
            );
            const reducedPixel = tableHead.offsetHeight + headerHeight;
            setTableHeight(reducedPixel);
        }
    }, [size, tableData, headerHeight]);

    useEffect(() => {
        if (tableData) {
            let columnTitlesList = selectedView === TOP_VIEW ? top_view : front_view;
            columnTitlesList = columnTitlesList.map(colTitle => {
                if (colTitle.key === "disabled") {
                    return {
                        ...colTitle,
                        render: (text, data) => {
                            return <Icon component={text && Icon} />;
                        },
                    };
                }
                return colTitle;
            });
            setColumnHeadings(columnTitlesList);
            const transformedTableData = transformRowData(tableData.list, columnTitlesList);
            setFormattedTableData(transformedTableData);
        }
    }, [tableData]);

    return (
        <>
            {isTableError ? (
                <Alert
                    message={<p style={{ textAlign: "center" }}>{tableErrorMessage}</p>}
                    type="error"
                />
            ) : (
                <TableContainer ref={tableRef}>
                    <Table
                        columns={columnHeadings}
                        rowClassName={record => !record.isEnabled && "disabled-row"}
                        dataSource={formattedTableData}
                        pagination={false}
                        scroll={{ y: `calc(100vh - ${tableHeight}px)` }}
                        loading={isTableDataLoading}
                    />
                </TableContainer>
            )}
        </>
    );
};

const mapStateToProps = ({ tableState }) => {
    return {
        isTableDataLoading: tableState.isLoading,
        isTableError: tableState.isError,
        tableErrorMessage: tableState.errorMessage,
        tableData: tableState.payload,
        selectedView: tableState.view,
    };
};

export default connect(mapStateToProps, null)(Table);

I have tried writing the basic test, also in the configureStore should I pass the middleware since I am using Redux Thunk.

table.test.js

import React from "react";
import { shallow } from "enzyme";
import configureStore from "redux-mock-store";
import constants from "../constants";
import Table from "../Table";
import { Provider } from "react-redux";

const mockStore = configureStore([]);
const {
    unique_keys: { TOP_VIEW },
} = constants;

describe("Table", () => {
    let store;
    let component;
    beforeEach(() => {
        store = mockStore({
            isLoading: false,
            isError: false,
            errorMessage: null,
            payload: null,
            selectedView: TOP_VIEW,
        });
        component = shallow(
            <Provider store={store}>
                <Table />
            </Provider>
        );
    });

    it("should render the component", () => {
        expect(component).toMatchSnapshot();
    });
});
1

1 Answers

0
votes

Connected components are usually tested by exporting the unconnected version of the component and writing the tests for it. This allows you to control what data and when gets provided to the component and mock actions. And you don't need to mock the store. See the Redux docs for examples.

However, be aware that components with hooks are a bit more difficult to test when using shallow rendering.