DEV Community

Cover image for Sit down at my Jest Tagged Template Literal table and tidy up your tests.
Andy Coupe
Andy Coupe

Posted on

2

Sit down at my Jest Tagged Template Literal table and tidy up your tests.

Scenario

We have a really simple button component which receives a status on the props object and renders different button text based on the value of the status.

This simple component will be called LouisButton. The value of the status prop will be one of four values which can be seen in the code below.

const buttonTextMapper = {
  available: 'Buy now',
  unavailable: 'Unavailable',
  reserved: 'This product is reserved',
  outOfStock: 'Out of stock',
}

type ButtonProps = {
  status: 'available' | 'unavailable' | 'reserved' | 'outOfStock'
}

export const LouisButton: React.FC<ButtonProps> = ({ status }) => {
  const buttonText = buttonTextMapper[status]

  return (
    <button>{buttonText}</button>
  )
}
Enter fullscreen mode Exit fullscreen mode

Now let's write some tests for LouisButton using Jest and React Testing Library.

import { render } from '@testing-library/react'
import { LouisButton } from './button'

describe('LouisButton', () => {
  it('should render "Buy now" if the status is available', () => {
    const {getByText} = render(<LouisButton status={'available'}/>)

    expect(getByText('Buy now')).toBeInTheDocument()
  })

  it('should render "Unavailable" if the status is unavailable', () => {
    const {getByText} = render(<LouisButton status={'unavailable'}/>)

    expect(getByText('Unavailable')).toBeInTheDocument()
  })

  it('should render "This product is reserved" if the status is reserved', () => {
    const {getByText} = render(<LouisButton status={'reserved'}/>)

    expect(getByText('This product is reserved')).toBeInTheDocument()
  })

  it('should render "Out of stock" if the status is outOfStock', () => {
    const {getByText} = render(<LouisButton status={'outOfStock'}/>)

    expect(getByText('Out of stock')).toBeInTheDocument()
  })
})
Enter fullscreen mode Exit fullscreen mode

Remember, this is a simple button. But if more statuses were to be added, things could get ugly. We can improve this and make things easier to digest for the next developer who comes working in this area.

Say hello to it.each πŸ‘‹

 it.each`
      status           | buttonText
      ${'available'}   | ${'Buy now'}
      ${'unavailable'} | ${'Unavailable'}
      ${'reserved'}    | ${'This product is reserved'}
      ${'outOfStock'}  | ${'Out of stock'}
  `('should render $buttonText if the status is $status', ({buttonText, status}) => {
    const {getByText} = render(<LouisButton status={status}/>)

    expect(getByText(buttonText)).toBeInTheDocument()
  })
Enter fullscreen mode Exit fullscreen mode

Jest will run a test across each row in the tagged template literal table, mapping the title of each column to a variable which you can see in the test description, preceded by a dollar sign. This helps make your test descriptions read nicely.

Nice test descriptions

We can then destructure these variables and use them in our assertions. I think this pattern is much more maintainable than continuously adding more it blocks.

If another set of statuses are introduced then it's no big deal. Just add them to the table πŸ˜€

Thanks for reading πŸ‘

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (2)

Collapse
 
coding_tom profile image
Tom Cafferkey β€’

Thanks Andrew!

Collapse
 
dmitriialekseevfs profile image

Can we keep this Template Literal table outside in some variable const temLit=...``?

Sentry image

See why 4M developers consider Sentry, β€œnot bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay