Jest Equality Matcher For Strings That Disregards Whitespace

Undistraction picture Undistraction · Jan 25, 2018 · Viewed 9.8k times · Source

Jest's toEqual matcher takes whitespace into account when checking for equality. When formatting the expected value in tests it is impossible to do so in a way that matches a string containing newlines, tabs etc.

Does Jest offer a way to disregard whitespace when matching?

Note: I edited the question to make it more generic.

Answer

Undistraction picture Undistraction · Jan 26, 2018

As @Timo says, the only way of doing this appears to be with a custom matcher. Here is one that compresses all whitespace down to a single space for readability based on Jest's toEqual matcher. It will deal with tabs, newlines etc. It will give you pretty output like the included Jest matchers:

//matchStringIgnoringWhiteSpace.js

import { replace, map, equals } from 'ramda';
import { matcherHint, printReceived, printExpected } from 'jest-matcher-utils';
import diff from 'jest-diff';

const replaceWhitespace = replace(/\s+/g, ` `);
const compressWhitespace = map(replaceWhitespace);

const name = `toEqualWithCompressedWhitespace`;

export default function (received, expected) {
  const [
    receivedWithCompresssedWhitespace,
    expectedWithCompresssedWhitespace,
  ] = compressWhitespace([received, expected]);
  const pass = equals(
    receivedWithCompresssedWhitespace,
    expectedWithCompresssedWhitespace
  );
  const message = pass
    ? () =>
        `${matcherHint(`.not.${name}`)}\n\n` +
        `Uncompressed expected value:\n` +
        `  ${printExpected(expected)}\n` +
        `Expected value with compressed whitespace to not equal:\n` +
        `  ${printExpected(expectedWithCompresssedWhitespace)}\n` +
        `Uncompressed received value:\n` +
        `  ${printReceived(received)}\n` +
        `Received value with compressed whitespace:\n` +
        `  ${printReceived(receivedWithCompresssedWhitespace)}`
    : () => {
        const diffString = diff(
          expectedWithCompresssedWhitespace,
          receivedWithCompresssedWhitespace,
          {
            expand: this.expand,
          }
        );
        return (
          `${matcherHint(`.${name}`)}\n\n` +
          `Uncompressed expected value:\n` +
          `  ${printExpected(expected)}\n` +
          `Expected value with compressed whitespace to equal:\n` +
          `  ${printExpected(expectedWithCompresssedWhitespace)}\n` +
          `Uncompressed received value:\n` +
          `  ${printReceived(received)}\n` +
          `Received value with compressed whitespace:\n` +
          `  ${printReceived(receivedWithCompresssedWhitespace)}${
            diffString ? `\n\nDifference:\n\n${diffString}` : ``
          }`
        );
      };
  return {
    actual: received,
    expected,
    message,
    name,
    pass,
  };
};

To register the custom matcher you need to add it to your setupTests files. First register setupTests in your jest.config.js using the setupFilesAfterEnv field:

 setupFilesAfterEnv: `<rootDir>/path/to/setupTests.js`,

And then register the custom matcher on the expect object.

//setupTests.js

import toMatchStringIgnoringWhitespace from "<rootDir>/path/to/matchStringIgnoringWhiteSpace";

expect.extend({
    toMatchStringIgnoringWhitespace: toMatchStringIgnoringWhitespace
}); 

If you are using TypeScript you will also want to add the typings to the expect object following the instructions here.