@fluffy-spoon/substitute
Advanced tools
Comparing version 1.135.0 to 1.136.0
@@ -1,23 +0,38 @@ | ||
export declare class Argument<T> { | ||
private description; | ||
private matchingFunction; | ||
constructor(description: string, matchingFunction: (arg: T) => boolean); | ||
declare type PredicateFunction<T> = (arg: T) => boolean; | ||
declare type ArgumentOptions = { | ||
inverseMatch?: boolean; | ||
}; | ||
declare class BaseArgument<T> { | ||
private _description; | ||
private _matchingFunction; | ||
private _options?; | ||
constructor(_description: string, _matchingFunction: PredicateFunction<T>, _options?: ArgumentOptions); | ||
matches(arg: T): boolean; | ||
toString(): string; | ||
} | ||
export declare class AllArguments extends Argument<any> { | ||
export declare class Argument<T> extends BaseArgument<T> { | ||
private readonly _type; | ||
constructor(description: string, matchingFunction: PredicateFunction<T>, options?: ArgumentOptions); | ||
get type(): 'SingleArgument'; | ||
} | ||
export declare class AllArguments<T extends any[]> extends BaseArgument<T> { | ||
private readonly _type; | ||
constructor(); | ||
get type(): 'AllArguments'; | ||
} | ||
export declare class Arg { | ||
private static _all; | ||
static all(): AllArguments; | ||
static any(): Argument<any> & any; | ||
static any<T extends 'string'>(type: T): Argument<string> & string; | ||
static any<T extends 'number'>(type: T): Argument<number> & number; | ||
static any<T extends 'boolean'>(type: T): Argument<boolean> & boolean; | ||
static any<T extends 'array'>(type: T): Argument<any[]> & any[]; | ||
static any<T extends 'function'>(type: T): Argument<Function> & Function; | ||
static any<T extends 'string' | 'number' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | 'array'>(type: T): Argument<any> & any; | ||
static is<T>(predicate: (input: any) => boolean): Argument<T> & T; | ||
private static toStringify; | ||
export declare namespace Arg { | ||
type ExtractFirstArg<T> = T extends AllArguments<infer TArgs> ? TArgs[0] : T; | ||
type ReturnArg<T> = Argument<T> & T; | ||
type Inversable<T> = T & { | ||
not: T; | ||
}; | ||
export const all: <T extends any[]>() => AllArguments<T>; | ||
type Is = <T>(predicate: PredicateFunction<ExtractFirstArg<T>>) => ReturnArg<ExtractFirstArg<T>>; | ||
export const is: Inversable<Is>; | ||
type MapAnyReturn<T> = T extends 'any' ? ReturnArg<any> : T extends 'string' ? ReturnArg<string> : T extends 'number' ? ReturnArg<number> : T extends 'boolean' ? ReturnArg<boolean> : T extends 'symbol' ? ReturnArg<symbol> : T extends 'undefined' ? ReturnArg<undefined> : T extends 'object' ? ReturnArg<object> : T extends 'function' ? ReturnArg<Function> : T extends 'array' ? ReturnArg<any[]> : any; | ||
type AnyType = 'string' | 'number' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | 'array' | 'any'; | ||
type Any = <T extends AnyType = 'any'>(type?: T) => MapAnyReturn<T>; | ||
export const any: Inversable<Any>; | ||
export {}; | ||
} | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class Argument { | ||
constructor(description, matchingFunction) { | ||
this.description = description; | ||
this.matchingFunction = matchingFunction; | ||
exports.Arg = exports.AllArguments = exports.Argument = void 0; | ||
class BaseArgument { | ||
constructor(_description, _matchingFunction, _options) { | ||
this._description = _description; | ||
this._matchingFunction = _matchingFunction; | ||
this._options = _options; | ||
} | ||
matches(arg) { | ||
return this.matchingFunction(arg); | ||
var _a, _b; | ||
const inverseMatch = (_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.inverseMatch) !== null && _b !== void 0 ? _b : false; | ||
return inverseMatch ? !this._matchingFunction(arg) : this._matchingFunction(arg); | ||
} | ||
toString() { | ||
return this.description; | ||
return this._description; | ||
} | ||
[Symbol.for('nodejs.util.inspect.custom')]() { | ||
return this.description; | ||
return this._description; | ||
} | ||
} | ||
class Argument extends BaseArgument { | ||
constructor(description, matchingFunction, options) { | ||
super(description, matchingFunction, options); | ||
this._type = 'SingleArgument'; | ||
} | ||
get type() { | ||
return this._type; | ||
} | ||
} | ||
exports.Argument = Argument; | ||
class AllArguments extends Argument { | ||
class AllArguments extends BaseArgument { | ||
constructor() { | ||
super('{all}', () => true); | ||
super('{all}', () => true, {}); | ||
this._type = 'AllArguments'; | ||
} | ||
get type() { | ||
return this._type; | ||
} | ||
} | ||
exports.AllArguments = AllArguments; | ||
class Arg { | ||
static all() { | ||
return this._all = (this._all || new AllArguments()); | ||
} | ||
static any(type) { | ||
const description = !type ? '{any arg}' : '{type ' + type + '}'; | ||
return new Argument(description, x => { | ||
if (!type) | ||
return true; | ||
if (type === 'array') | ||
return Array.isArray(x); | ||
return typeof x === type; | ||
}); | ||
} | ||
static is(predicate) { | ||
return new Argument('{predicate ' + this.toStringify(predicate) + '}', predicate); | ||
} | ||
static toStringify(obj) { | ||
var Arg; | ||
(function (Arg) { | ||
const factory = (factoryF) => (...args) => factoryF(...args); | ||
const toStringify = (obj) => { | ||
if (typeof obj.inspect === 'function') | ||
@@ -48,5 +51,26 @@ return obj.inspect(); | ||
return obj; | ||
} | ||
} | ||
exports.Arg = Arg; | ||
}; | ||
Arg.all = () => new AllArguments(); | ||
const isFunction = (predicate, options) => new Argument(`{predicate ${toStringify(predicate)}}`, predicate, options); | ||
const isArgFunction = (predicate) => factory(isFunction)(predicate); | ||
isArgFunction.not = (predicate) => factory(isFunction)(predicate, { inverseMatch: true }); | ||
Arg.is = isArgFunction; | ||
const anyFunction = (type = 'any', options) => { | ||
const description = !type ? '{any arg}' : `{type ${type}}`; | ||
const predicate = (x) => { | ||
switch (type) { | ||
case 'any': | ||
return true; | ||
case 'array': | ||
return Array.isArray(x); | ||
default: | ||
return typeof x === type; | ||
} | ||
}; | ||
return new Argument(description, predicate, options); | ||
}; | ||
const anyArgFunction = (type) => factory(anyFunction)(type); | ||
anyArgFunction.not = (type) => factory(anyFunction)(type, { inverseMatch: true }); | ||
Arg.any = anyArgFunction; | ||
})(Arg = exports.Arg || (exports.Arg = {})); | ||
//# sourceMappingURL=Arguments.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Context = void 0; | ||
const util_1 = require("util"); | ||
@@ -4,0 +5,0 @@ const InitialState_1 = require("./states/InitialState"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Substitute = void 0; | ||
const Substitute_1 = require("./Substitute"); | ||
exports.Substitute = Substitute_1.Substitute; | ||
Object.defineProperty(exports, "Substitute", { enumerable: true, get: function () { return Substitute_1.Substitute; } }); | ||
var Arguments_1 = require("./Arguments"); | ||
exports.Arg = Arguments_1.Arg; | ||
Object.defineProperty(exports, "Arg", { enumerable: true, get: function () { return Arguments_1.Arg; } }); | ||
exports.default = Substitute_1.Substitute; | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.FunctionState = void 0; | ||
const Utilities_1 = require("../Utilities"); | ||
@@ -4,0 +5,0 @@ const SubstituteBase_1 = require("../SubstituteBase"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.GetPropertyState = void 0; | ||
const FunctionState_1 = require("./FunctionState"); | ||
@@ -4,0 +5,0 @@ const Utilities_1 = require("../Utilities"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.InitialState = void 0; | ||
const SetPropertyState_1 = require("./SetPropertyState"); | ||
@@ -4,0 +5,0 @@ const Utilities_1 = require("../Utilities"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SetPropertyState = void 0; | ||
const Utilities_1 = require("../Utilities"); | ||
@@ -4,0 +5,0 @@ const SubstituteBase_1 = require("../SubstituteBase"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Substitute = exports.AreProxiesDisabledKey = exports.HandlerKey = void 0; | ||
const Context_1 = require("./Context"); | ||
@@ -4,0 +5,0 @@ const Utilities_1 = require("./Utilities"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SubstituteException = exports.SubstituteJS = void 0; | ||
const util_1 = require("util"); | ||
@@ -4,0 +5,0 @@ const Utilities_1 = require("./Utilities"); |
@@ -25,3 +25,3 @@ import { AllArguments } from "./Arguments"; | ||
declare type FunctionHandler<TArguments extends any[], TReturnType, Terminating> = Equals<TArguments, unknown[]> extends true ? {} : Terminating extends true ? TerminatingFunction<TArguments> : FunctionSubstitute<TArguments, TReturnType>; | ||
export declare type FunctionSubstitute<TArguments extends any[], TReturnType> = ((...args: TArguments) => (TReturnType & MockObjectMixin<TArguments, TReturnType>)) & ((allArguments: AllArguments) => (TReturnType & MockObjectMixin<TArguments, TReturnType>)); | ||
export declare type FunctionSubstitute<TArguments extends any[], TReturnType> = ((...args: TArguments) => (TReturnType & MockObjectMixin<TArguments, TReturnType>)) & ((allArguments: AllArguments<TArguments>) => (TReturnType & MockObjectMixin<TArguments, TReturnType>)); | ||
export declare type NoArgumentFunctionSubstitute<TReturnType> = (() => (TReturnType & NoArgumentMockObjectMixin<TReturnType>)); | ||
@@ -48,3 +48,3 @@ export declare type PropertySubstitute<TReturnType> = (TReturnType & Partial<NoArgumentMockObjectMixin<TReturnType>>); | ||
}; | ||
declare type TerminatingFunction<TArguments extends any[]> = ((...args: TArguments) => void) & ((arg: AllArguments) => void); | ||
declare type TerminatingFunction<TArguments extends any[]> = ((...args: TArguments) => void) & ((arg: AllArguments<TArguments>) => void); | ||
declare type TerminatingObject<T> = { | ||
@@ -51,0 +51,0 @@ [P in keyof T]: T[P] extends (...args: infer F) => any ? F extends [] ? () => void : FunctionSubstituteWithOverloads<T[P], true> : T[P]; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Get = exports.areArgumentsEqual = exports.stringifyCalls = exports.areArgumentArraysEqual = exports.stringifyArguments = exports.Nothing = exports.SubstituteMethods = exports.Type = void 0; | ||
const Arguments_1 = require("./Arguments"); | ||
@@ -4,0 +5,0 @@ const GetPropertyState_1 = require("./states/GetPropertyState"); |
{ | ||
"name": "@fluffy-spoon/substitute", | ||
"version": "1.135.0", | ||
"version": "1.136.0", | ||
"description": "An NSubstitute port to TypeScript called substitute.js.", | ||
@@ -34,3 +34,3 @@ "license": "MIT", | ||
"ava": "^3.8.2", | ||
"typescript": "^3.0.0" | ||
"typescript": "^3.9.2" | ||
}, | ||
@@ -37,0 +37,0 @@ "ava": { |
113
README.md
@@ -28,9 +28,9 @@ <a href="https://opencollective.com/substitute-js#section-contribute"><img src="https://opencollective.com/substitute-js/backers/badge.svg" alt="OpenCollective backers"></a> <a href="https://opencollective.com/substitute-js#section-contribute"><img src="https://opencollective.com/substitute-js/sponsors/badge.svg" alt="OpenCollective sponsors"></a> | ||
//Create: | ||
var calculator = Substitute.for<Calculator>(); | ||
// Create: | ||
const calculator = Substitute.for<Calculator>(); | ||
//Set a return value: | ||
// Set a return value: | ||
calculator.add(1, 2).returns(3); | ||
//Check received calls: | ||
// Check received calls: | ||
calculator.received().add(1, Arg.any()); | ||
@@ -41,3 +41,3 @@ calculator.didNotReceive().add(2, 2); | ||
## Creating a mock | ||
`var calculator = Substitute.for<Calculator>();` | ||
`const calculator = Substitute.for<Calculator>();` | ||
@@ -48,13 +48,13 @@ ## Setting return types | ||
```typescript | ||
//single return type | ||
// single return type | ||
calculator.add(1, 2).returns(4); | ||
console.log(calculator.add(1, 2)); //prints 4 | ||
console.log(calculator.add(1, 2)); //prints undefined | ||
console.log(calculator.add(1, 2)); // prints 4 | ||
console.log(calculator.add(1, 2)); // prints undefined | ||
//multiple return types in sequence | ||
// multiple return types in sequence | ||
calculator.add(1, 2).returns(3, 7, 9); | ||
console.log(calculator.add(1, 2)); //prints 3 | ||
console.log(calculator.add(1, 2)); //prints 7 | ||
console.log(calculator.add(1, 2)); //prints 9 | ||
console.log(calculator.add(1, 2)); //prints undefined | ||
console.log(calculator.add(1, 2)); // prints 3 | ||
console.log(calculator.add(1, 2)); // prints 7 | ||
console.log(calculator.add(1, 2)); // prints 9 | ||
console.log(calculator.add(1, 2)); // prints undefined | ||
``` | ||
@@ -67,4 +67,4 @@ | ||
calculator.heavyOperation(1, 2).resolves(4); | ||
//same as calculator.heavyOperation(1, 2).returns(Promise.resolve(4)); | ||
console.log(await calculator.heavyOperation(1, 2)); //prints 4 | ||
// same as calculator.heavyOperation(1, 2).returns(Promise.resolve(4)); | ||
console.log(await calculator.heavyOperation(1, 2)); // prints 4 | ||
``` | ||
@@ -74,4 +74,4 @@ | ||
calculator.heavyOperation(1, 2).rejects(new Error()); | ||
//same as calculator.heavyOperation(1, 2).returns(Promise.reject(new Error())); | ||
console.log(await calculator.heavyOperation(1, 2)); //throws Error | ||
// same as calculator.heavyOperation(1, 2).returns(Promise.reject(new Error())); | ||
console.log(await calculator.heavyOperation(1, 2)); // throws Error | ||
``` | ||
@@ -82,8 +82,8 @@ | ||
calculator.enabled = true; | ||
var foo = calculator.add(1, 2); | ||
const foo = calculator.add(1, 2); | ||
//verify call to add(1, 2) | ||
// verify call to add(1, 2) | ||
calculator.received().add(1, 2); | ||
//verify property set to "true" | ||
// verify property set to "true" | ||
calculator.received().enabled = true; | ||
@@ -99,17 +99,34 @@ ``` | ||
//ignoring first argument | ||
// ignoring first argument | ||
calculator.add(Arg.any(), 2).returns(10); | ||
console.log(calculator.add(1337, 3)); //prints undefined since second argument doesn't match | ||
console.log(calculator.add(1337, 2)); //prints 10 since second argument matches | ||
console.log(calculator.add(1337, 3)); // prints undefined since second argument doesn't match | ||
console.log(calculator.add(1337, 2)); // prints 10 since second argument matches | ||
//received call with first arg 1 and second arg less than 0 | ||
// received call with first arg 1 and second arg less than 0 | ||
calculator.received().add(1, Arg.is(x => x < 0)); | ||
``` | ||
### Generic and inverse matchers | ||
```typescript | ||
import { Arg } from '@fluffy-spoon/substitute'; | ||
const equalToZero = (x: number) => x === 0; | ||
// first argument will match any number | ||
// second argument will match a number that is not '0' | ||
calculator.divide(Arg.any('number'), Arg.is.not(equalToZero)).returns(10); | ||
console.log(calculator.divide(100, 10)); // prints 10 | ||
const argIsNotZero = Arg.is.not(equalToZero); | ||
calculator.received(1).divide(argIsNotZero, argIsNotZero); | ||
``` | ||
> #### Note: `Arg.is()` will automatically infer the type of the argument it's replacing | ||
### Ignoring all arguments | ||
```typescript | ||
//ignoring all arguments | ||
// ignoring all arguments | ||
calculator.add(Arg.all()).returns(10); | ||
console.log(calculator.add(1, 3)); //prints 10 | ||
console.log(calculator.add(5, 2)); //prints 10 | ||
console.log(calculator.add(1, 3)); // prints 10 | ||
console.log(calculator.add(5, 2)); // prints 10 | ||
``` | ||
@@ -123,4 +140,4 @@ | ||
calculator.add(1, 3).returns(1337); | ||
console.log(calculator.add(1, 3)); //prints 10 | ||
console.log(calculator.add(5, 2)); //prints 10 | ||
console.log(calculator.add(1, 3)); // prints 10 | ||
console.log(calculator.add(5, 2)); // prints 10 | ||
``` | ||
@@ -131,4 +148,4 @@ | ||
calculator.add(Arg.all()).returns(10); | ||
console.log(calculator.add(1, 3)); //prints 1337 | ||
console.log(calculator.add(5, 2)); //prints 10 | ||
console.log(calculator.add(1, 3)); // prints 1337 | ||
console.log(calculator.add(5, 2)); // prints 10 | ||
``` | ||
@@ -148,22 +165,22 @@ | ||
var realCalculator = new RealCalculator(); | ||
var fakeCalculator = Substitute.for<Calculator>(); | ||
const realCalculator = new RealCalculator(); | ||
const fakeCalculator = Substitute.for<Calculator>(); | ||
//let the subtract method always use the real method | ||
// let the subtract method always use the real method | ||
fakeCalculator.subtract(Arg.all()).mimicks(realCalculator.subtract); | ||
console.log(fakeCalculator.subtract(20, 10)); //prints 10 | ||
console.log(fakeCalculator.subtract(1, 2)); //prints -1 | ||
console.log(fakeCalculator.subtract(20, 10)); // prints 10 | ||
console.log(fakeCalculator.subtract(1, 2)); // prints -1 | ||
//for the add method, we only use the real method when the first arg is less than 10 | ||
//else, we always return 1337 | ||
// for the add method, we only use the real method when the first arg is less than 10 | ||
// else, we always return 1337 | ||
fakeCalculator.add(Arg.is(x < 10), Arg.any()).mimicks(realCalculator.add); | ||
fakeCalculator.add(Arg.is(x >= 10), Arg.any()).returns(1337); | ||
console.log(fakeCalculator.add(5, 100)); //prints 105 via real method | ||
console.log(fakeCalculator.add(210, 7)); //prints 1337 via fake method | ||
console.log(fakeCalculator.add(5, 100)); // prints 105 via real method | ||
console.log(fakeCalculator.add(210, 7)); // prints 1337 via fake method | ||
//for the divide method, we only use the real method for explicit arguments | ||
// for the divide method, we only use the real method for explicit arguments | ||
fakeCalculator.divide(10, 2).mimicks(realCalculator.divide); | ||
fakeCalculator.divide(Arg.all()).returns(1338); | ||
console.log(fakeCalculator.divide(10, 5)); //prints 5 | ||
console.log(fakeCalculator.divide(9, 5)); //prints 1338 | ||
console.log(fakeCalculator.divide(10, 5)); // prints 5 | ||
console.log(fakeCalculator.divide(9, 5)); // prints 1338 | ||
``` | ||
@@ -209,11 +226,11 @@ | ||
var fake = Substitute.for<Example>(); | ||
const fake = Substitute.for<Example>(); | ||
//BAD: this would have called substitute.js' "received" method. | ||
//fake.received(2); | ||
// BAD: this would have called substitute.js' "received" method. | ||
// fake.received(2); | ||
//GOOD: we now call the "received" method we have defined in the class above. | ||
// GOOD: we now call the "received" method we have defined in the class above. | ||
Substitute.disableFor(fake).received(1337); | ||
//now we can assert that we received a call to the "received" method. | ||
// now we can assert that we received a call to the "received" method. | ||
fake.received().received(1337); | ||
@@ -220,0 +237,0 @@ ``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
123246
1036
241