I'm refactoring a TypeScript method to add an optional parameter with a default value. The refactored method is a core operation, and there are many high-level operations that call the core function. The pre-existing calls omit the new parameter (thus using the default value), while new and refactored methods supply the new parameter value. A simplified version looks like this:
export class Scratch {
coreOperation(mainArg: string, option: boolean = false) {
// ...
}
private midLevelOperation(mainArg: string) {
this.coreOperation(mainArg + '1');
}
highLevelOperation1(mainArg: string) {
this.midLevelOperation(mainArg);
this.coreOperation(mainArg + '2', true);
}
}
I'm also updating the Jasmine tests of the higher-level operations. I want to assert that the high-level operations cause the core operation to be called with certain parameters. Tests would look roughly like this:
describe('Scratch', () => {
let objectUnderTest: Scratch;
beforeEach(() => {
objectUnderTest = new Scratch();
spyOn(objectUnderTest, 'coreOperation');
});
describe('highLevelOperation1', () => {
it('should call core operation', () => {
objectUnderTest.highLevelOperation1('main');
expect(objectUnderTest.coreOperation).toHaveBeenCalledWith('main1', false);
expect(objectUnderTest.coreOperation).toHaveBeenCalledWith('main2', true);
});
});
});
The problem is that Jasmine's toHaveBeenCalledWith doesn't know that the second argument has a default value. The error for the above code:
- Expected spy coreOperation to have been called with:
[ 'main1', false ]
but actual calls were:
[ 'main1' ],
[ 'main2', true ].
Obviously I can get the test to pass by removing the the false argument from my test. But I don't want the tests to know whether call sites use 1 argument or 2, especially from private library functions like this example.
Is there a way to write a Jasmine matcher that works both when an optional parameter is omitted and when the default value is passed?