Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing React Select component

https://github.com/JedWatson/react-select

I would like to use React-Select react component, but I need to add tests.

I've tried several options I found with google, but nothing seems to work. I have the code below, but it's not causing a change event. I have been able to add a focus event, which adds 'is-focussed' class, but the 'is-open' class is still missing.

I have used: https://github.com/JedWatson/react-select/blob/master/test/Select-test.js as a reference

I have tried to use a change event only on the input field, but this has not helped either. I noticed there is a onInputChange={this.change} for the select.

Test

import Home from '../../src/components/home'; import { mount } from 'enzyme'  describe('Home', () => {  it("renders home", () => {      const component = mount(<Home/>);      // default class on .Select div     // "Select foobar Select--single is-searchable"      const select = component.find('.Select');      // After focus event     // "Select foobar Select--single is-searchable is-focussed"     // missing is-open     TestUtils.Simulate.focus(select.find('input'));      //this is not working     TestUtils.Simulate.keyDown(select.find('.Select-control'), { keyCode: 40, key: 'ArrowDown' });     TestUtils.Simulate.keyDown(select.find('.Select-control'), { keyCode: 13, key: 'Enter' });      // as per code below I expect the h2 to have the select value in it eg 'feaure'  }); }); 

Component under test

import React, { Component } from 'react'; import Select from 'react-select';  class Home extends Component { constructor(props) {     super(props);      this.state = {         message: "Please select option"};     this.change = this.change.bind(this); }  change(event) {      if(event.value) {         this.setState({message: event.label});     } }  render () {      const options = [ {label: 'bug', value: 1} , {label: 'feature', value: 2 }, {label: 'documents', value: 3}, {label: 'discussion', value: 4}];      return (       <div className='content xs-full-height'>           <div>               <h2>{this.state.message}</h2>                <Select                   name="select"                   value={this.state.message}                   options={options}                   onInputChange={this.change}                   onChange={this.change}               />            </div>         </div>     ); } }  export default Home; 

Command line To run test I do:

>> npm run test 

and in package.js I have this script:

"test": "mocha --compilers js:babel-core/register -w test/browser.js ./new", 

Test setup

and browser.js is:

import 'babel-register'; import jsdom from 'jsdom';  const exposedProperties = ['window', 'navigator', 'document'];  global.document = jsdom.jsdom('<!doctype html><html><body></body></html>'); 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' }; 

I have also tried using methods for testing outlined here: https://github.com/StephenGrider/ReduxSimpleStarter

Any help will be greatly appreciated

like image 392
Llewellyn Avatar asked Feb 01 '17 22:02

Llewellyn


People also ask

How do you mock select in React?

This is an example of how you could mock a select: jest. mock("react-select", () => ({ options, value, onChange }) => { function handleChange(event) { const option = options. find( option => option.

How do you simulate selection from dropdown jest?

const component = mount(<MyComponent/>); component. find('#dropdown'). at(0). simulate('change', { target: { value: 'item1', name: 'item1' } });


2 Answers

From https://github.com/JedWatson/react-select/issues/1357

Only solution I found was to simulate a selection through key-down events:

wrapper.find('.Select-control').simulate('keyDown', { keyCode: 40 }); // you can use 'input' instead of '.Select-control' wrapper.find('.Select-control').simulate('keyDown', { keyCode: 13 }); expect(size).to.eql('your first value in the list') 
like image 144
Keith Avatar answered Sep 22 '22 04:09

Keith


I've tried both answers listed above, and still no luck.

What did work for me was:

  1. Add classNamePrefix prop - i.e list (as mentioned in the other answers) :

    <Select    classNamePrefix='list'    options={[      { label: 'one', value: 'one' },      { label: 'two', value: 'two' } ]}/> 
  2. select the dropdown indicator & simulate a mouseDown => opened dropdown:

    wrapper   .find('.list__dropdown-indicator')   .simulate('mouseDown', {     button: 0    }); 
  3. expect things to happen i.e. in my case I was checking for the number of dropdown options

    expect(wrapper.find('.list__option').length).toEqual(2); 

    if you have control over the props being sent, you can add a menuIsOpen prop to always have the menu open (aka step 2 in the list).

To select a value from the dropdown, after opening the dropdown:

wrapper.find('.list__option').last().simulate('click', null); 

then you can test either:

expect(wrapper.find('.list__value-container').text()).toEqual('two'); 

or

expect(wrapper.find('.list__single-value').text()).toEqual('two'); 
like image 42
Sanda Avatar answered Sep 22 '22 04:09

Sanda