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?
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.
toContain
to check that expected content is in the returned stringtoMatch
- to check using regular expresion (RegEx)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.