Jest Equality Matcher For Strings That Disregards Whitespace

14,429

Solution 1

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.

Solution 2

As far as I know, there is no way to achieve this with Jest out of the box.

However, it is pretty straightforward to write your own reusable matcher using expect.extend. Remove all whitespace from both strings, e.g. via str.replace(/\s/g, ''), and compare the strings.

Share:
14,429

Related videos on Youtube

Undistraction
Author by

Undistraction

Updated on September 28, 2022

Comments

  • Undistraction
    Undistraction over 1 year

    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.

  • Chance Strickland
    Chance Strickland over 5 years
    This was super helpful -- only suggested change: const replaceWhitespace = (str) => str.replace(/\s+/g, ' ').trim() to account for whitespace at the beginning/end of the strings.
  • dwjohnston
    dwjohnston about 3 years
    Fantastic. I've updated your answer with most recent standard practises.
  • jsonp
    jsonp about 3 years
    Using the ramda library is "standard practice"?
  • Tr1stan
    Tr1stan about 2 years
    Ramda has been a dependency of this snippet since the initial version.