【问题标题】:React.js tests TypeError: Cannot read property 'pushState' of undefinedReact.js 测试 TypeError:无法读取未定义的属性“pushState”
【发布时间】:2015-12-07 23:04:43
【问题描述】:

我正在尝试为我的 React 组件编写测试。我收到此错误:

TypeError: 无法读取未定义的属性“pushState”

我的代码如下所示:

"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吗?如果是这样,我该如何模拟它?

【问题讨论】:

    标签: reactjs react-router jestjs react-router-component


    【解决方案1】:

    我会说这是因为您没有将 React-router 的 History mixin 添加到您的组件中。

    例子:

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

    【讨论】:

    【解决方案2】:

    应该在实例化路由器时创建历史记录。当每条路线被命中时,历史记录作为道具传递给组件。还应该注意的是,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>
        );
      }
    });
    

    【讨论】:

    • 完美!当您使用 sinon 和 chai 对该组件编写测试时,我可以知道如何模拟 this.props.history.push('app')
    • 我还没有为此编写测试。这次升级是最近才进行的。
    猜你喜欢
    • 2018-02-27
    • 2021-11-08
    • 1970-01-01
    • 2021-10-24
    • 2019-12-20
    • 2021-04-12
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多