How to test style for a React component attribute with Enzyme
Asked Answered
P

12

67

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;
Prospective answered 24/11, 2016 at 23:41 Comment(2)
hey jacefarm what is the configuration you use for jest in order to use sass(scss)? I mean I have the following ` "moduleNameMapper": { "\\.(scss|css)$": "<rootDir>/src/sassMockForJest.js" },` but I got undefined errors when using properties for example if I used the same component like you I would see Cannot read property 'textCenter' of undefined because the ${gc.textCenter}Welford
Hey, you can get rid of your mock store by exporting your class as well. You get: import ConnLandingHero, { LandingHero } from "../LandingHero"; It's saved our team a lot of time.Enclosure
T
60

You can use this method. It returns ReactElement.

let containerStyle = container.get(0).style;
expect(containerStyle).to.have.property('opacity', '1');
Titillate answered 30/3, 2017 at 9:29 Comment(8)
For those using Jest, note that it should be expect(...).toHaveProperty(...) instead.Distasteful
It should be container.get(0).props.styleElspeth
Jest can get css style?Beckham
None of these are working for me. wrapper.get(0).style returns undefined as well as wrapper.get(0).props.style.Oiler
this will only work if style is a react prop like in the case of inline-stylingPinot
Same, none of the above worked but this -> wrapper.get(0).props.style worked for me, when prop style is assigned to the componentMazarin
try using wrapper.props().style, in my case I got rid of get(0) by directly using props() and it gave me the required style propertyKevin
Unfortunately if you decide to change the way you do your styling in the future to use stylesheets, you will break all of your unit tests. That why you should not do it this wayRichia
B
35

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.

Butlery answered 29/12, 2017 at 8:50 Comment(0)
T
32
const elem = wrapper.find(Element);
expect(getComputedStyle(elem.getDOMNode()).getPropertyValue('opacity')).toBe('0.4');
Toh answered 20/2, 2019 at 14:43 Comment(4)
this is the correct answer if you want to assert on external CSS style applied to the particular element — that's opposed to inline CSS styles passed as props etc.Makedamakefast
Works perfectly. Thank you so much. This should be the accepted answer!Fleer
great!, i keep thinking thisBussard
The reason this should be the accepted answer, is because it is agnostic of implementation, using other answers, if you decide to move towards external style sheets, you will break all your unit tests, this way, you won'tRichia
C
21

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

Cutaneous answered 28/11, 2017 at 3:31 Comment(1)
deep is very important here thanxJaramillo
S
10

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

expect(component.find('#item-id')).toHaveStyleRule('opacity', 'red');

Sicard answered 1/6, 2018 at 16:40 Comment(0)
H
3

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.

Hance answered 14/12, 2016 at 4:21 Comment(0)
P
3

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
Pizzeria answered 13/5, 2020 at 14:45 Comment(0)
S
1

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');

Schizothymia answered 9/10, 2019 at 18:13 Comment(0)
F
1

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 👍

Fleer answered 18/6, 2020 at 9:10 Comment(0)
H
1

We do like this using import { shallow } from "enzyme";

const component = shallow();

expect(component.find("[id="id_of_element"]")).toHaveStyleRule("border", "2px solid red");

Hickok answered 14/6, 2022 at 11:4 Comment(0)
L
0

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;

Lappet answered 14/10, 2020 at 15:2 Comment(0)
L
0
const node = wrapper.find(Element);
//Checking border property
expect(getComputedStyle(node.getDOMNode()).getPropertyValue('border')).toBe('2px solid red');
Lustre answered 22/12, 2020 at 13:13 Comment(2)
Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.Wernick
identical to already existing older answer in this pageFester

© 2022 - 2024 — McMap. All rights reserved.