2016-04-11 10 views
7

Ich verwende CSSTransitionGroup, um ein Element zu animieren, wenn es im DOM erscheint oder wenn es das DOM verlässt. Es läuft gut.Deaktivieren Sie die CSSTransitionGroup von React im Test

Jetzt - ich möchte Unit-Test diese Komponente. Ich erstelle einen temporären DOM-Knoten und füge ihn an die <body> an, ich rendere meine Komponente hinein und führe dann einige Aktionen aus. Als Ergebnis erwarte ich, dass ein untergeordneter DOM-Knoten verschwindet.

Das Problem: Animationsklassen werden angewendet, und die Komponente bleibt im DOM, bis die CSS-Animationen enden. Dies bedeutet, dass mein Test auch einige hundert Millisekunden warten sollte, bevor ich behaupten kann, dass dieses Element weg ist. Ich kann das nicht - ich möchte, dass meine Tests schnell sind, da es sich um Unit-Tests handelt.

Die Frage: Gibt es eine Möglichkeit, CSS-Übergänge zu deaktivieren, ohne zusätzliche Optionen zu meiner Komponente hinzuzufügen?

Was ich versucht habe: Unit-Tests selbst funktioniert gut. Ich kann Animationen loswerden, indem ich einen Parameter an meine Komponente übergebe, der dafür sorgt, dass CSSTransitionGroup nicht verwendet wird. Also - Worst-Case-Szenario - werde ich genau das tun. Aber ich suche nach einer besseren Lösung.

Ich könnte auch behaupten, dass "-enter"/"- enter-active"/"- leave"/"- leave-active" Klassen auf einem fraglichen Element vorhanden sind. Das scheint ein bisschen hacky zu sein, da ich mir einen Fehler vorstellen könnte, bei dem diese Klassen angewendet werden, aber das Element im DOM bleiben würde. Ich möchte lieber nicht auf diesen Ansatz zurückgreifen.

+0

Sie könnten die Komponente verspotten. Wenn Sie Jest verwenden, können Sie ['ReactTestUtils.mockComponent'] (https://facebook.github.io/react/docs/test-utils.html#mockcomponent) verwenden. Ich würde nicht die Funktionalität von 'CSSTransitionGroup' direkt testen. – Aaron

+0

Wie wäre es mit Money Patching reagieren Komponente beim Ausführen der Tests? und dann deaktivierst du CSSTransitionGroup dort. – goldylucks

+0

Ich habe das am Ende gemacht @AdamGoldman. Du hast mich daran erinnert, dass ich hier wahrscheinlich meine eigene Frage beantworten sollte. – kamituel

Antwort

0

Ich ging mit dem Ansatz, der auf der einen Seite macht es einfach, Animationen im Test zu deaktivieren, und auf der anderen Seite erfordert keine Test-spezifische Parameter von jeder der animierten Komponenten unterstützt werden.

Da ich ClojureScript verwenden, Syntax, um einige nicht vertraut sind, aber ich werde es ein wenig kommentieren, um es deutlicher zu machen:

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

In regelmäßigen Code wird diese Klasse auf genau die gleiche Art und Weise verwendet werden, Als Standard würde CSSTransitionGroup verwendet werden.

In Unit-Tests, aber ich animations-enabled als false und sicher behaupten, auf DOM-Elemente hinzugefügt/entfernt sofort binden können:

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

Ich liebe es, wenn jemand meine Antwort ohne Kommentar zu Warum abgibt. Wie auch immer ... dieser Ansatz funktioniert für uns bisher sehr gut. – kamituel

0

Ich hatte eine wirklich harte Zeit Überlegungen über die Antwort ClojureScript vorgesehen, hatte ein ähnliche Anforderung und notiert, das ist scheinbar das einzige Google-Ergebnis zurückgegeben.

Hier ist, wie ich es gelöst, sinon mit:

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

Grundsätzlich Stummel die gesamte CSS-Übergang Gruppe heraus in einem div, das entlang den Kindern zu machen. Das mag nicht schön sein, aber es scheint ziemlich gut für meine Bedürfnisse zu funktionieren.

+0

Ich höre dich, Lisp ist anfangs schwer zu lesen;) Aber deine Lösung macht Sinn. Es ist nicht zu 100% dasselbe wie meines (ich habe 'CSSTransitionGroup' in eine testspezifische Klasse geschrieben, du verwendest Stubs), also würde ich sagen, dass meins etwas sauberer ist - vielleicht, aber deins vermeidet eine zusätzliche Klasse. Prost! – kamituel

1

Ich glaube es gibt eine bessere Lösung mit proxyquire (proxyquireify in meinem browserify basierten Build). Inspiriert von den vorherigen Antworten.

./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') 
}) 

Hoffnung, dass zukünftige Leser dieser Frage hilft.

0

Nach dieser plans

reagieren-addons-CSS-Übergang-Gruppe ist unter deprecation. Also vielleicht react-motion stattdessen verwenden?