How to test style for a React component attribute with Enzyme

ReactjsEnzyme

Reactjs Problem Overview


I am trying to test a style attribute for a React component. What is the best way to get style params in the test?

At this moment, my best option is to test if the HTML includes the string, but I think there is a better option.

Case:

it('Should render large image when desktop', () => {
    const dummyUrl = 'http://dummyUrl';
    const wrapper = shallow(
      <MockedStore
        initialState={{
          app: fromJS({ browser: { desktop: true } }),
        }}
      >
        <LandingHero bigImage={dummyUrl} />
      </MockedStore>
    );
  });

The Component to test is:

// @flow
import React, { Component } from 'react';
import gc from 'styles/core.scss';
import $ from 'jquery';
import DownloadButton from 'components/DownloadButton';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import DownArrow from 'components/DownArrow';
import { connect } from 'react-redux';
import type { Map } from 'immutable';
import c from './styles.scss';

@withStyles([gc, c])
@connect(({ app }) => ({ app }))
class LandingHero extends Component {
  componentDidMount() {
    if ($(window).height() > 0) { // Necesary for webpack dev server
      $(this.hero).css('height', $(window).height() - 46);
    }
  }

  hero: HTMLElement;

  props: {
    app: Map<string, any>,
    copy: string,
    secondaryText: string,
    thirdText: string,
    bigImage?: string,
    smallImage: string,
  }

  render() {
    const { copy, secondaryText, thirdText } = this.props;
    const browser = this.props.app.has('browser') ? this.props.app.get('browser') : {};
    const backgroundImage = browser.desktop ? this.props.bigImage : this.props.smallImage;

    return (
      <div
        className={`${c.hero} ${gc.textCenter}` +
        ` ${gc.alignMiddle} ${gc.alignCenter} ${gc.row} ${gc.expanded}`}
        ref={(hero) => { this.hero = hero; }}
        style={{
          margin: 0,
          position: 'relative',
          background: `linear-gradient(to bottom, rgba($ixdarkprimary, .3), rgba($ixdarkprimary, .3)), url(${backgroundImage || ''})`,
        }}
      >
        <div className={`${gc.row} ${gc.alignCenter} ${gc.alignMiddle} ${gc.column} ${gc.medium10}`}>
          <div className={`${gc.textCenter}`}>
            <div
              className={`${gc.white} ${c.mainText} ${c.copy}`}
            >
              { copy }
            </div>
            <div className={`${gc.small6} ${gc.smallOffset3} ${gc.medium4} ${gc.mediumOffset4}`} style={{ marginBottom: 45 }}>
              <DownloadButton />
            </div>
            <div className={`${gc.white} ${gc.fontBold} ${gc.font24}`}>{secondaryText}</div>
            <p className={`${gc.white} ${gc.font20}`}>{thirdText}</p>
          </div>
          <DownArrow goTo="#content" />
        </div>
      </div>
    );
  }
}

export default LandingHero;

Reactjs Solutions


Solution 1 - Reactjs

You can use this method. It returns ReactElement.

let containerStyle = container.get(0).style;
expect(containerStyle).to.have.property('opacity', '1');

Solution 2 - Reactjs

Slightly elaborating on others' answers:

expect(component.find('#item-id').prop('style')).toHaveProperty('backgroundSize', '100%');

This will check the style prop of #item-id. This prop is an object and here toHaveProperty matcher checks if this object contains backgroundSize property and if its value is 100%.

This way other style properties are ignored.

Solution 3 - Reactjs

const elem = wrapper.find(Element);
expect(getComputedStyle(elem.getDOMNode()).getPropertyValue('opacity')).toBe('0.4');

Solution 4 - Reactjs

expect(component.find('#item-id').prop('style')).to.deep.equal({display: 'none'})

Solution 5 - Reactjs

If you use jest-styled-components then you can use toHaveStyleRule as follows:

Solution 6 - Reactjs

Have a look at chaiEnzyme, which provides a handy little assertion you can use with chai to check whether a wrapper has a particular style (https://github.com/producthunt/chai-enzyme#stylekey-val), should help make your tests look a little cleaner.

Solution 7 - Reactjs

For me, it was a mash-up for a few answers. For those also using Jest / Enzyme:

let containerStyle = wrapper.find('#item-id').get(0).props.style;

expect(containerStyle).toHaveProperty('opacity', '1'); // ('propert', 'value')

Note:

  • find returns a ShallowWrapper so we need to .get(0) the first matching element
  • .props is an attribute not a function in this instance
  • jest uses toHaveProperty not to.have.property

Solution 8 - Reactjs

I would like to add that the following props() method can also be used. https://airbnb.io/enzyme/docs/api/ShallowWrapper/props.html

let containerStyleOpacity = container.get(0).props().style.opacity; expect(containerStyleOpacity).to.be.equal('1');

Solution 9 - Reactjs

This works for me also.

expect(containerStyle.getDOMNode()).toHaveStyle('opacity : 0');

I had to do this to replace

expect(getComputedStyle(checkbox.getDOMNode()).getPropertyValue('opacity')).toBe('0');

which worked when I ran the test locally in my Intellij IDE. However when I ran it using npm t it failed. Must be something to do with how getComputedStyle was being computed in the different scenarios.

toHaveStyle worked in both 

Solution 10 - Reactjs

I don't know if Enzyme has changed with recent versions but I needed parentheses after props in order to get the top answer to work.

containerStyle = container.get(0).props().style;

Solution 11 - Reactjs

const node = wrapper.find(Element);
//Checking border property
expect(getComputedStyle(node.getDOMNode()).getPropertyValue('border')).toBe('2px solid red');

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioncristian camilo cede&#241;o gallegoView Question on Stackoverflow
Solution 1 - ReactjsvisortelleView Answer on Stackoverflow
Solution 2 - ReactjsNeurotransmitterView Answer on Stackoverflow
Solution 3 - ReactjsMahdi AbdiView Answer on Stackoverflow
Solution 4 - Reactjscyberjar09View Answer on Stackoverflow
Solution 5 - ReactjsDenisHView Answer on Stackoverflow
Solution 6 - ReactjsBen HareView Answer on Stackoverflow
Solution 7 - ReactjsKitsonView Answer on Stackoverflow
Solution 8 - ReactjsSark PehaView Answer on Stackoverflow
Solution 9 - ReactjsSimon LongView Answer on Stackoverflow
Solution 10 - ReactjsferaleyebrowsView Answer on Stackoverflow
Solution 11 - ReactjsDilipView Answer on Stackoverflow