Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
118 views
in Technique[技术] by (71.8m points)

reactjs - Test failed of a Component in react using typescript

When ever I run the test it fails. I don't know what mistake I am making.

How can I test those if statements and the child component. I am using jest and enzyme for react tests.

This is my test file:

import React from "react";
import { shallow } from "enzyme";
import LaunchContainer from "./index";
import Launch from "./Launch";

describe("render LaunchContainer component", () => {

    let container: any;
    beforeEach(() => { container = shallow(<LaunchContainer setid={()=>{}} setsuccess={()=>{}} />) });

    it("should render LaunchContainer component", () => {
        expect(container.containsMatchingElement(<Launch setsuccess={()=>{}} setid={()=>{}} data={{}}/>)).toEqual(true);
      });

})

The parent component for which the test is used:

import React from "react";
import { useLaunchesQuery } from "../../generated/graphql";
import Launch from './Launch';

interface Props {
    setid: any;
    setsuccess: any;
}

const LaunchContainer: React.FC<Props> = ({setid, setsuccess}) => {
    const {data, loading, error} = useLaunchesQuery();

    if (loading) {
        return <div>loading...</div>
    }

    if (error || !data) {
        return <div>error</div>
    }

    return <Launch setid={setid} data={data} setsuccess={setsuccess} />
}

export default LaunchContainer;

The child component to be added in test:

import React from "react";
import { LaunchesQuery } from "../../generated/graphql";
import './style.css';

interface Props {
    data: LaunchesQuery;
    setid: any;
    setsuccess: any;
}

const Launch: React.FC<Props> = ({setid, data, setsuccess}) => {
    return (
        <div className="launches">
            <h3>All Space X Launches</h3>
            <ol className="LaunchesOL">
                {!!data.launches && data.launches.map((launch, i) => !!launch && 
                    <li key={i} className="LaunchesItem" onClick={() => {
                        setid(launch.flight_number?.toString())
                        setsuccess(JSON.stringify(launch.launch_success))
                    }}>
                        {launch.mission_name} - {launch.launch_year} (<span className={launch.launch_success? "LaunchDetailsSuccess": launch.launch_success===null? "": "LaunchDetailsFailed"}>{JSON.stringify(launch.launch_success)}</span>)
                    </li>
                )}
            </ol>
        </div>
    );
}

export default Launch;
question from:https://stackoverflow.com/questions/65950162/test-failed-of-a-component-in-react-using-typescript

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To test those if statements you should mock your useLaunchesQuery to return the loading, error and data values that hit your if statements. You can use mockImplementationOnce or mockReturnValueOnce. For example you could write

import { useLaunchesQuery } from "../../generated/graphql";

/** 
 * You mock your entire file /generated/graphql so it returns
 * an object containing the mock of useLaunchesQuery.
 * Note that every members in this file and not specified in this mock
 * will not be usable.
 */
jest.mock('../../generated/graphql', () => ({
    useLaunchesQuery: jest.fn(() => ({
        loading: false,
        error: false,
        data: [/**Whatever your mocked data is like */]
    }))
}))

const setid = jest.fn();
const setsuccess = jest.fn();

/**
 * A good practice is to make a setup function that returns
 * your tested component so so you can call it in every test
 */
function setup(props?: any) { // type of your component's props
    // You pass mock functions declared in the upper scope so you can
    // access it later to assert that they have been called the way they should
    return <LaunchContainer setid={setid} setsuccess={setsuccess} {...props} />
    // Spread the props passed in parameters so you overide with whatever you want
}

describe("render LaunchContainer component", () => {
    it('should show loading indicator', () => {
        /** 
         * Here I use mockReturnValueOnce so useLaunchesQuery is mocked to return
         * this value only for the next call of it
         */
        (useLaunchesQuery as jest.Mock).mockReturnValueOnce({ loading: true, error: false, data: [] })

        /** Note that shallow won't render any child of LaunchContainer other than basic JSX tags (div, span, etc)
         * So you better use mount instead 
        */
        const container = mount(setup()); // here i could pass a value for setid or setsuccess

        // Put an id on your loading indicator first
        expect(container.find('#loading-indicator').exists()).toBeTruthy()

        /** The logic for the other if statement remains the same */
    })
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...