0

I have my tests passing at the moment. I just want to double check if this is the correct way to check a method. If not, please make the correction if possible

This is what I have so far : file.test.js

 it ('handleChange: should call correctly ',() => {
   const wrapper = shallow(<Component {...baseProps } />);
   expect(wrapper).toMatchSnapshot();
   wrapper.setState({e: 'test'});
   expect(wrapper.instance().handleChange({target: {value : 'id'}}))
   expect(wrapper.instance().handleChange({target: {name : 'key'}}))
});

it('deleteAxis : should call correctly',() => {
  const wrapper = shallow(<Component {...baseProps } />);
  expect(wrapper).toMatchSnapshot();
  wrapper.setState({});
  expect(wrapper.instance().deleteAxis({ id:{} }))
})

This is part of the main file. File.js

handleChange = (e) => {
  let localState = {}
  let key = e.target.name
  let value = e.target.value
  localState[key] = value
  localState['id'] = this.props.id
  this.props.addNewAxis(localState)
  this.setState(localState)
}

deleteAxis = () => {
  this.props.deleteAxisByID(this.props.id)
}

I expect both methods to be tested and pass the right way. I have both working at the moment but unsure if its correct. Thanks

skyboyer
  • 22,209
  • 7
  • 57
  • 64
userr2591
  • 81
  • 1
  • 3
  • 12
  • `expect(wrapper.instance().handleChange({target: {value : 'id'}}))` what are you expecting from that? You're testing the method can be called, not that it does anything you expect it to do – Matthew Herbst Jan 30 '19 at 04:08

2 Answers2

0

You can move repetitive code into a describe block's beforeEach function and you can check and make sure addNewAxis and deleteNewAxisByID are being called with the correct values. Lastly, your handleChange function is a bit confusing because of the naming convention, instead try to keep it one to one.

You can change your handleChange function to:

handleChange = e => {
  const { name, value } = e.target;
  const { id } = this.props;
  const newAxis = { id, [name]: value };    
  this.setState(newAxis, () => this.props.addNewAxis(newAxis)); //updates state first, then once updated, calls addNewAxis
}

Then you can test the methods and subsequent function calls:

import React from 'react';
import { shallow } from 'enzyme';
import SomeComponent from './SomeComponent.js';

// jest mock functions (mocks this.props.func)
const addNewAxis = jest.fn();
const deleteAxisByID = jest.fn();

// defining this.props
const initialProps = {
  id: "abcd-1234-efgh-5678",
  addNewAxis,
  deleteAxisByID
}

describe('Some Component', () => {
  let wrapper;
  beforeEach(() => wrapper = shallow(<SomeComponent {...initialProps } />)); // before each test, shallow mount the Component

  // Option 1 - adding a spy, updating the instance and manually changing the input
  it('handles input changes and updates addNewAxis with a new value`, () => {
    const name = "Line 10";
    const value = 144;
    const { id } = initialProps;
    const newAxis = { id, [name]: value };

    const spy = jest.spyOn(wrapper.instance(), 'handleChange'); // spys an instance of Component's handleChange method
    wrapper.instance().forceUpdate(); // updates the instance to include the spy

    const input = wrapper.find('input'); // finds the input -- you can also find by className or some other identifying DOM element: wrapper.find('input.add-axis')
    input.simulate('change', { target: { value, name } }); // simulates an onChange event with values

    expect(spy).toBeCalled(); 
    expect(wrapper.state()).toContain(newAxis);
    expect(addNewAxis).toBeCalledWith(newAxis);
    spy.mockClear();
  });

  // Option 2 - calling the method directly
  it('handles input changes and updates addNewAxis with a new value`, () => {
    const name = "Line 10";
    const value = 144;
    const { id } = initialProps;
    const newAxis = { id, [name]: value };

    wrapper.instance().handleChange({ target: { value, name } }); // calls the instance handleChange method directly

    expect(wrapper.state()).toContain(newAxis);
    expect(addNewAxis).toHaveBeenCalledWith(newAxis);
  });

    // Same 2 options as above, up to your personal preference
  it('deletes an axis`, () => {
    const { id } = initialProps;

    wrapper.instance().deleteAxis();

    expect(deleteAxisByID).toHaveBeenCalledWith(id);
  });

});
Matt Carlotta
  • 18,972
  • 4
  • 39
  • 51
  • Why spy on the instance method, you are calling the method in the next line anyways when using Option 2? – vamsiampolu Jan 30 '19 at 06:17
  • Also, you can remove `spy = jest.spyOn(wrapper.instance(), 'deleteAxis');` on `Option 2`. Now you can keep the spy local to `Option 1` instead of using a `let`. – vamsiampolu Jan 30 '19 at 06:21
  • I never used spy functions before - check what I wrote as an answer - @mattcarlotta – userr2591 Jan 30 '19 at 12:10
  • I will stick with option 2 most likely - i Just ran the code - i get an error because of this line expect(wrapper.state()).toContain(newAxis); . Expected object: {"Line 10": 144, "id": "test Id"} To contain value: {"Line 10": 144, "id": "test Id"} They are both the same, it should pass. But when I comment the line, everything runs fine – userr2591 Jan 30 '19 at 12:45
  • @mattcarlotta any ideas ? – userr2591 Jan 31 '19 at 20:33
  • Try `toBe` instead of `toContain`. – Matt Carlotta Jan 31 '19 at 21:27
0

this is what I usually do when I am writing an unit test file

Describe(' FILE NAME', () => {

  let tree;
  let baseProps;
  let mockdefaultDataFromViewXML =  jest.fn().mockReturnValue({});
  let mockaddAxisList = jest.fn().mockReturnValue({});

beforeEach(() => {

baseProps = { 

 defaultDataFromViewXML : mockdefaultDataFromViewXML,
 addAxisList : mockaddAxisList,
userr2591
  • 81
  • 1
  • 3
  • 12