Search code examples
reactjstypescriptjestjstdd

React, Jest tdd with typescript


React, Jest tdd with typescript

Hi

I'm looking at some simple TDD tutorial but I'm trying to use typescript but the tutorials are not in typescript.

The simple exmaple is Class component with a header and a counter.

The test just test that the components load without crashing and clicking the counter increases the counter state.

I have a setup function that creates a shallow ri render the App component

When I call the setup function in the it statement I get the following error.

const setup: (state: IState, props?: {}) => ShallowWrapper<any, Readonly<{}>, React.Component<{}, {}, any>>
Expected 1-2 arguments, but got 0.ts(2554)
App.test.tsx(15, 16): An argument for 'state' was not provided.
Peek Problem
No quick fixes available

How can I fix this typescript error

App.tsx

import React, {Component} from 'react';
import './App.css';

interface IState{
  counter: number
}

interface IProps{

}

class App extends Component<IState, {}> {

  state = {
    counter: 0
  }

  render(){
    return (
      <div data-test='componentApp'>
        <h1 data-test='counter'>The counter is {this.state.counter}</h1>
        <button 
          data-test='button' 
          onClick={() => this.setState({counter: this.state.counter + 1})
          }>Increment Counter</button>
      </div>
    )
  }
}

export default App;

App.text.tsx

import React from 'react';
import App from './App';
import "./setupTests"
import { shallow } from "enzyme";

interface ITest{
  warpper: String,
  val: String
}

interface IState{
  counter: number
}

const setup = (state:IState, props={}) => {
  const wrapper =  shallow(<App {...state} {...props}/>)
  if(state) wrapper.setState(state)
  return wrapper
}

const findByTestAttr = (wrapper:any, val:string) => {
  return wrapper.find(`[data-test="${val}"]`);
}

describe('App Component', () => {

  it('renders without crashing', () => {
    const wrapper = setup() //Error here
    const componentApp = findByTestAttr(wrapper, 'componentApp')
    expect(componentApp.length).toBe(1)
  });

  it('renders incerment button', () => {
    const wrapper = setup() //Error here
    const button = findByTestAttr(wrapper, 'button')
    expect(button.length).toBe(1)
  })

  it('renders counter display', () => {
    const wrapper = setup() //Error here
    const counter = findByTestAttr(wrapper, 'counter') 
    expect(counter.length).toBe(1)
  })

  it('counter starts at 0', () => {
    const wrapper = setup(); //Error here
    const initialCounterState = wrapper.state('counter');
    expect(initialCounterState).toBe(0)
  })

  it('clicking button increments counter display', () => {
    const counterHere = 7
    const wrapper = setup(null, {counterHere})
    const button = findByTestAttr(wrapper, 'button');
    button.simulate('click')
    const counter = findByTestAttr(wrapper, 'counter') 
    expect(counter.text()).toContain(counter+1)
  })

})

Solution

  • Well, this error does not derive from TypeScript, you're simply not passing any state in setup. Try instantiating wrapper like const wrapper = setup({counter: 0}). As a side note, I discourage using shallow as it exposes the components' internals (which you are leveraging by calling the setState), it's a nasty con of using that for rendering. Instead, try using mount.