2

I'm building a test using Mocha and Chai for my ReactJS components. Basically I have this structure for my components:

  • ScheduleApp
    • ScheduleForm

Under my ScheduleForm I'm using this jQuery plugin bootstrap-timepicker. I'm using another plugin called bootstrap-datepicker and it is running just fine notice the componentDidMount on my ScheduleForm.

// ScheduleForm.jsx Component
import React, {PropTypes} from 'react';
import jQuery from 'jquery';
import datepicker from 'bootstrap-datepicker';
import timepicker from 'bootstrap-timepicker';

export default class ScheduleForm extends React.Component {
    handleChange() {
        // Some code to handle the onChange event
    }

    componentDidMount() {
        jQuery(this.refs.startDate).datepicker({
            autoclose: true,
            format: 'yyyy-mm-dd'
        }).on("changeDate", function(e) {
            this.onStartDateChange(e);
        }.bind(this));

        jQuery(this.refs.startTime).timepicker({
            defaultTime: '8:00 AM',
            snapToStep: false
        }).on('changeTime.timepicker', function(e) {
            this.onStartTimeChange(e);
        }.bind(this));

        jQuery(this.refs.endTime).timepicker({
            defaultTime: '2:00 PM',
            snapToStep: false
        }).on('changeTime.timepicker', function(e) {
            this.onEndTimeChange(e);
        }.bind(this));
    }

    render() {
        <div>
            <div className="form-group">
              <label>Start Date</label>
              <input className="form-control" type="text" onChange={this.handleChange} ref="startDate" />
            </div>
            <div className="form-group">
              <label>Start Time</label>
              <input className="form-control" type="text" onChange={this.handleChange} ref="startTime" />
            </div>
            <div className="form-group">
              <label>End Time</label>
              <input className="form-control" type="text" onChange={this.handleChange} ref="endTime" />
            </div>
        </div>
    }
}

Here's my parent component:

// ScheduleApp.jsx Component
import React from 'react';
import ScheduleForm from './schedule-form.jsx';

export default class ScheduleApp extends React.Component {
    constructor() {
        super();
        this.state = {
            startTime: '8:00 AM',
            endTime: '2:00 PM'
        }
    }

    handleStartTimeChange(startTime) {
        this.setState({
            startTime: startTime
        });
    }

    handleEndTimeChange(endTime) {
        this.setState({
            endTime: endTime
        });
    }

    render() {
        return <div>
                    <ScheduleForm
                            handleStartTimeChange={this.handleStartTimeChange.bind(this)}
                            handleEndTimeChange={this.handleEndTimeChange.bind(this)}
                            startTime={this.state.startTime}
                            endTime={this.state.endTime} />
                </div>
    }
}

Now here is my test spec for this component:

// test.spec.js
import React from 'react';
import { mount, shallow } from 'enzyme';
import {expect} from 'chai';
import ScheduleApp from '../src/components/schedule-app.jsx';
import ScheduleForm from '../src/components/schedule-form.jsx';

describe('<ScheduleApp/>', function() {
  it('contains 1 <ScheduleForm/> component', function() {
    const wrapper = mount(<ScheduleApp />);
    expect(wrapper.find(ScheduleForm)).to.have.length(1);
  });
});

Here is my jsdom file:

if (!global.document) {
  try {
    const jsdom = require('jsdom').jsdom; // could throw

    const exposedProperties = ['window', 'navigator', 'document'];

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

    global.navigator = {
      userAgent: 'node.js',
    };
  } catch (e) {
    // jsdom is not supported...
  }
}

After running my test I get this error TypeError: (0 , _jquery2.default)(...).timepicker is not a function. I can load this field fine without problem on my browser but with my test spec it throws out an error for the timepicker plugin and it's running ok with the datepicker.

Also if it's worth noting, bootstrap-datepicker and bootstrap-timepicker use the same jQuery and only bootstrap-timepicker requires window and document in its function parameter, like so:

(function($, window, document) {
}())

Also, is there a way to find out where the jQuery plugin is failing? This would have been really easy if I it shows it on the logs.

Any help would be much appreciated.

JohnnyQ
  • 4,839
  • 6
  • 47
  • 65

1 Answers1

0

You probably have to import jQuery for your spec as it uses a global.

import jQuery from 'jquery';
vijayst
  • 20,359
  • 18
  • 69
  • 113
  • Thanks for your response. But I've already tried that before and still throws out the same error. :( Both `bootstrap-datepicker` and `bootstrap-timepicker` use the same jQuery but only `bootstrap-timepicker` throws out an error. – JohnnyQ Sep 08 '16 at 03:05
  • Did u try importing the plugins as well? – vijayst Sep 08 '16 at 04:42
  • Adding jQuery to window will also help. – vijayst Sep 08 '16 at 04:50