Crafting Dropdown with React and Jest

On my last post, I’ve talked about configuring ESlint with Airbnb convention on RubyMine editor. Now, I’m ready to write JavaScript code!

My team use React for creating frontend component, so this time I’ll explain about creating dropdown using React by creating the test first using Jest.

First, I wrote the test on file Dropdown-test.jsx for testing the dropdown,

import React from 'react';
import TestUtils from 'react-addons-test-utils';
import Dropdown from '../Dropdown';

const items = [
  {
    text: 'Facebook',
    link: 'https://facebook.com',
  },
  {
    text: 'Twitter',
    link: 'https://twitter.com',
  },
];

const texts = [];
const links = [];

items.forEach((item) => {
  texts.push(item.text);
  links.push(item.link);
});

describe('dropdown', () => {
  test('renders default title button', () => {
    const dropdown = TestUtils.renderIntoDocument();
    const button = TestUtils.findRenderedDOMComponentWithTag(dropdown, 'button');

    expect(button.textContent).toBe('Dropdown');
  });

  test('renders custom title button', () => {
    const dropdown =
      TestUtils.renderIntoDocument();
    const button = TestUtils.findRenderedDOMComponentWithTag(dropdown, 'button');

    expect(button.textContent).toBe('Social Media');
  });

  test('renders list of items on click', () => {
    const dropdown = TestUtils.renderIntoDocument();
    const button = TestUtils.findRenderedDOMComponentWithTag(dropdown, 'button');
    TestUtils.Simulate.click(button);

    const list = TestUtils.findRenderedDOMComponentWithTag(dropdown, 'ul');
    expect(TestUtils.isDOMComponent(list)).toBe(true);
    expect(TestUtils.scryRenderedDOMComponentsWithTag(dropdown, 'a').map(li =>
      li.textContent,
    )).toEqual(texts);
    expect(TestUtils.scryRenderedDOMComponentsWithTag(dropdown, 'a').map(a =>
      a.getAttribute('href'),
    )).toEqual(links);
  });
});

Then when I run the test something happened 😮

before
What’s wrong? The test is failed :”””

Well, don’t be panic. The test is failed since there isn’t any dropdown component yet. Since we use TDD, so we need to create the test first. Then I create the component based on the test. Basically the dropdown component can be divided to be 3 parts, which are the dropdown itself, dropdown button , and dropdown item. So, I refactored the code and created those parts separately to fulfill the test.

Here’s the code for dropdown item written using React on DropdownItem.jsx,

import React from 'react';

export default class DropdownItem extends React.Component {
  render() {
    return (

); } } DropdownItem.propTypes = { text: React.PropTypes.string, link: React.PropTypes.string, }; DropdownItem.defaultProps = { text: ”, link: ‘#’, };

); } } DropdownItem.propTypes = { text: React.PropTypes.string, link: React.PropTypes.string, }; DropdownItem.defaultProps = { text: ”, link: ‘#’, };

Here’s the contains of DropdownButton.jsx,

import React from 'react';

export default class DropdownButton extends React.Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.props.onClick();
  }

  render() {
    return (
      
        {this.props.title}
        
      
    );
  }
}

DropdownButton.propTypes = {
  title: React.PropTypes.string,
  onClick: React.PropTypes.func.isRequired,
};

DropdownButton.defaultProps = {
  title: 'Dropdown',
};

And last for wrapping up the elements, here’s Dropdown.jsx,

import React from 'react';
import DropdownButton from './DropdownButton.jsx';
import DropdownItem from './DropdownItem.jsx';

export default class Dropdown extends React.Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);

    this.state = {
      opened: false,
    };
  }

  handleClick() {
    this.setState(
      {
        opened: !this.state.opened,
      },
    );
  }

  render() {
    const content = this.state.opened ? (
    {this.props.menuItems.map(item => , )}

) : null; return ( < div className=”dropdown”> {content}

); } } Dropdown.propTypes = { menuItems: React.PropTypes.arrayOf(React.PropTypes.object), title: React.PropTypes.string, }; Dropdown.defaultProps = { menuItems: [], title: ‘Dropdown’, };

After creating the components, let’s see what will happen when running test,

after
Woahh, the test is passed with 100% coverage, nice! 😀

The test is passed with 100% coverage :”) I also wrote those code using Airbnb convention. At first, I got some trouble since I wasn’t really know all the rules but after reading some documentation I could resolve it, what a relieved! 😀

Well, I think this is the end of my current post, goodbye all!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s