React.js tests TypeError: Cannot read property 'pushState' of undefined
React.js tests TypeError: Cannot read property 'pushState' of undefined
我正在尝试为我的 React 组件编写测试。我收到此错误:
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
吗?如果是这样,我该如何模拟它?
我会说这是因为您没有将 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>
)
}
})
历史应该在实例化路由器时创建。当命中每条路线时,历史记录作为道具传递给组件。还应该注意的是,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>
);
}
});
我正在尝试为我的 React 组件编写测试。我收到此错误:
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
吗?如果是这样,我该如何模拟它?
我会说这是因为您没有将 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>
)
}
})
历史应该在实例化路由器时创建。当命中每条路线时,历史记录作为道具传递给组件。还应该注意的是,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>
);
}
});