From 8e85f3df741a3fc7bbedfc25bc68a64a3d727f54 Mon Sep 17 00:00:00 2001 From: Nito Buendia Date: Wed, 16 Feb 2022 21:10:31 +0800 Subject: [PATCH] Create toHaveSpyInteractions matcher This matcher checks all the properties of a given spy object and checks whether at least one of the spies has been called. It returns true if one or more of the spies of the spy object has been called and false otherwise. --- src/core/matchers/requireMatchers.js | 1 + src/core/matchers/toHaveSpyInteractions.js | 73 ++++++++++++++++++++++ 2 files changed, 74 insertions(+) mode change 100644 => 100755 src/core/matchers/requireMatchers.js create mode 100755 src/core/matchers/toHaveSpyInteractions.js diff --git a/src/core/matchers/requireMatchers.js b/src/core/matchers/requireMatchers.js old mode 100644 new mode 100755 index c14ceac9..3c9d6983 --- a/src/core/matchers/requireMatchers.js +++ b/src/core/matchers/requireMatchers.js @@ -27,6 +27,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) { 'toHaveBeenCalledTimes', 'toHaveBeenCalledWith', 'toHaveClass', + 'toHaveSpyInteractions', 'toMatch', 'toThrow', 'toThrowError', diff --git a/src/core/matchers/toHaveSpyInteractions.js b/src/core/matchers/toHaveSpyInteractions.js new file mode 100755 index 00000000..d9c3c72e --- /dev/null +++ b/src/core/matchers/toHaveSpyInteractions.js @@ -0,0 +1,73 @@ +getJasmineRequireObj().toHaveSpyInteractions = function(j$) { + var getErrorMsg = j$.formatErrorMsg( + '', + 'expect().toHaveSpyInteractions()' + ); + + /** + * {@link expect} the actual (a {@link SpyObj}) spies to have been called. + * @function + * @name matchers#toHaveSpyInteractions + * @since 4.0.0 + * @example + * expect(mySpyObj).toHaveSpyInteractions(); + * expect(mySpyObj).not.toHaveSpyInteractions(); + */ + function toHaveSpyInteractions(matchersUtil) { + return { + compare: function(actual) { + var result = {}; + + if (!j$.isObject_(actual)) { + throw new Error( + getErrorMsg( + 'Expected a spy object, but got ' + matchersUtil.pp(actual) + '.' + ) + ); + } + + if (arguments.length > 1) { + throw new Error(getErrorMsg('Does not take arguments')); + } + + result.pass = false; + let hasSpy = false; + const calledSpies = []; + for (const spy of Object.values(actual)) { + if (!j$.isSpy(spy)) continue; + hasSpy = true; + + if (spy.calls.any()) { + result.pass = true; + calledSpies.push([spy.and.identity, spy.calls.count()]); + } + } + + if (!hasSpy) { + throw new Error( + getErrorMsg( + 'Expected a spy object with spies, but object has no spies.' + ) + ); + } + + let resultMessage = 'Expected spy object spies to have been called'; + if (result.pass) { + resultMessage += ', the following spies were called: '; + resultMessage += calledSpies + .map(([spyName, spyCount]) => { + return `${spyName} called ${spyCount} time(s)`; + }) + .join(', '); + } else { + resultMessage += ', but no spies were called.'; + } + result.message = resultMessage; + + return result; + } + }; + } + + return toHaveSpyInteractions; +};