摩卡+酶测试反应组件占位符错误

时间:2017-02-09 19:08:41

标签: jquery reactjs enzyme jsdom mocha-webpack

我正在尝试测试依赖于jquery-placeholder的REACT组件,我将jsdom-setup设置为mocha要求,我确实有其他测试运行mocha + chai + react + enzyme,但是当我尝试安装这个组件,而不是使用酶的浅层,它因为jquery占位符插件而失败。

现在,每当我尝试直接在组件上需要jquery-placeholder时,它无法加载组件时窗口未定义错误,或者在访问$ .fn.placeholder时无法访问undefined属性,因此它可能是我的jsdom上的内容-setup,但我不确定它是什么,你能帮我弄清楚如何将占位符jquery插件添加到mocha所需的jsdom-setup或组件本身,以便我可以正确测试。

我正在从npm加载jquery-placeholder包,并使用REACT 0.14.8

这是我的jsdom-setup.js文件:

var jQuery = require('jquery');
var jsdom = require('jsdom').jsdom;
var _ = require('lodash');
var mockSettings = require('./mocks/api/clinical.json');
var appStarter = require('../app/public/resources/react/app');
var exposedProperties = ['window', 'navigator', 'document', 'App'];

global.document = jsdom('');
global.window = global.document.defaultView;
global.window.locale = locale;
global.navigator = {
    userAgent: 'node.js'
};

var $ = global.jQuery = require('jquery')(global.window);
global.$ = global.jQuery;
global.window.jQuery = global.jQuery;
global.window.$ = global.jQuery;


var App = _.assign({ settings: mockSettings.settings.interactive }, mockApp);
appStarter(App);
global.window['App'] = App;

Object.keys(document.defaultView).forEach(function(property) {
    if (typeof global[property] === 'undefined') {
        exposedProperties.push(property);
        global[property] = document.defaultView[property];
    }
});

该组件的要点(为简洁起见省略了一些内容):

var React = require('react');
var ConnectApi = require('../../connect-api');
var SuggestionList = require('../layout/suggestion-list');
var i18nTools = require('../../utils/i18n');

var SearchForm = React.createClass({
    propTypes: {
        onClear: React.PropTypes.func,
        onSubmit: React.PropTypes.func,
        onSelection: React.PropTypes.func,
        currentSearch: React.PropTypes.string,
        selectBy: React.PropTypes.string,
        onPinpoint: React.PropTypes.func,
        filters: React.PropTypes.object
    },

    getInitialState: function () {
        return {
            currentSearch: this.props.currentSearch || '',
            selectBy: this.props.selectBy || '',
            currentSuggestions: [],
            submitted: false,
            locationSupported: (App.settings.geoLocation === true)
        };
    },

    componentDidMount: function () {
        var query = {};
        $('input, textarea').placeholder();

        if (this.state.currentSearch === '' ||
            App.settings.useSearchSuggestions === false) {
            return;
        }

        this.getSuggestions(this.state.currentSearch);
    },



    clearInput: function () {
        this.setState({
            submitted: false,
            currentSearch: ''
        });

        this.props.onClear();
    },


    onSubmit: function (e) {
        var query = {};
        if (e) {
            e.preventDefault();
            e.stopPropagation();
        }
        if (this.refs.search.value === '') {
            this.setState({ inputError: true });
            return;
        }

        this.setState({
            inputError: false,
            submitted: true
        });
    },


    renderSearchActions: function () {
        if (this.state.submitted) {
            return (
                <a className='searchCTA' onClick={this.clearInput} style={ { display: 'block'} }>
                    <span className='icon ion-hapi-close'></span>
                </a>
            );
        } else {
            return (
                <a className='searchCTA' onClick={this.onSubmit}>
                    <span className='icon hapi-search'></span>
                </a>
            );
        }
    },

    renderLocationActions: function() {
        if (this.state.locationSupported) {
            return (
                <a className='pinpointCTA' onClick={this.props.onPinpoint}>
                    <span className='icon hapi-geo'></span>
                </a>
            );
        } else {
            return;
        }
    },

    render: function () {
        var sPlaceholder = App.settings.strings.searchBarPlaceholder || i18nTools.translate('searchBarPlaceholder');

        return (
            <div id='searchform-wrap'>
                <form onSubmit={this.onSubmit}>
                    <div className='input-wrap search'>
                        <input type='text'
                                className={this.state.inputError ? 'error' : ''}
                                ref='search'
                                onChange={this.handleChange}
                                placeholder={sPlaceholder}
                                value={this.state.currentSearch}
                                style={ { display: 'block'} }
                                autoComplete='off' />
                        {this.renderLocationActions()}
                    </div>
                    {this.renderSearchActions()}
                </form>
                <SuggestionList onSelection={this.onSelection} sources={this.state.currentSuggestions}/>
            </div>
        );
    }
});

module.exports = SearchForm;

这是我想要做的测试:

var React = require('react');
var shallow = require('enzyme').shallow;
var mount = require('enzyme').mount;
var expect = require('chai').expect;
var SearchForm = require('../components/clinical/search-form');
var sinon = require('sinon');

describe("Search Form Component", function() {
    var wrapper;
    var onSubmit;

    beforeEach(function () {
        onSubmit = sinon.spy();
    });

    afterEach(function () {
        onSubmit = null;
        wrapper = null;
    });
    describe("when submit search form", function () {
        describe("with query on search form", function  () {
            it("should call onSubmit", function () {
                wrapper = mount(<SearchForm onSubmit={onSubmit}/>);
                var search = wrapper.ref('search')
                // var input = wrapper.find('input');
                // console.log(input.ref('search'));
                // input.ref('search').node.value = "kaiser";
                // input.simulate('change', input)
                // wrapper.find('form').simulate('submit');
                // expect(onSubmit.calledOnce).to.equal(true);
            });

        });
    });
});

以防这是我的gulp测试:

gulp.task('test', ['lint'], function() {
    var mochaOpts = {
        compilers: {
            js: babel
        },
        require: ['./test/jsdom-setup.js'],
        reporter: 'spec'
    };
    if (!!opts.grep) mochaOpts.grep = opts.grep;

    return gulp.src([
        './test/components/**/*.test.js'
    ])
    .pipe(mocha(mochaOpts))
    .once('end', function () {
        process.exit();
    });
});

0 个答案:

没有答案