2015-12-07 4 views
0

Я пытаюсь написать тесты для моего компонента React. Я получаю эту ошибку:React.js tests TypeError: Не удается прочитать свойство «pushState» undefined

TypeError: Cannot read property 'pushState' of undefined

Мой код выглядит следующим образом:

"use strict"; 


var React = require('react'); 
var ProductAction = require('../actions/product'); 
var Router = require('react-router'); 
var PropTypes = Router.PropTypes; 

var ImportProducts = React.createClass({ 
    contextTypes: { history: PropTypes.history }, 
    getInitialState: function() { 
     return {productList: ''}; 
    }, 
    handleClickImport: function (e) { 
     e.preventDefault(); 
     ProductAction.importProducts(this.state.productList); 
     this.context.history.pushState(null, '/import_result'); 
    }, 
    handleClickCancel: function() { 
     this.setState({productList: ''}); 
    }, 
    onTextChange: function (evt) { 
     this.setState({productList: evt.target.value}); 
    }, 
    render: function() { 
     return (
      <div> 
       <h3> Import Products </h3> 
       <textarea type='text' className='bigTxt' name='prodListTxt'    value={this.state.productList} onChange={this.onTextChange} /> 
      <div className='import-products-container'> 
       <input type='submit'className='srBtn' ref='import' onClick={this.handleClickImport} value='import'/> 
       <input type='submit'className='srBtn' ref='cancel' onClick={this.handleClickCancel} value='cancel'/> 
      </div> 
     </div> 
     ); 
    } 
}); 

module.exports = ImportProducts; 

Мой тест выглядит следующим образом:

require('../test_dom')('<html><body></body></html>'); 

var chai = require('chai'); 
var expect = chai.expect; 
var sinon = require('sinon'); 
var customRequire = require('../custom_require'); 
var proxyquire = require('proxyquire'); 
var reactRouterContext = require('../stubs/react_router_context'); 
var ReactDOMServer = require('react-dom/server'); 

chai.use(require('sinon-chai')); 

describe('Page', function() { 
var React; 
var TestUtils; 
var ReactRouterContext; 

    beforeEach(function() { 
     React = require('react/addons'); 
     TestUtils = React.addons.TestUtils; 
     ReactRouterContext = reactRouterContext; 
    }); 

it('on import button click should clear value in product list', function() { 

    var productAction = customRequire.require('actions/product'); 
    var actionsSpy = sinon.spy(productAction, 'importProducts'); 

    var ParentComponent = proxyquire(customRequire.getPath('components/import_products.js'), { 
     '../actions/product': actionsSpy, 
     'react-router': require('react-router') 
    }); 

    var element = TestUtils.renderIntoDocument(<ParentComponent />); 
    var textArea = TestUtils.findRenderedDOMComponentWithTag(element, 'textarea'); 
    TestUtils.Simulate.change(textArea, { target: { value: '1, 2, 3'} }); 

    var importButton = TestUtils.scryRenderedDOMComponentsWithClass(element, 'srBtn')[0]; 
    console.log(importButton.value); 

    TestUtils.Simulate.click(importButton); 
    expect(actionsSpy.calledOnce).to.be.true; 
    expect(actionsSpy.withArgs('1, 2, 3').calledOnce).to.be.true; 
}); 

Похоже this.context.history.pushState(null, '/import_result'); линия разрыва. this.context.history не определено только при запуске тестов, но это нормально, когда я запускаю код. Должен ли я высмеивать this.context? Если да, то как я могу издеваться над этим?

ответ

0

История должна быть создана, когда маршрутизатор экземпляра. По мере того как каждый маршрут попадает, история передается в качестве опоры для компонента. Следует также отметить, что pushState устарел, и теперь вы просто используете push. См Навигация по https://github.com/rackt/history/blob/master/docs/GettingStarted.md

// Index.js 
import React from 'react'; 
import { Router, Route } from 'react-router'; 
import { createHistory } from 'history'; 
import App from './App.js'; 

const history = createHistory(); 
const routes = (
    <Route to='/'> 
    <Route to='app' component='App' /> 
    </Route> 
); 

React.render(<Router history={ history } routes={ routes } />, document.body); 

// App.js 
export default React.createClass({ 
    onClick() { 
    this.props.history.push('app') 
    }, 
    render() { 
    return (
     <div onClick={this.onClick()}>Go to App</div> 
    ); 
    } 
}); 
+0

безупречный! когда вы пишете тест на этот компонент, используя sinon и chai. Могу ли я знать, как можно u mock this.props.history.push ('app') –

+0

Я еще не написал тестов для этого. Это обновление было довольно недавним. –

+0

ОК .. Спасибо! Я внесу изменения в свой код –

1

Я бы сказал, что это связано с тем, что вы не добавляете React-router к вашему компоненту.

Пример:

import { History } from 'react-router' 

React.createClass({ 
    mixins: [ History ], 
    render() { 
     return (
      <div> 
       <div onClick={() => this.history.pushState(null, '/foo')}>Go to foo</div> 
       <div onClick={() => this.history.replaceState(null, 'bar')}>Go to bar without creating a new history entry</div> 
       <div onClick={() => this.history.goBack()}>Go back</div> 
      </div> 
     ) 
    } 
}) 
+0

выглядит Примеси не действительны ... https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750#. ykhfn9frw –

+0

Это правда. Реагируйте так быстро. –

Смежные вопросы