diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 0000000..2bbe962 --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,576 @@ +## Classes + +
+
Action
+

Class specifying action to be executed on mocked function calls.

+
+
Cardinality
+

Describes number of expected function calls.

+
+
Expectation
+

Class specifying function call expectation. +Each expectation contains a matcher, +cardinality and a list of +actions to be executed.

+
+
InvokerAction
+

Specialization of an Action invoking a provided callback +argument. This implementation assumes that callback is +provided as the last argument on the list.

+
+
Matcher
+

Validates provided list of arguments.

+
+
WeakMatcherMatcher
+

Specialization of Matcher for weak argument list comparison.

+
+
Mock
+

Mock class for wrapping test subject dependencies.

+
+
+ + + +## Action +Class specifying action to be executed on mocked function calls. + +**Kind**: global class + +* [Action](#Action) + * [new Action(action, counter)](#new_Action_new) + * [.validate()](#Action+validate) ⇒ Boolean + * [.available()](#Action+available) ⇒ Boolean + * [.execute(args)](#Action+execute) ⇒ \* + + + +### new Action(action, counter) +**Throws**: + +- TypeErrpr TypeError is thrown if specified number is defined and its type is not a Number. +- Error Error is thrown if provided counter value is 0. This value is reserved +and can't be used for initializing actions. + + +| Param | Type | Description | +| --- | --- | --- | +| action | Any | If provided action is a function it will be executed with arguments provided to execute method. Parameter of any other type will produce action returning it upon execution. | +| counter | Number | Expected number of action execution times. Negative value will create action that can be executed any number of times. | + + + +### action.validate() ⇒ Boolean +Determines if action has been executed expected number of times. + +**Kind**: instance method of [Action](#Action) + + +### action.available() ⇒ Boolean +Determines if action can be executed. + +**Kind**: instance method of [Action](#Action) +**Returns**: Boolean - Returns true if action can be executed, false otherwise. + + +### action.execute(args) ⇒ \* +Executes current action with provided arguments array. + +**Kind**: instance method of [Action](#Action) +**Returns**: \* - Propagates return value of internal action. +**Throws**: + +- Error Throws error if current action was already executed specified +number of times. + + +| Param | Type | Description | +| --- | --- | --- | +| args | Array | Array of arguments to be passed to the action function. | + + + +## Cardinality +Describes number of expected function calls. + +**Kind**: global class + +* [Cardinality](#Cardinality) + * [new Cardinality(min, max)](#new_Cardinality_new) + * [.set(min, max)](#Cardinality+set) + * [.unbound()](#Cardinality+unbound) + * [.bump(count)](#Cardinality+bump) + * [.available()](#Cardinality+available) ⇒ Boolean + * [.use()](#Cardinality+use) ⇒ Boolean + * [.validate()](#Cardinality+validate) ⇒ Boolean + + + +### new Cardinality(min, max) + +| Param | Type | Description | +| --- | --- | --- | +| min | Number | Minimum number of expected calls. | +| max | Number | Maximum number of expected calls. | + + + +### cardinality.set(min, max) +Sets new values of minimum and maximum expected calls. + +**Kind**: instance method of [Cardinality](#Cardinality) +**Throws**: + +- TypeError Throws TypeError if min or max parameter is not a valid number. +- Error Error is thrown if given minimum expected calls value is negative, +or if given maximum expected calls value is positive lower than min. + + +| Param | Type | Description | +| --- | --- | --- | +| min | Number | Minimum number of expected calls. | +| max | Number | Maximum number of expected calls. | + + + +### cardinality.unbound() +Removes upper bound from cardinality. + +**Kind**: instance method of [Cardinality](#Cardinality) + + +### cardinality.bump(count) +Shifts the cardinality by a given number of expected calls. + +**Kind**: instance method of [Cardinality](#Cardinality) +**Throws**: + +- TypeError Throws TypeError if count parameter is not a valid number. +- Error Error is thrown if given count is lower or equal to 0. + + +| Param | Type | Description | +| --- | --- | --- | +| count | Number | Number of additional expected calls. | + + + +### cardinality.available() ⇒ Boolean +Checks if cardinality allows for more calls. + +**Kind**: instance method of [Cardinality](#Cardinality) +**Returns**: Boolean - True if cardinality allows at least one more call, +false otherwise. + + +### cardinality.use() ⇒ Boolean +Uses one call from cardinality. + +**Kind**: instance method of [Cardinality](#Cardinality) +**Returns**: Boolean - True if call didn't cause exceeding cardinality upper +bound, false otherwise. + + +### cardinality.validate() ⇒ Boolean +Validates that cardinality was used expected number of times. + +**Kind**: instance method of [Cardinality](#Cardinality) +**Returns**: Boolean - True if number of calls lies in defined range, false otherwise. + + +## Expectation +Class specifying function call expectation. +Each expectation contains a [matcher](#Matcher), +[cardinality](#Cardinality) and a list of +[actions](#Action) to be executed. + +**Kind**: global class + +* [Expectation](#Expectation) + * [new Expectation(args)](#new_Expectation_new) + * [.isMatching(args)](#Expectation+isMatching) ⇒ Boolean + * [.isSaturated()](#Expectation+isSaturated) ⇒ Boolean + * [.validate()](#Expectation+validate) ⇒ Boolean + * [.times(count)](#Expectation+times) + * [.atLeast(count)](#Expectation+atLeast) + * [.atMost(count)](#Expectation+atMost) + * [.between(min, max)](#Expectation+between) + * [.matching()](#Expectation+matching) ⇒ [Expectation](#Expectation) + * [.with()](#Expectation+with) + * [.matchingAtLeast()](#Expectation+matchingAtLeast) ⇒ [Expectation](#Expectation) + * [.withAtLeast()](#Expectation+withAtLeast) + * [.willOnce(action)](#Expectation+willOnce) ⇒ [Expectation](#Expectation) + * [.willTwice(action)](#Expectation+willTwice) ⇒ [Expectation](#Expectation) + * [.willRepeatedly(action)](#Expectation+willRepeatedly) + * [.willOnceInvoke()](#Expectation+willOnceInvoke) ⇒ [Expectation](#Expectation) + * [.willTwiceInvoke()](#Expectation+willTwiceInvoke) ⇒ [Expectation](#Expectation) + * [.willRepeatedlyInvoke()](#Expectation+willRepeatedlyInvoke) + * [.execute(args)](#Expectation+execute) ⇒ \* + + + +### new Expectation(args) + +| Param | Type | Description | +| --- | --- | --- | +| args | Array | Array of arguments to be used for creation of matcher object | + + + +### expectation.isMatching(args) ⇒ Boolean +Checks if given argument list fits the expectation matcher. + +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: Boolean - Returns result of applying provided arguments to matcher function. + +| Param | Type | Description | +| --- | --- | --- | +| args | Array | Array of arguments to be validated | + + + +### expectation.isSaturated() ⇒ Boolean +Determines if expectation has been already executed maximum +expected number of times. + +**Kind**: instance method of [Expectation](#Expectation) + + +### expectation.validate() ⇒ Boolean +Validates the expectation. + +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: Boolean - Returns true if expectation cardinality is fulfilled, false otherwise. + + +### expectation.times(count) +Specifies expectation cardinality to given number of expected calls. + +**Kind**: instance method of [Expectation](#Expectation) + +| Param | Type | Description | +| --- | --- | --- | +| count | Number | Expected number of calls | + + + +### expectation.atLeast(count) +Specifies number of expectation matching calls to be equal or greater +of given number. + +**Kind**: instance method of [Expectation](#Expectation) + +| Param | Type | Description | +| --- | --- | --- | +| count | Number | Minimal number of expected matching calls. | + + + +### expectation.atMost(count) +Specifies number of expectation matching calls to be at least 1, +but not greater than given number. + +**Kind**: instance method of [Expectation](#Expectation) + +| Param | Type | Description | +| --- | --- | --- | +| count | Number | Maximal number of expected matching calls. | + + + +### expectation.between(min, max) +Specifies number of expectation matching calls to lie in given range. + +**Kind**: instance method of [Expectation](#Expectation) + +| Param | Type | Description | +| --- | --- | --- | +| min | Number | Minimal number of expected matching calls. | +| max | Number | Maximal number of expected matching calls. | + + + +### expectation.matching() ⇒ [Expectation](#Expectation) +Creates expectation matcher from provided arguments. + +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: [Expectation](#Expectation) - Returns current instance of the expectation for chaining. + + +### expectation.with() +Alias of matching method + +**Kind**: instance method of [Expectation](#Expectation) + + +### expectation.matchingAtLeast() ⇒ [Expectation](#Expectation) +Creates weak expectation matcher from given arguments. Weak matcher +will yield match if at least n first specified arguments match. Actual +call can contain more arguments. + +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: [Expectation](#Expectation) - Returns current instance of the expectation for chaining. + + +### expectation.withAtLeast() +Alias of matchingAtLeast + +**Kind**: instance method of [Expectation](#Expectation) + + +### expectation.willOnce(action) ⇒ [Expectation](#Expectation) +Adds a new action from provided arguments and adds it to +expectation action list. Newly created Action has expected +execution count set to 1. + +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: [Expectation](#Expectation) - Returns current instance of the expectation for chaining. + +| Param | Type | Description | +| --- | --- | --- | +| action | \* | Parameter passed for Action constructor | + + + +### expectation.willTwice(action) ⇒ [Expectation](#Expectation) +Adds a new action from provided arguments and adds it to +expectation action list. Newly created Action has expected +execution count set to 2. + +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: [Expectation](#Expectation) - Returns current instance of the expectation for chaining. + +| Param | Type | Description | +| --- | --- | --- | +| action | \* | Parameter passed for Action constructor | + + + +### expectation.willRepeatedly(action) +Adds a new action from provided arguments and adds it to +expectation action list. Newly created Action has unbounded +execution count. + +**Kind**: instance method of [Expectation](#Expectation) + +| Param | Type | Description | +| --- | --- | --- | +| action | \* | Parameter passed for Action constructor | + + + +### expectation.willOnceInvoke() ⇒ [Expectation](#Expectation) +Adds a new invoker action, that will call callback passed +on execution time with given arguments. Newly created Invoker +has expected execution count set to 1. + +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: [Expectation](#Expectation) - Returns current instance of the expectation for chaining. + + +### expectation.willTwiceInvoke() ⇒ [Expectation](#Expectation) +Adds a new invoker action, that will call callback passed +on execution time with given arguments. Newly created Invoker +has expected execution count set to 2. + +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: [Expectation](#Expectation) - Returns current instance of the expectation for chaining. + + +### expectation.willRepeatedlyInvoke() +Adds a new invoker action, that will call callback passed +on execution time with given arguments. Newly created Invoker +has unbounded execution time. + +**Kind**: instance method of [Expectation](#Expectation) + + +### expectation.execute(args) ⇒ \* +**Kind**: instance method of [Expectation](#Expectation) +**Returns**: \* - If no action was specified for the expectation, will return no value. +If there is an action to be executed returns result of that execution. +**Throws**: + +- Error Throws error if none of specified actions are valid for execution + + +| Param | Type | +| --- | --- | +| args | Array | + + + +## Invoker ⇐ [Action](#Action) +Specialization of an Action invoking a provided callback +argument. This implementation assumes that callback is +provided as the last argument on the list. + +**Kind**: global class +**Extends**: [Action](#Action) + +* [Invoker](#Invoker) ⇐ [Action](#Action) + * [new Invoker(args, counter)](#new_Invoker_new) + * [.validate()](#Action+validate) ⇒ Boolean + * [.available()](#Action+available) ⇒ Boolean + * [.execute(args)](#Action+execute) ⇒ \* + + + +### new Invoker(args, counter) + +| Param | Type | Description | +| --- | --- | --- | +| args | Array | Array of arguments to be passed to callback on execution time. | +| counter | Number | Action cardinality | + + + +### invoker.validate() ⇒ Boolean +Determines if action has been executed expected number of times. + +**Kind**: instance method of [Invoker](#Invoker) + + +### invoker.available() ⇒ Boolean +Determines if action can be executed. + +**Kind**: instance method of [Invoker](#Invoker) +**Returns**: Boolean - Returns true if action can be executed, false otherwise. + + +### invoker.execute(args) ⇒ \* +Executes current action with provided arguments array. + +**Kind**: instance method of [Invoker](#Invoker) +**Returns**: \* - Propagates return value of internal action. +**Throws**: + +- Error Throws error if current action was already executed specified +number of times. + + +| Param | Type | Description | +| --- | --- | --- | +| args | Array | Array of arguments to be passed to the action function. | + + + +## Matcher +Validates provided list of arguments. + +**Kind**: global class + +* [Matcher](#Matcher) + * [new Matcher(args)](#new_Matcher_new) + * [.check(args)](#Matcher+check) ⇒ Boolean + + + +### new Matcher(args) +Creates Matcher from given arguments + + +| Param | Type | Description | +| --- | --- | --- | +| args | Array | If no argument is provided creates default matcher which validates any arguments.If array contains single element of function type, creates a predicate matcher from provided function. Otherwise creates matcher that will validate arguments against given array. | + + + +### matcher.check(args) ⇒ Boolean +Checks given argument list against matcher. + +**Kind**: instance method of [Matcher](#Matcher) +**Returns**: Boolean - Returns true if given argument list passes the matcher test. + +| Param | Type | Description | +| --- | --- | --- | +| args | Array | Array of arguments used for validation | + + + +## WeakMatcher ⇐ [Matcher](#Matcher) +Specialization of Matcher for weak argument list comparison. + +**Kind**: global class +**Extends**: [Matcher](#Matcher) + +* [WeakMatcher](#WeakMatcher) ⇐ [Matcher](#Matcher) + * [new WeakMatcher()](#new_WeakMatcher_new) + * [.check(args)](#Matcher+check) ⇒ Boolean + + + +### new WeakMatcher() +Passes all arguments to parent constructor. + + + +### weakMatcher.check(args) ⇒ Boolean +Checks given argument list against matcher. + +**Kind**: instance method of [WeakMatcher](#WeakMatcher) +**Returns**: Boolean - Returns true if given argument list passes the matcher test. + +| Param | Type | Description | +| --- | --- | --- | +| args | Array | Array of arguments used for validation | + + + +## Mock +Mock class for wrapping test subject dependencies. + +**Kind**: global class + +* [Mock](#Mock) + * [new Mock(object)](#new_Mock_new) + * [.expectCall(functionName)](#Mock+expectCall) ⇒ [Expectation](#Expectation) + * [.verify(done)](#Mock+verify) + * [.cleanup()](#Mock+cleanup) + + + +### new Mock(object) + +| Param | Type | Description | +| --- | --- | --- | +| object | Object | Object to be mocked. | + + + +### mock.expectCall(functionName) ⇒ [Expectation](#Expectation) +Creates Expectation for function with given name. + +**Kind**: instance method of [Mock](#Mock) +**Returns**: [Expectation](#Expectation) - Returns newly created Expectation object +**Throws**: + +- Error Error is thrown if given function name doesn't match any of +functions from mocked object. + + +| Param | Type | Description | +| --- | --- | --- | +| functionName | String | Name of the function for which the call is expected. | + + + +### mock.verify(done) +Verifies if all expectations on mock object were fulfilled. + +**Kind**: instance method of [Mock](#Mock) +**Throws**: + +- Error If no callback provided, method throws Error containing list of mocked +object functions with unresolved expectations. + + +| Param | Type | Description | +| --- | --- | --- | +| done | function | Optional callback parameter. If provided, function want throw expectation but will pass error to callback. If verification succeeds callback is called with null. | + + + +### mock.cleanup() +Restores original functions in mocked object. + +**Kind**: instance method of [Mock](#Mock) diff --git a/lib/action.js b/lib/action.js index 554a4af..a8a9bb9 100644 --- a/lib/action.js +++ b/lib/action.js @@ -32,10 +32,14 @@ class Action { this.setCounter((typeof counter === 'undefined') ? 1 : counter); } - /** + /** @private + * Sets action counter * * @param {Number} counter * @throws {TypeError} + * Throws TypeError if counter is not a valid number + * @throws {Error} + * Throws error if given counter equals 0. */ setCounter(counter) { check.type(counter, 'number', 'Action counter should be a valid number'); @@ -67,6 +71,8 @@ class Action { * @throws {Error} * Throws error if current action was already executed specified * number of times. + * @returns {*} + * Propagates return value of internal action. */ execute(args) { check.assert(this.counter !== 0, 'Calling execute on already saturated action'); diff --git a/lib/cardinality.js b/lib/cardinality.js index ea5f71b..559f5f4 100644 --- a/lib/cardinality.js +++ b/lib/cardinality.js @@ -2,13 +2,33 @@ const check = require('./check'); +/** Describes number of expected function calls. */ class Cardinality { + /** @constructor + * + * @param {Number} min + * Minimum number of expected calls. + * @param {Number} max + * Maximum number of expected calls. + */ constructor(min, max) { max = max || min; this.set(min, max); this.counter = 0; } + /** Sets new values of minimum and maximum expected calls. + * + * @param {Number} min + * Minimum number of expected calls. + * @param {Number} max + * Maximum number of expected calls. + * @throws {TypeError} + * Throws TypeError if min or max parameter is not a valid number. + * @throws {Error} + * Error is thrown if given minimum expected calls value is negative, + * or if given maximum expected calls value is positive lower than min. + */ set(min, max) { check.type(min, 'number', 'Expected number for min parameter'); check.type(max, 'number', 'Expected number for max parameter'); @@ -20,28 +40,56 @@ class Cardinality { this.max = max; } + /** Removes upper bound from cardinality. */ unbound() { this.max = -1; } + /** Shifts the cardinality by a given number of expected calls. + * + * @param {Number} count + * Number of additional expected calls. + * + * @throws {TypeError} + * Throws TypeError if count parameter is not a valid number. + * @throws {Error} + * Error is thrown if given count is lower or equal to 0. + */ bump(count) { check.type(count, 'number', 'Expected count parameter to be of number type'); check.assert(count > 0, 'Invalid count value ' + count); - this.min += count; + this.min += parseInt(count); if(this.max >= 0) { this.max += count; } } + /** Checks if cardinality allows for more calls. + * + * @returns {Boolean} + * True if cardinality allows at least one more call, + * false otherwise. + */ available() { return ((this.counter < this.max) || (this.max < 0)) } + /** Uses one call from cardinality. + * + * @returns {Boolean} + * True if call didn't cause exceeding cardinality upper + * bound, false otherwise. + */ use() { this.counter += 1; return ((this.counter <= this.max) || (this.max < 0)); } + /** Validates that cardinality was used expected number of times. + * + * @returns {Boolean} + * True if number of calls lies in defined range, false otherwise. + */ validate() { return (this.counter >= this.min) && ((this.counter <= this.max) || (this.max < 0)); diff --git a/lib/expectation.js b/lib/expectation.js index 8ac6614..4f9b839 100644 --- a/lib/expectation.js +++ b/lib/expectation.js @@ -47,17 +47,13 @@ function addAction(action) { this.actions.push(action); } -/** @class Expectation - * - * Class specifying function call expectation. Each expectation contains - * matcher and list of actions. - * - * Matcher specifies if function call argument list is valid. - * Action list determines what actions should be executed and how many times - * on consecutive calls. +/** Class specifying function call expectation. + * Each expectation contains a [matcher]{@link Matcher}, + * [cardinality]{@link Cardinality} and a list of + * [actions]{@link Action} to be executed. */ class Expectation { - /** + /** @constructor * * @param {Array} args * Array of arguments to be used for creation of matcher object @@ -264,7 +260,6 @@ class Expectation { check.assert(idx >= 0, 'Unable to find valid action for execution'); return this.actions[idx].execute(args); } - } module.exports = Expectation; \ No newline at end of file diff --git a/lib/invoker.js b/lib/invoker.js index b445d6c..fd249d0 100644 --- a/lib/invoker.js +++ b/lib/invoker.js @@ -4,7 +4,8 @@ const Action = require('./action'); /** Specialization of an Action invoking a provided callback * argument. This implementation assumes that callback is - * provided as last argument on the list. + * provided as the last argument on the list. + * @extends Action */ class Invoker extends Action { /** @constructor diff --git a/lib/matcher.js b/lib/matcher.js index f3c9f6c..9fda14b 100644 --- a/lib/matcher.js +++ b/lib/matcher.js @@ -15,7 +15,17 @@ class TypeChecker extends ArgChecker { } } +/** Validates provided list of arguments. */ class Matcher { + /** Creates Matcher from given arguments + * + * @param {?Array} args + * If no argument is provided creates default matcher which + * validates any arguments.If array contains single element of + * function type, creates a predicate matcher from provided + * function. Otherwise creates matcher that will validate arguments + * against given array. + */ constructor(args) { args = args || []; if(args.length === 0) { @@ -27,6 +37,13 @@ class Matcher { } } + /** Checks given argument list against matcher. + * + * @param {Array} args + * Array of arguments used for validation + * @returns {Boolean} + * Returns true if given argument list passes the matcher test. + */ check(args) { if(this.predicate) { return this.predicate.apply(null, args); @@ -36,6 +53,15 @@ class Matcher { } + /** @private + * @static + * Compares pair of arguments + * + * @param {*} expected + * Expected argument as provided in matcher. + * @param {*} actual + * Actual argument passed in function call. + */ static compareArgument(expected, actual) { if(expected instanceof ArgChecker) { return expected.check(actual); @@ -43,10 +69,30 @@ class Matcher { return _.isEqual(expected, actual); } + /** @private + * Validates length of argument list. + * + * @param {Array} expected + * Expected argument list as provided in matcher. + * @param {Array} actual + * Actual argument list passed in function call. + * @returns {Boolean} + * True if both lists have the same length, false otherwise. + */ checkLength(expected, actual) { return expected.length === actual.length; } + /** @private + * Check call argument list. + * + * @param {Array} expected + * Expected argument list as provided in matcher. + * @param {Array} actual + * Actual argument list passed in function call. + * @returns {Boolean} + * True if call argument list passes the matcher, false otherwise. + */ checkArguments(expected, actual) { if(!this.checkLength(expected, actual)) { return false; @@ -60,10 +106,26 @@ class Matcher { } } +/** Specialization of Matcher for weak argument list comparison. + * @extends Matcher + */ class WeakMatcher extends Matcher { + /** Passes all arguments to parent constructor. */ constructor(/* ... */) { super(...arguments); } + + /** @private + * Validates length of argument list. + * + * @param {Array} expected + * Expected argument list as provided in matcher. + * @param {Array} actual + * Actual argument list passed in function call. + * @returns {Boolean} + * True if actual argument call list is at least the size + * of expected call list. + */ checkLength(expected, actual) { return expected.length <= actual.length; } diff --git a/lib/mock.js b/lib/mock.js index 4fcc3ee..d0d0184 100644 --- a/lib/mock.js +++ b/lib/mock.js @@ -36,11 +36,10 @@ function formatCall(functionName, args) { return output; } -/** @class Mock - * - */ +/** Mock class for wrapping test subject dependencies. */ class Mock { - /** + /** @constructor + * * @param {Object} object * Object to be mocked. */ @@ -57,7 +56,9 @@ class Mock { } } - /** Bind for all functions of mocked object + /** @private + * Bind for all functions of mocked object + * * @param {String} functionName * Name of the function being called * @throws {UnexpectedCall} @@ -125,8 +126,7 @@ class Mock { } } - /** Restores original functions in mocked object. - */ + /** Restores original functions in mocked object. */ cleanup() { for(const functionName in this.originals) { this.mocked[functionName] = this.originals[functionName];