UNPKG

backbone.select

Version:

Selecting Backbone models; handling selections in Backbone collections.

355 lines (288 loc) 14.5 kB
/** * More custom matchers for Jasmine. */ /** * Returns a definition of internal Backbone.Select events. * * @type {string[]} */ jasmine.getInternalBackboneSelectEvents = function () { return ["@bbs:_selected", "@bbs:_deselected"]; }; if ( ! jasmine._addTheseCustomMatchers ) jasmine._addTheseCustomMatchers = {}; /** * @name jasmine.Matchers#toHaveBeenCalledWithInitial * @function * @param {...*} initialCallArguments * @returns {boolean} */ /** * Matcher that checks to see if the actual, a Jasmine spy, was called with parameters beginning with a specific set. * * @example * * spyOn(obj, "foo"); * obj.foo(1, 2, 3); * expect(obj.foo).toHaveBeenCalledWithInitial(1, 2); // => true */ jasmine._addTheseCustomMatchers.toHaveBeenCalledWithInitial = function ( util, customEqualityTesters ) { return { compare: function ( actual, expected ) { var result = {}, expectedArgs = jasmine.util.argsToArray( arguments ).slice( 1 ); if ( !jasmine.isSpy( actual ) ) { throw new Error( 'Expected a spy, but got ' + jasmine.pp( actual ) + '.' ); } var actualInitial = _.map( actual.calls.allArgs(), function ( args ) { return args.slice( 0, expectedArgs.length ); } ); result.pass = util.contains( actualInitial, expectedArgs, customEqualityTesters ); if ( result.pass ) { result.message = "Expected spy " + actual.and.identity() + " not to have been called with initial arguments " + jasmine.pp( expectedArgs ) + " but it was."; } else { result.message = !actual.calls.any() ? "Expected spy " + actual.and.identity() + " to have been called with initial arguments " + jasmine.pp( expectedArgs ) + " but it was never called." : "Expected spy " + actual.and.identity() + " to have been called with initial arguments " + jasmine.pp( expectedArgs ) + " but actual calls were " + jasmine.pp( actual.calls.allArgs() ).replace( /^\[ | \]$/g, '' ) + '.'; } return result; } }; }; /** * @name jasmine.Matchers#toHaveBeenCalled_ignoringInternalEvents * @function * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone.Select. * * Checks if the `actual`, a Jasmine spy, was called. **Is meant to be used for spies on `trigger` only**, which * receive the name of the triggered event as first argument. * * The check excludes calls which pass the name of an internal Backbone.Select event as first argument. Otherwise, * functionally identical to Jasmine's `.toHaveBeenCalled()` matcher. */ jasmine._addTheseCustomMatchers.toHaveBeenCalled_ignoringInternalEvents = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getIgnoredEvents: function () { return jasmine.getInternalBackboneSelectEvents(); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount > 0; }, msgAction: "to have been called (not counting internal events)", showActualWhenNegated: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalled_ignoringInternalEventsAnd * @function * @param {...(string|string[])} ignoredEvents a sequence of string arguments, or a single array, or a combination of both * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone.Select. Just like * toHaveBeenCalled_ignoringInternalEvents, but allows to add other event names to be ignored. */ jasmine._addTheseCustomMatchers.toHaveBeenCalled_ignoringInternalEventsAnd = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getIgnoredEvents: function () { return jasmine.getInternalBackboneSelectEvents().concat( jasmine.util.argsToArray( arguments ).slice( 1 ) ); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount > 0; }, msgAction: "to have been called (not counting internal and ignored events)", showActualWhenNegated: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalledOnce_ignoringInternalEvents * @function * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone.Select. Just like * toHaveBeenCalled_ignoringInternalEvents, but tests for exactly one call. */ jasmine._addTheseCustomMatchers.toHaveBeenCalledOnce_ignoringInternalEvents = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getIgnoredEvents: function () { return jasmine.getInternalBackboneSelectEvents(); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount === 1; }, msgAction: "to have been called once (not counting internal events)", showActual: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalledTwice_ignoringInternalEvents * @function * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone.Select. Just like * toHaveBeenCalled_ignoringInternalEvents, but tests for exactly two calls. */ jasmine._addTheseCustomMatchers.toHaveBeenCalledTwice_ignoringInternalEvents = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getIgnoredEvents: function () { return jasmine.getInternalBackboneSelectEvents(); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount === 2; }, msgAction: "to have been called twice (not counting internal events)", showActual: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalledOnce_ignoringInternalEventsAnd * @function * @param {...(string|string[])} ignoredEvents a sequence of string arguments, or a single array, or a combination of both * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone.Select. Just like * toHaveBeenCalled_ignoringInternalEventsAnd, but tests for exactly one call. */ jasmine._addTheseCustomMatchers.toHaveBeenCalledOnce_ignoringInternalEventsAnd = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getIgnoredEvents: function () { return jasmine.getInternalBackboneSelectEvents().concat( jasmine.util.argsToArray( arguments ).slice( 1 ) ); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount === 1; }, msgAction: "to have been called once (not counting internal and ignored events)", showActual: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalledTwice_ignoringInternalEventsAnd * @function * @param {...(string|string[])} ignoredEvents a sequence of string arguments, or a single array, or a combination of both * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone.Select. Just like * toHaveBeenCalled_ignoringInternalEventsAnd, but tests for exactly two calls. */ jasmine._addTheseCustomMatchers.toHaveBeenCalledTwice_ignoringInternalEventsAnd = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getIgnoredEvents: function () { return jasmine.getInternalBackboneSelectEvents().concat( jasmine.util.argsToArray( arguments ).slice( 1 ) ); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount === 2; }, msgAction: "to have been called twice (not counting internal and ignored events)", showActual: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalled_ignoringEvents * @function * @param {...(string|string[])} ignoredEvents a sequence of string arguments, or a single array, or a combination of both * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone. Excludes calls for any number of * specified events. Otherwise, functionally identical to Jasmine's `.toHaveBeenCalled()` matcher. * * The names of excluded events can be passed in as a sequence of string arguments, or as a single array, or as a * combination of both. * * Checks if the `actual`, a Jasmine spy, was called. **Is meant to be used for spies on `trigger` only**, which * receive the name of the triggered event as first argument. */ jasmine._addTheseCustomMatchers.toHaveBeenCalled_ignoringEvents = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getIgnoredEvents: function () { return jasmine.util.argsToArray( arguments ).slice( 1 ); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount > 0; }, msgAction: "to have been called (not counting ignored events)", showActualWhenNegated: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalledForEvents * @function * @param {...(string|string[])} exclusiveEvents a sequence of string arguments, or a single array, or a combination of both * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone. Only examines calls for specified events. * Otherwise, functionally identical to Jasmine's `.toHaveBeenCalled()` matcher. * * The names of the exclusive events can be passed in as a sequence of string arguments, or as a single array, or as a * combination of both. * * Checks if the `actual`, a Jasmine spy, was called. **Is meant to be used for spies on `trigger` only**, which * receive the name of the triggered event as first argument. */ jasmine._addTheseCustomMatchers.toHaveBeenCalledForEvents = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getExclusiveEvents: function () { return jasmine.util.argsToArray( arguments ).slice( 1 ); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount > 0; }, msgAction: "to have been called (only counting the specified events)", showActualWhenNegated: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalledOnceForEvents * @function * @param {...(string|string[])} exclusiveEvents a sequence of string arguments, or a single array, or a combination of both * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone. Just like toHaveBeenCalledForEvents, but * tests for exactly one call. */ jasmine._addTheseCustomMatchers.toHaveBeenCalledOnceForEvents = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getExclusiveEvents: function () { return jasmine.util.argsToArray( arguments ).slice( 1 ); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount === 1; }, msgAction: "to have been called once (only counting the specified events)", showActual: true } ); }; /** * @name jasmine.Matchers#toHaveBeenCalledTwiceForEvents * @function * @param {...(string|string[])} exclusiveEvents a sequence of string arguments, or a single array, or a combination of both * @returns {boolean} */ /** * Matcher specifically for `trigger` event spies, in the context of Backbone. Just like toHaveBeenCalledForEvents, but * tests for exactly two calls. */ jasmine._addTheseCustomMatchers.toHaveBeenCalledTwiceForEvents = function ( util, customEqualityTesters ) { return customToHaveBeenCalled( { getExclusiveEvents: function () { return jasmine.util.argsToArray( arguments ).slice( 1 ); }, checkFilteredCallCount: function ( filteredCallCount ) { return filteredCallCount === 2; }, msgAction: "to have been called twice (only counting the specified events)", showActual: true } ); }; /** * @param {Object} config * @param {function} config.checkFilteredCallCount * @param {string} config.msgAction * @param {boolean} [config.showActual=false] * @param {boolean} [config.showActualWhenNegated=false] * @param {function} [config.getIgnoredEvents] * @param {function} [config.getExclusiveEvents] * @returns {Object} */ function customToHaveBeenCalled ( config ) { return { compare: function ( actual ) { var callCount, msgActualCalls, ignoredEvents = config.getIgnoredEvents && config.getIgnoredEvents.apply( null, arguments ) || [], exclusiveEvents = config.getExclusiveEvents && config.getExclusiveEvents.apply( null, arguments ) || [], detectedEventNames = [], result = {}; // if ( !_.isArray( ignoredEvents.length ) throw new Error( "The names of ignored events have not been passed in. Please specify the event names." ); if ( !jasmine.isSpy( actual ) ) throw new Error( 'Expected a spy, but got ' + jasmine.pp( actual ) + '.' ); ignoredEvents = _.flatten( ignoredEvents ); exclusiveEvents = _.flatten( exclusiveEvents ); callCount = _.reduce( actual.calls.allArgs(), function ( callCount, args ) { var eventName = args[0]; if ( !_.contains( ignoredEvents, eventName ) && ( !exclusiveEvents.length || _.contains( exclusiveEvents, eventName ) ) ) { callCount++; detectedEventNames.push( eventName ); } return callCount; }, 0 ); result.pass = config.checkFilteredCallCount( callCount ); msgActualCalls = callCount === 0 ? "it was not called." : "it was called " + callCount + ( callCount === 1 ? " time." : " times." ) + "\n" + ( callCount === 1 ? "The event name has been: " : "The event names have been: " ) + '"' + detectedEventNames.join( '", "' ) + '"'; if ( result.pass ) { result.message = "Expected spy " + actual.and.identity() + " not " + config.msgAction + ", but " + ( config.showActualWhenNegated ? msgActualCalls : "it was." ); } else { result.message = "Expected spy " + actual.and.identity() + " " + config.msgAction + ", but " + ( config.showActual ? msgActualCalls : "it wasn't." ); } return result; } }; }