Search code examples
typescriptunit-testingjasmine

How to get jasmine tests to ignore tabs in multiline string


I have a function that returns a multiline string like so:

example line 1
example line 2
example line 3

and I'd like to be able to write like so:

it('should get the proper data', () => {
  expect(service.getData('foo').toEqual(
  `example line 1
    example line 2
    example line 3`);
});

but of course that will give me this error since the test adds in some whitespace before most lines:

Expected 'example line 1
example line 2
example line 3' to equal 'example line 1
    example line 2
    example line 3'.

Now I obviously know I could just write my tests slightly differently by adding in \n characters, or just manually removing that whitespace, but that looks a bit uglier in my tests.

I'd love it if there were some kind of utility I could use like this:

it('should get the proper data', () => {
  expect(service.getData('foo').toEqual(
  util.safeUnindent(`example line 1
    example line 2
    example line 3`));
});

Is there some kind of add on I can use that will strip out indentations like this in a safe & reliable way, do I just need to roll my own, or should I just use \n characters?


Solution

  • It looks like you have to roll a little of your own (I have not found any out of the box solution).

    But a couple of things comes quickly to mind, where the custom matcher is the most elegant, I find.

    1. Using toContain to check that expected content is in the returned string
    2. Using toMatch - to check using regular expresion (RegEx)
    3. Using custom matchers - very reusable and easy to read

    See https://jasmine.github.io/api/edge/matchers, https://jasmine.github.io/tutorials/custom_matcher and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions

    Function to test:

    function getData(x){
        return `
        example line 1
        example line 2
        example line 3
        `
    }
    

    Test setup:

    function trimmedLines(untrimmed){
        // trim leading and trailing spaces and newlines and split at inner newlines
        const lines = untrimmed.trim().replace(/^\n+/, '').replace(/\n+$/, '').split('\n')
        const trimmedLines = []
        lines.forEach(line => {
            // trim and add each line to new array
            trimmedLines.push(line.trim())
        });
        // return a trimmed string
        return trimmedLines.join('\n')
    }
    
    const customMatchers = {
        ToEqualTrimmed: function(matchersUtil) {
            return {
                compare: function(actual, expected) {
                    if (expected === undefined) expected = '';
                    const result = { };
                    result.pass = matchersUtil.equals(
                        trimmedLines(actual),
                        trimmedLines(expected)
                    )
    
                    if (result.pass) {
                        result.message = "Expected " + actual + " to be trimmed equal to" + expected;
                    } else {
                        result.message = "Expected " + actual + " to be trimmed equal to" + expected + ' But was not!';
                    }
                    return result;
                }
            };
        }
    };
    
    beforeEach(function() {
        jasmine.addMatchers(customMatchers);
    });
    
    describe("Outer test desc", () => {
        it('should get the proper data', () => {
            const output = getData('foo')
            // this fails
            expect(output).toEqual(
              `example line 1
                example line 2
                example line 3`);
            // these 3 pass
            expect(output).toContain('example line 1')
            expect(output).toContain('example line 2')
            expect(output).toContain('example line 3')
            // this passes too
            expect(output).toMatch('[ \n]*example line 1[ \n]*example line 2[ \n]*example line 3[ \n]*');
            // passes too
            expect(output).ToEqualTrimmed(
              `example line 1
                example line 2
                example line 3`);
    
    
        });
    
    });
    

    The [ \n]* matches zero or more spaces or newlines.