Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save phatnguyenuit/93bd9aa506bbe06ddaeea166d2f010db to your computer and use it in GitHub Desktop.
Save phatnguyenuit/93bd9aa506bbe06ddaeea166d2f010db to your computer and use it in GitHub Desktop.
Prevent code duplication when writing unit tests with Jest .each

Prevent code duplication when writing unit tests with Jest .each

Today I am going to show you how to prevent code duplication when writing unit tests with Jest .each.

Let's get started!

Prevent code duplication when writing unit tests with Jest .each


Table of contents

Prerequisites

Problem definition

Given a string transformer function to convert a string to a kebab cased one

https://gist.github.com/phatnguyenuit/5ada24a985010faae611357b96bc4af8

const createTransform = (
  pattern: string | RegExp,
  separator: string,
  wordTransformer: (word: string) => string,
) => (text: string) => text.split(pattern).map(wordTransformer).join(separator);

const exhaustedPattern = /[\s_-]|(?=[A-Z0-9])/;

export const toKebabCase = createTransform(exhaustedPattern, '-', (word) =>
  word.toLowerCase(),
);

// "my_example" => "this-is-my-example"
// "anotherExample123" => "another-example-1-2-3"

And how your test cases are organized

https://gist.github.com/phatnguyenuit/b5eecb0e1d0dff158600134d29aa3ab8

import { toKebabCase } from './utils';

describe('toKebabCase', () => {
  it('should work from empty string', () => {
    expect(toKebabCase('')).toEqual('');
  });

  it('should return "my-example" when given "my_example"', () => {
    expect(toKebabCase('my_example')).toEqual('my-example');
  });

  it('should return "another-example" when given "Another-Example"', () => {
    expect(toKebabCase('Another-Example')).toEqual('another-example');
  });

  it('should return "another-example" when given "anotherExample"', () => {
    expect(toKebabCase('anotherExample')).toEqual('another-example');
  });

  it('should return "another-example-1-2-3" when given "anotherExample123"', () => {
    expect(toKebabCase('anotherExample123')).toEqual('another-example-1-2-3');
  });
});

So you can see there are 5 test cases for toKebabCase utilities. Is there any way to make it better ? shorter ? and easier to maintain ?

YES, you can refactor the above test cases by using Jest it.each

it is an alias for test. So do not get confused when sometimes you see test instead of it. Refer to this. I prefer using it more than test because of the shortest name

Go back ⏪

Practices

Introduction

it.each signature

// it.each`table`(name, fn, timeout)

it.each`
  var1 | var2 | expectedResult
  ${1} | ${2} | ${3}
  ${2} | ${3} | ${5}
`('should work', ({ var1, var2, expectedResult }) => {
  expect(yourFn(var1, var2)).toEqual(expectedResult);
});

The table here is tagged literal string in JavaScript. Why does it call table ?

Because we organize our test cases like a table.

var1 var2 expectedResult
1 2 3
2 3 5
  • The 1st row contains variable name columns separated by |
  • From the 2nd row, each row contains variable value columns we pass to the test case as template literal expression ${value}, separated by | also.

Go back ⏪

Coding time

Okay for now, you can refactor the above test cases to reduce code duplication.

https://gist.github.com/phatnguyenuit/851c2742294dee460fb38056caa0da23

import { toKebabCase } from './utils';

describe('toKebabCase', () => {
  it.each`
    text                   | expectedResult
    ${''}                  | ${''}
    ${'my_example'}        | ${'my-example'}
    ${'Another-Example'}   | ${'another-example'}
    ${'anotherExample'}    | ${'another-example'}
    ${'anotherExample123'} | ${'another-example-1-2-3'}
  `(
    'should return "$expectedResult" when given "$text"',
    ({ text, expectedResult }) => {
      expect(toKebabCase(text)).toEqual(expectedResult);
    },
  );
});

Wow, do you surprise that our test cases shorter, easier to understand and maintain

Wait, wait. Does it work ? Yes, absolutely YES ✔.

it.each test case result

All test cases are passed now. You can see the GREEN ✅color (passed test cases), it can make your happy day at work 😁. Avoid the RED ❌ one (failed test cases) as little as possible if you want to get a long day 😂🤣

You might wonder if the describe.each exists?

✅YES, there is describe.each supported by Jest.

For describe.each, it's similar to it.each but for grouping test cases into collections.

You can explore more by going through the references section.

Go back ⏪

Conclusion

It is very cool to use it.each from Jest to make your test cases maintainable, avoid duplication.

Thank you for reading my article! I hope it is helpful for you. If you have any concerns or questions, do not hesitate to leave a comment below.

See you in the next article!

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment