【问题标题】:How to test style for a React component attribute with Enzyme如何使用 Enzyme 测试 React 组件属性的样式
【发布时间】:2017-04-09 07:34:03
【问题描述】:

我正在尝试测试 React 组件的样式属性。在测试中获取样式参数的最佳方法是什么?

此时,我最好的选择是测试 HTML 是否包含字符串,但我认为还有更好的选择。

案例:

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

要测试的组件是:

// @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;

【问题讨论】:

  • 嘿 jacefarm 为了使用 sass(scss),您开玩笑的配置是什么?我的意思是我有以下 ` "moduleNameMapper": { "\\.(scss|css)$": "/src/sassMockForJest.js" },` 但是在使用属性时出现未定义的错误,例如如果我使用与您相同的组件我会看到Cannot read property 'textCenter' of undefined,因为${gc.textCenter}
  • 嘿,你也可以通过导出你的类来摆脱你的模拟商店。你得到:import ConnLandingHero, { LandingHero } from "../LandingHero";这为我们的团队节省了很多时间。

标签: reactjs enzyme


【解决方案1】:

看看 chaiEnzyme,它提供了一个方便的小断言,您可以使用 chai 来检查包装器是否具有特定样式 (https://github.com/producthunt/chai-enzyme#stylekey-val),应该有助于使您的测试看起来更简洁。

【讨论】:

    【解决方案2】:

    您可以使用this 方法。它返回 ReactElement。

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

    【讨论】:

    • 对于那些使用 Jest 的人,请注意它应该是 expect(...).toHaveProperty(...)
    • 应该是container.get(0).props.style
    • 这些都不适合我。 wrapper.get(0).style 返回 undefined 以及 wrapper.get(0).props.style
    • 这只有在 style 是一个 react prop 时才有效,就像 inline-styling 的情况一样
    • 尝试使用wrapper.props().style,就我而言,我直接使用props() 摆脱了get(0),它给了我所需的style 属性
    【解决方案3】:

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

    【讨论】:

    • 深在这里非常重要,thanx
    【解决方案4】:

    稍微详细说明其他人的答案:

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

    这将检查#item-idstyle 属性。这个道具是一个对象,这里toHaveProperty匹配器检查这个对象是否包含backgroundSize属性以及它的值是否为100%

    这样会忽略其他样式属性。

    【讨论】:

      【解决方案5】:

      如果您使用jest-styled-components,那么您可以使用toHaveStyleRule,如下所示:

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

      【讨论】:

        【解决方案6】:
        const elem = wrapper.find(Element);
        expect(getComputedStyle(elem.getDOMNode()).getPropertyValue('opacity')).toBe('0.4');
        

        【讨论】:

        • 如果你想断言应用于特定元素的外部 CSS 样式,这是正确的答案——这与作为道具传递的内联 CSS 样式等相反。
        • 完美运行。太感谢了。这应该是公认的答案!
        【解决方案7】:

        我想补充一点,下面的props()方法也可以使用。 https://airbnb.io/enzyme/docs/api/ShallowWrapper/props.html

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

        【讨论】:

          【解决方案8】:

          对我来说,这是几个答案的混搭。 对于那些也使用 Jest / Enzyme 的人:

          let containerStyle = wrapper.find('#item-id').get(0).props.style;
          
          expect(containerStyle).toHaveProperty('opacity', '1'); // ('propert', 'value')
          

          注意:

          • find 返回一个ShallowWrapper 所以我们需要.get(0) 第一个匹配元素
          • .props 在此实例中是属性而不是函数
          • 开玩笑使用toHaveProperty 而不是to.have.property

          【讨论】:

            【解决方案9】:

            这也适用于我。

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

            我不得不这样做来替换

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

            当我在我的 Intellij IDE 中本地运行测试时,它起作用了。但是,当我使用 npm t 运行它时,它失败了。必须与 getComputedStyle 在不同场景中的计算方式有关。

            toHaveStyle 在这两个地方都工作过 ?

            【讨论】:

              【解决方案10】:

              我不知道 Enzyme 是否在最近的版本中发生了变化,但我需要在 props 后面加上括号才能获得最佳答案。

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

              【讨论】:

                【解决方案11】:
                const node = wrapper.find(Element);
                //Checking border property
                expect(getComputedStyle(node.getDOMNode()).getPropertyValue('border')).toBe('2px solid red');
                

                【讨论】:

                • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票。
                • 相同already existing本页旧答案
                猜你喜欢
                • 2019-09-24
                • 2019-05-30
                • 2017-01-01
                • 2017-04-13
                • 2017-02-12
                • 2018-08-20
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多