首页 > 解决方案 > Testing React component that relies on externally imported js with Enzyme

问题描述

I've got a bit of an annoying issue here while trying to test a react modal class component in Enzyme, the class uses bootstrap and jQuery, application below.

componentDidMount() {
    // @ts-ignore
    $('#' + this.props.modalId).modal('toggle');
    this.addKeydownHandler();
}

componentWillUnmount() {
    this.removeKeydownHandler();
    // @ts-ignore
    $('#' + this.props.modalId).modal('toggle');
}

addKeydownHandler = () => {
    $(document).on('keydown', (e: any) => { this.preventTabKey(e) });
}

removeKeydownHandler = () => {
    $(document).off('keydown', (e: any) => { this.preventTabKey(e) });
}

I'm importing everything needed in my index file so they are accessible across the whole website as below.

import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/css/bootstrap-theme.css';
import * as jquery from 'jquery';
(window as any).jQuery = jquery;
import 'popper.js';
import '../node_modules/bootstrap/dist/js/bootstrap.min.js';

And I'm calling Enzyme's mount as below.

var children = <div className="fgsr" ><p>Test</p></div>
    var modal = Enzyme.mount(
        <Modal modalId={"testId"} >
            {children}
        </Modal>
    );

The problem is when I just mount the Modal for testing I get various errors - "TypeError: $(...).modal is not a function" and "Bootstrap js needs jQuery", if I just add the bootstrap js

The immediate/hacky fix is to simply add the imports below to the Modal class, but obviously don't want to include multiples of large files just to get tests to run.

import * as jquery from 'jquery';
(window as any).jQuery = jquery;
import '../../../../node_modules/bootstrap/dist/js/bootstrap.min.js';

Is there a workaround for this or a way to add extra imports to an Enzyme mounted wrapper?

标签: reactjstypescriptunit-testingenzyme

解决方案


There doesn't seem to be any way of injecting externally imported js files into an enzyme wrapper for testing but there's a good workaround. I simply created a utility test component with all the dependencies imported that took children as props and simply returned the children in that component as below.

import * as React from 'react';
import * as jquery from 'jquery';
(window as any).jQuery = jquery;
import 'popper.js';
import '../../../node_modules/bootstrap/dist/js/bootstrap.min.js';

export interface Props {
    children: JSX.Element;
}

const DependencyContainer = ({ children }: Props) => {
    return (children);
}

export default DependencyContainer;

And then in my test class just wrapped my component in that container.

var modal = Enzyme.mount(
        <DependencyContainer>
            <Modal>
                {children}
            </Modal>
        </DependencyContainer>
    );

This way no additionally files need to be imported into production code.


推荐阅读