【问题标题】:Disable React's CSSTransitionGroup in test在测试中禁用 React 的 CSSTransitionGroup
【发布时间】:2016-04-11 13:59:34
【问题描述】:

当元素出现在 DOM 中或离开 DOM 时,我正在使用 CSSTransitionGroup 为元素设置动画。效果很好。

现在 - 我想对这个组件进行单元测试。我正在创建一个临时 DOM 节点并将其附加到 <body>,我将组件渲染到其中,然后执行一些操作。因此,我希望子 DOM 节点会消失。

问题: 应用动画类,组件保存在 DOM 中,直到 CSS 动画结束。这意味着我的测试也应该等待几百毫秒,然后我才能断言该元素已消失。我不能那样做 - 我希望我的测试很快,因为这些是单元测试。

问题: 有没有办法在不向我的组件添加额外选项的情况下禁用 CSS 过渡?

我尝试了什么: 单元测试本身运行良好。我可以通过将参数传递给我的组件来摆脱动画,这将使它不使用CSSTransitionGroup。所以 - 最坏的情况 - 我会这样做。但我正在寻找更好的解决方案。

我还可以断言“-enter”/“-enter-active”/“-leave”/“-leave-active”类存在于相关元素上。不过,这似乎有点 hacky,因为我可以想象应用这些类的错误,但元素将保留在 DOM 中。我不想采用这种方法。

【问题讨论】:

  • 你可以模拟这个组件。如果你使用 Jest,你可以使用 ReactTestUtils.mockComponent。我不会费心直接测试CSSTransitionGroup 的功能。
  • 在运行测试时如何修补反应组件?然后你在那里禁用 CSSTransitionGroup。
  • 我最终做到了@AdamGoldman。你提醒我我应该在这里回答我自己的问题。

标签: unit-testing reactjs reactcsstransitiongroup


【解决方案1】:

使用 Jest 这是我想出的解决方案。我嘲笑了Transition 组件。由于我的导入看起来像 import {Transition} from 'react-transition-group',这就是我创建的:

根据我的笑话配置,在我的 __mocks__ 文件夹中找到的任何内容都将用于代替任何导入。

__mocks__/react-transition-group/index.js:

import Transition from './Transition'

export { Transition }
//more exports to come as I use other parts of react-transition-group

__mocks__/react-transition-group/Transition.js:

import React from 'react'

export default (props) => (
  <div>
    {props.in ? props.children() : null}
  </div>
)

这样,孩子会立即被渲染——“Transition”几乎被禁用了。

**这适用于v2.4.0react-transition-group

【讨论】:

    【解决方案2】:

    http://reactcommunity.org/react-transition-group/testing/

    import { config } from 'react-transition-group'
    
    config.disabled = true
    

    这帮助我摆脱了酶动画

    【讨论】:

    • 仅在开玩笑时也可以使用。
    • 非常简单的方法!
    【解决方案3】:

    我相信使用proxyquire(在我的基于browserify 的构建中的proxyquireify)有一个更简洁的解决方案。受先前答案的启发。

    ./stubs/react_css_transition_group.js:

    const { createElement: el, Component } = require('react')
    
    class ReactCSSTransitionGroup extends Component {
      constructor(props) {
        super(props)
      }
    
      render() {
        const { children, component } = this.props
    
        return el(component, null, children)
      }
    }
    
    ReactCSSTransitionGroup.defaultProps = {
      component: 'div'
    }
    
    module.exports = ReactCSSTransitionGroup
    

    ./foo_test.js:

    const test = require('tape')
    const { mount } = require('enzyme')
    const { createElement: el } = require('react')
    const proxyquire = require('proxyquireify')(require)
    
    const CSSTransitionGroup = require('./stubs/react_css_transition_group')
    
    const Foo = proxyquire('../src/foo', {
      'react-addons-css-transition-group': CSSTransitionGroup
    })
    
    /* pseudocode */
    test('something about bar', (assert) => {
      assert.plan(1)
    
      const foo = el(Foo)
      const wrapper = mount(foo)
    
      assert.equal(wrapper.find('p').first().text(), 'bar')
    })
    

    希望对这个问题的未来读者有所帮助。

    【讨论】:

      【解决方案4】:

      我采用的方法一方面可以很容易地在测试中禁用动画,另一方面 - 不需要每个动画组件支持任何特定于测试的参数。

      由于我使用 ClojureScript,语法可能有些人不熟悉,但我会稍微注释一下以使其更清晰:

      ;; By default, in non-unit-test code, animations are enabled.
      (def ^:dynamic animations-enabled true)
      
      ;; Custom component that essentially wraps React.addons.CSSTransitionGroup,
      ;; but modifies props passed to it whenever animations-enabled
      ;; is set to false.
      (def css-transition-group
        (let [rc-anim-cls (rc/adapt-react-class js/React.addons.CSSTransitionGroup)]
        (rc/create-class
          {:reagent-render
           (fn [anim-spec & children]
             (let [anim-spec-2 (if animations-enabled
                                 ;; If animations are enabled,
                                 ;; pass props through with no change.
                                 anim-spec
                                 ;; If animations are disabled,
                                 ;; override that in props before passing
                                 ;; them to CSSTransitionGroup.
                                 (assoc anim-spec
                                        :transition-enter false
                                        :transition-leave false))]
             (into [rc-anim-cls anim-spec-2] children)))})))
      

      在常规代码中,此类的使用方式与标准 CSSTransitionGroup 的使用方式完全相同。

      然而,在单元测试中,我可以将 animations-enabled 绑定为 false 并安全地断言正在添加/删除的 DOM 元素:

      (binding [anim/animations-enabled false]
        ;; Create component that uses animations. It will not be
        ;; animated though.
        )
      

      【讨论】:

      • 我喜欢有人对我的回答投了反对票,但没有说明原因。无论如何......到目前为止,这种方法对我们很有效。
      • 可能是因为如果你是一个普通的 JS 开发者,上面说的毫无意义。什么是“绑定”?全局变量?
      【解决方案5】:

      我很难对所提供的 ClojureScript 答案进行推理,有类似的要求,并指出这似乎是唯一返回的谷歌结果。

      这是我使用 sinon 解决的方法:

          transitionGroupStub = sinon.stub(ReactCSSTransitionGroup.prototype, 'render', function () {
              return React.createElement('DIV', null, this.props.children)
          })
      

      基本上将整个 css 过渡组存根,以在传递子项的 div 内进行渲染。这可能不漂亮,但它似乎可以很好地满足我的需求。

      【讨论】:

      • 我听到了,Lisp 一开始很难阅读;)但是,您的解决方案是有道理的。它与我的不是 100% 相同(我将 CSSTransitionGroup 包装在一个特定于测试的类中,你使用存根),所以我会说我的更干净一些 - 也许,但你的避免额外的类。干杯!
      【解决方案6】:

      据此plans

      react-addons-css-transition-group 已被弃用。所以也许改用react-motion

      【讨论】:

        猜你喜欢
        • 2015-02-07
        • 1970-01-01
        • 2018-09-02
        • 2017-05-14
        • 2021-11-09
        • 1970-01-01
        • 1970-01-01
        • 2022-11-25
        • 2016-04-17
        相关资源
        最近更新 更多