Solvedreact fontawesome Add documentation for Jest mocks

I was facing some console error messages with components relying that had FontAwesomeIcons in them. Didn't stop tests from passing, but made for some overly chatty tests. I'm not an expert on Jest at this point, so it took a bit of fumbling around to settle on something that worked. I'd like to add some documentation for other newbies, so I first want to know if the way I did it is any good.

First I used spyOn(console, "error"); to suppress the errors, but of course that hides other problems.

I'm using create-react-app, and created a manual mock insrc/__mocks__/@fortawesome/react-fontawesome.js, with this code:

import React from "react";

export function FontAwesomeIcon(props) {
  return <i className="fa" />;
}

That works for me. I'd rewrite it as docs, of course, but is the approach good?

19 Answers

✔️Accepted Answer

If you are using create-react-app there is an easier way than mocking. Create a module that just does the registering of the icons, maybe named registerFaIcons.js. This can then be used by both your React application as well as the Jest tests.

import { library } from '@fortawesome/fontawesome-svg-core';
import {
	faSpinner
} from '@fortawesome/free-solid-svg-icons';

export default function registerIcons() {
	library.add(
		faSpinner
	);
}

So with create-react-app, within your setupTests.js file you can put code that imports and calls the registerIcons method. This will register the icons for use by all tests and the FA icons will render as expected.

import registerFaIcons from './registerFaIcons';

registerFaIcons();

Other Answers:

I thought I'd share our version of the mock. We're outputting an empty <svg> element to match the current implementation, with only the appropriate class names (which will help any element getters in the test). We also allow the icon prop to be an object as imported from the Font Awesome libraries.

/**
 * Mocks @fortawesome/react-fontawesome.js to return a simple, empty <svg> element
 * with the correct class name for the given `icon` prop. We use this to keep full
 * <svg> content out of our rendered component tests.
 */
import React from 'react'
import PropTypes from 'prop-types'

export function FontAwesomeIcon (props) {
  const classNames = ['svg-inline--fa']

  if (typeof props.icon === 'string') {
    classNames.push(props.icon)
  } else {
    classNames.push(`fa-${props.icon.iconName}`)
  }

  return <svg className={classNames.join(' ')} />
}

FontAwesomeIcon.propTypes = {
  icon: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.shape({
      prefix: PropTypes.string,
      iconName: PropTypes.string,
      icon: PropTypes.arrayOf(PropTypes.any)
    })
  ]).isRequired
}

More Issues: