-1

I'm trying to test to see if their is no list when no input is entered when executing this test

App.test.tsx

describe('Should test empty array on onSubmit method',() => {
  it('should test empty array  onSubmit method', ()=>{
    const component = shallow(<App/>)
    const form = component.find('Form').at(0);
    const preventDefault = jest.fn();
    // const items = ['Learn react', 'rest', 'go out'];
    // component.setState({
    //  currentTask:"test-task",
    //  tasks:[...items, 'test-task']
    // })

    // form.simulate('submit', { preventDefault });
    // expect(preventDefault).toBeCalled();
    // form.props().onSubmit();
    form.simulate('submit', {preventDefault})
    expect(component.state().tasks.length).toBe(0);

  })
})

However im gettting this error

● Should test empty array on onSubmit method › should test empty array onSubmit method

expect(received).toBe(expected) // Object.is equality

Expected: 0
Received: 1

I noticed that i have linting error that reads this

Property 'tasks' does not exist on type 'Readonly<{}>'.

on this line

expect(component.state().tasks.length).toBe(0);

What should i change to make this pass ?

I referenced something similar to this question

Expected Array but received array in Jest

but the solution didn't work for me.

App.tsx

import React from 'react';
import logo from './logo.svg';
import Form from './Form';
import './App.css';
// we need an interface to be able to use the state properties, if not error.
// the same rule applies when using props
// so here we call Istate
interface IState {
  currentTask: string;
  tasks: Array<string>;
}

export default class App extends React.Component<{}, IState>{
  constructor(props: {}){
    super(props);
    this.state = {
      currentTask: "",
      tasks:[]
    }
  }

  // when using e.preventDefault in typescript, or any paramater, it has to be followed
 //  by the following any, array, string, etc. in this case we use any

  handleSubmit(e: any){
    e.preventDefault();
    this.setState({
      currentTask: "",
      tasks: [...this.state.tasks, this.state.currentTask]
    }, () => {
      console.log(this.state.tasks)
    })


  }

  onChange = (e: any) => {
    e.preventDefault();
    this.setState({
      currentTask: e.target.value
    })

  }

  render(){
    return (
      <div className="App">
        <h1 className="sampleh1">React Typescript Todo</h1>

        <Form 
          onSubmit={(e)=> this.handleSubmit(e)}
          currentTask={this.state.currentTask}
          onChange={this.onChange}  
        />
      </div>
    );

  }
}

side note

if i change code from

expect(component.state().tasks.length).toBe(0);

to

expect(component.state().tasks).toHaveLength(0);

i get this, im confused because their is no values in the array, so why is it receiving 1 and not 0 ???

 Received array:  [""]
skyboyer
  • 22,209
  • 7
  • 57
  • 64
randal
  • 1,272
  • 3
  • 23
  • 48
  • you are adding `this.state.currentTask` to the `tasks` array which makes it `[""]` as said in the error – Agney May 23 '19 at 17:31
  • I see, how would i make this test pass then ? without editing the App.tsx file – randal May 23 '19 at 17:33
  • 1
    you would expect length to be 1, I guess. – Agney May 23 '19 at 17:35
  • that does make it pass, however, if you could refactor this unit test code to make it more easier to understand, how would you do it ? – randal May 23 '19 at 17:36
  • im quite new to testing :). – randal May 23 '19 at 17:37
  • 1
    that very much depends on the use case that you are testing against. Currently, I think you are testing the specifics instead of the use case, but that is longer than discussion allowed on SO. You could try reading os repos or look up [articles](https://kentcdodds.com/blog/how-to-know-what-to-test) – Agney May 23 '19 at 17:42

1 Answers1

1

The error is valid, because in handleSubmit code, you are pushing empty string as an element to the array tasks and hence the length is shown as 1.

this.setState({
      currentTask: "",
      tasks: [...this.state.tasks, this.state.currentTask]
    }

so after above code execution, the state.tasks = [""] // whose length will now be 1. So, if your goal is to push currentTask if it is present then use some conditional operator here.

this.setState(prevState => ({
      currentTask: "",
      tasks: prevState.currentTask ? [...prevState.tasks, prevState.currentTask] : prevState.tasks
    })
Anuradha Kumari
  • 703
  • 5
  • 9