From 0b75a04407a0a562bf4f46251def6c3f8e787f9f Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Tue, 19 Feb 2019 17:03:30 +0100 Subject: [PATCH 1/8] Infer parameter and return types for sinon.spy() --- types/sinon/ts3.1/index.d.ts | 4 +-- types/sinon/ts3.1/sinon-tests.ts | 44 ++++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/types/sinon/ts3.1/index.d.ts b/types/sinon/ts3.1/index.d.ts index 7123e75d49..6b7830722c 100644 --- a/types/sinon/ts3.1/index.d.ts +++ b/types/sinon/ts3.1/index.d.ts @@ -211,7 +211,7 @@ declare namespace Sinon { returnValues: TReturnValue[]; // Methods - (...args: any[]): any; + (...args: TArgs): TReturnValue; /** * Returns true if the spy was called before @param anotherSpy * @param anotherSpy @@ -338,7 +338,7 @@ declare namespace Sinon { /** * Spies on the provided function */ - (func: Function): SinonSpy; + any>(func: F): SinonSpy, ReturnType>; /** * Creates a spy for object.method and replaces the original method with the spy. * An exception is thrown if the property is not already a function. diff --git a/types/sinon/ts3.1/sinon-tests.ts b/types/sinon/ts3.1/sinon-tests.ts index 2db25348ae..d27d03c230 100644 --- a/types/sinon/ts3.1/sinon-tests.ts +++ b/types/sinon/ts3.1/sinon-tests.ts @@ -83,8 +83,8 @@ function testSandbox() { const privateFooStubbedInstance = sb.createStubInstance(PrivateFoo); stubInstance.foo.calledWith('foo', 1); privateFooStubbedInstance.foo.calledWith(); - const clsFoo: sinon.SinonStub = stubInstance.foo; - const privateFooFoo: sinon.SinonStub = privateFooStubbedInstance.foo; + const clsFoo: sinon.SinonStub<[string, number], number> = stubInstance.foo; + const privateFooFoo: sinon.SinonStub<[], void> = privateFooStubbedInstance.foo; const clsBar: number = stubInstance.bar; const privateFooBar: number = privateFooStubbedInstance.bar; } @@ -325,7 +325,7 @@ function testTypedSpy() { } function testSpy() { - const fn = () => { }; + let fn = (arg: string, arg2: number): boolean => true; const obj = class { foo() { } set bar(val: number) { } @@ -333,12 +333,11 @@ function testSpy() { }; const instance = new obj(); - let spy = sinon.spy(); + const spy = sinon.spy(); // $ExpectType SinonSpy const spyTwo = sinon.spy().named('spyTwo'); - spy = sinon.spy(fn); - spy = sinon.spy(instance, 'foo'); - spy = sinon.spy(instance, 'bar', ['set', 'get']); + const methodSpy = sinon.spy(instance, 'foo'); + const methodSpy2 = sinon.spy(instance, 'bar', ['set', 'get']); let count = 0; count = spy.callCount; @@ -356,7 +355,12 @@ function testSpy() { arr = spy.exceptions; arr = spy.returnValues; - spy('a', 'b'); + const fnSpy = sinon.spy(fn); // $ExpectType SinonSpy<[string, number], boolean> + fn = fnSpy; // Should be assignable to original function + fnSpy('a', 1); // $ExpectType boolean + fnSpy.args; // $ExpectType [string, number][] + fnSpy.returnValues; // $ExpectType boolean[] + spy(1, 2); spy(true); @@ -420,13 +424,12 @@ function testSpy() { function testStub() { const obj = class { - foo() { } + foo(arg: string): number { return 1; } promiseFunc() { return Promise.resolve('foo'); } }; const instance = new obj(); - let stub = sinon.stub(); - stub = sinon.stub(instance, 'foo').named('namedStub'); + const stub = sinon.stub(); const spy: sinon.SinonSpy = stub; @@ -485,6 +488,25 @@ function testStub() { stub.yieldsToAsync('foo', 'a', 2); stub.yieldsToOnAsync('foo', instance, 'a', 2); stub.withArgs('a', 2).returns(true); + + // Type-safe stubs + const stub2 = sinon.stub(instance, 'foo').named('namedStub'); + instance.foo = stub2; // Should be assignable to original + stub2.returns(true); // $ExpectError + stub2.returns(5); + stub2.returns('foo'); // $ExpectError + stub2.callsFake((arg: string) => 1); + stub2.callsFake((arg: number) => 1); // $ExpectError + stub2.callsFake((arg: string) => 'a'); // $ExpectError + stub2.onCall(1).returns(2); + stub2.withArgs('a', 2).returns('true'); // $ExpectError + stub2.withArgs('a').returns(1); + stub2.withArgs('a').returns('a'); // $ExpectError + + const pStub = sinon.stub(instance, 'promiseFunc'); + pStub.resolves(); + pStub.resolves('foo'); + pStub.resolves(1); // $ExpectError } function testTypedStub() { From 34b2e5e53acf5aa3993c3fa84a912b9affd35370 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Tue, 19 Feb 2019 23:14:41 +0100 Subject: [PATCH 2/8] Fix and improve sinon.assert() with new types, add tests --- types/sinon/ts3.1/index.d.ts | 56 ++++++++++++++++---------------- types/sinon/ts3.1/sinon-tests.ts | 44 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/types/sinon/ts3.1/index.d.ts b/types/sinon/ts3.1/index.d.ts index 6b7830722c..3898097278 100644 --- a/types/sinon/ts3.1/index.d.ts +++ b/types/sinon/ts3.1/index.d.ts @@ -1155,129 +1155,129 @@ declare namespace Sinon { * Passes if spy was never called * @param spy */ - notCalled(spy: SinonSpy): void; + notCalled(spy: SinonSpy): void; /** * Passes if spy was called at least once. */ - called(spy: SinonSpy): void; + called(spy: SinonSpy): void; /** * Passes if spy was called once and only once. */ - calledOnce(spy: SinonSpy): void; + calledOnce(spy: SinonSpy): void; /** * Passes if spy was called exactly twice. */ - calledTwice(spy: SinonSpy): void; + calledTwice(spy: SinonSpy): void; /** * Passes if spy was called exactly three times. */ - calledThrice(spy: SinonSpy): void; + calledThrice(spy: SinonSpy): void; /** * Passes if spy was called exactly num times. */ - callCount(spy: SinonSpy, count: number): void; + callCount(spy: SinonSpy, count: number): void; /** * Passes if provided spies were called in the specified order. * @param spies */ - callOrder(...spies: SinonSpy[]): void; + callOrder(...spies: SinonSpy[]): void; /** * Passes if spy was ever called with obj as its this value. * It’s possible to assert on a dedicated spy call: sinon.assert.calledOn(spy.firstCall, arg1, arg2, ...);. */ - calledOn(spyOrSpyCall: SinonSpy | SinonSpyCall, obj: any): void; + calledOn(spyOrSpyCall: SinonSpy | SinonSpyCall, obj: any): void; /** * Passes if spy was always called with obj as its this value. */ - alwaysCalledOn(spy: SinonSpy, obj: any): void; + alwaysCalledOn(spy: SinonSpy, obj: any): void; /** * Passes if spy was called with the provided arguments. * It’s possible to assert on a dedicated spy call: sinon.assert.calledWith(spy.firstCall, arg1, arg2, ...);. * @param spyOrSpyCall * @param args */ - calledWith(spyOrSpyCall: SinonSpy | SinonSpyCall, ...args: any[]): void; + calledWith(spyOrSpyCall: SinonSpy | SinonSpyCall, ...args: MatchArguments): void; /** * Passes if spy was always called with the provided arguments. * @param spy * @param args */ - alwaysCalledWith(spy: SinonSpy, ...args: any[]): void; + alwaysCalledWith(spy: SinonSpy, ...args: MatchArguments): void; /** * Passes if spy was never called with the provided arguments. * @param spy * @param args */ - neverCalledWith(spy: SinonSpy, ...args: any[]): void; + neverCalledWith(spy: SinonSpy, ...args: MatchArguments): void; /** * Passes if spy was called with the provided arguments and no others. * It’s possible to assert on a dedicated spy call: sinon.assert.calledWithExactly(spy.getCall(1), arg1, arg2, ...);. * @param spyOrSpyCall * @param args */ - calledWithExactly( - spyOrSpyCall: SinonSpy | SinonSpyCall, - ...args: any[] + calledWithExactly( + spyOrSpyCall: SinonSpy | SinonSpyCall, + ...args: MatchArguments ): void; /** * Passes if spy was always called with the provided arguments and no others. */ - alwaysCalledWithExactly(spy: SinonSpy, ...args: any[]): void; + alwaysCalledWithExactly(spy: SinonSpy, ...args: MatchArguments): void; /** * Passes if spy was called with matching arguments. * This behaves the same way as sinon.assert.calledWith(spy, sinon.match(arg1), sinon.match(arg2), ...). * It’s possible to assert on a dedicated spy call: sinon.assert.calledWithMatch(spy.secondCall, arg1, arg2, ...);. */ - calledWithMatch( - spyOrSpyCall: SinonSpy | SinonSpyCall, - ...args: any[] + calledWithMatch( + spyOrSpyCall: SinonSpy | SinonSpyCall, + ...args: TArgs ): void; /** * Passes if spy was always called with matching arguments. * This behaves the same way as sinon.assert.alwaysCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...). */ - alwaysCalledWithMatch(spy: SinonSpy, ...args: any[]): void; + alwaysCalledWithMatch(spy: SinonSpy, ...args: TArgs): void; /** * Passes if spy was never called with matching arguments. * This behaves the same way as sinon.assert.neverCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...). * @param spy * @param args */ - neverCalledWithMatch(spy: SinonSpy, ...args: any[]): void; + neverCalledWithMatch(spy: SinonSpy, ...args: TArgs): void; /** * Passes if spy was called with the new operator. * It’s possible to assert on a dedicated spy call: sinon.assert.calledWithNew(spy.secondCall, arg1, arg2, ...);. * @param spyOrSpyCall */ - calledWithNew(spyOrSpyCall: SinonSpy | SinonSpyCall): void; + calledWithNew(spyOrSpyCall: SinonSpy | SinonSpyCall): void; /** * Passes if spy threw any exception. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall): void; + threw(spyOrSpyCall: SinonSpy | SinonSpyCall): void; /** * Passes if spy threw the given exception. * The exception is an actual object. * It’s possible to assert on a dedicated spy call: sinon.assert.threw(spy.thirdCall, exception);. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: string): void; + threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: string): void; /** * Passes if spy threw the given exception. * The exception is a String denoting its type. * It’s possible to assert on a dedicated spy call: sinon.assert.threw(spy.thirdCall, exception);. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: any): void; + threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: any): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy): void; + alwaysThrew(spy: SinonSpy): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy, exception: string): void; + alwaysThrew(spy: SinonSpy, exception: string): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy, exception: any): void; + alwaysThrew(spy: SinonSpy, exception: any): void; /** * Uses sinon.match to test if the arguments can be considered a match. */ diff --git a/types/sinon/ts3.1/sinon-tests.ts b/types/sinon/ts3.1/sinon-tests.ts index d27d03c230..3fc046eb96 100644 --- a/types/sinon/ts3.1/sinon-tests.ts +++ b/types/sinon/ts3.1/sinon-tests.ts @@ -287,6 +287,50 @@ function testAssert() { sinon.assert.expose(obj); sinon.assert.expose(obj, { prefix: 'blah' }); sinon.assert.expose(obj, { includeFail: true }); + + const typedSpy = sinon.spy((arg1: string, arg2: boolean) => 123); + sinon.assert.notCalled(typedSpy); + sinon.assert.called(typedSpy); + sinon.assert.calledOnce(typedSpy); + sinon.assert.calledTwice(typedSpy); + sinon.assert.calledThrice(typedSpy); + sinon.assert.callCount(typedSpy, 3); + sinon.assert.callOrder(typedSpy, spyTwo); + sinon.assert.calledOn(typedSpy, obj); + sinon.assert.calledOn(typedSpy.firstCall, obj); + sinon.assert.alwaysCalledOn(typedSpy, obj); + sinon.assert.alwaysCalledWith(typedSpy, 'a', 'b', 'c'); // $ExpectError + sinon.assert.alwaysCalledWith(typedSpy, 'a', true); + sinon.assert.neverCalledWith(typedSpy, 'a', false); + sinon.assert.neverCalledWith(typedSpy, 'a', 'b'); // $ExpectError + sinon.assert.calledWithExactly(typedSpy, 'a', true); + sinon.assert.calledWithExactly(typedSpy, 'a', 'b'); // $ExpectError + sinon.assert.alwaysCalledWithExactly(typedSpy, 'a', true); + sinon.assert.alwaysCalledWithExactly(typedSpy, 'a', 1); // $ExpectError + sinon.assert.calledWithMatch(typedSpy, 'a', true); + sinon.assert.calledWithMatch(typedSpy.firstCall, 'a', true); + sinon.assert.calledWithMatch(typedSpy.firstCall, 'a', 2); // $ExpectError + sinon.assert.alwaysCalledWithMatch(typedSpy, 'a', true); + sinon.assert.alwaysCalledWithMatch(typedSpy, 'a', 2); // $ExpectError + sinon.assert.neverCalledWithMatch(typedSpy, 'a', true); + sinon.assert.neverCalledWithMatch(typedSpy, 'a', 2); // $ExpectError + sinon.assert.calledWithNew(typedSpy); + sinon.assert.calledWithNew(typedSpy.firstCall); + sinon.assert.threw(typedSpy); + sinon.assert.threw(typedSpy.firstCall); + sinon.assert.threw(typedSpy, 'foo error'); + sinon.assert.threw(typedSpy.firstCall, 'foo error'); + sinon.assert.threw(typedSpy, new Error('foo')); + sinon.assert.threw(typedSpy.firstCall, new Error('foo')); + sinon.assert.alwaysThrew(typedSpy); + sinon.assert.alwaysThrew(typedSpy, 'foo error'); + sinon.assert.alwaysThrew(typedSpy, new Error('foo')); + sinon.assert.match('a', 'b'); + sinon.assert.match(1, 1 + 1); + sinon.assert.match({ a: 1 }, { b: 2, c: 'abc' }); + sinon.assert.expose(obj); + sinon.assert.expose(obj, { prefix: 'blah' }); + sinon.assert.expose(obj, { includeFail: true }); } function testTypedSpy() { From e50e51a73ab644ca2be9783807fd199caa373521 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Wed, 20 Feb 2019 10:35:23 +0100 Subject: [PATCH 3/8] Fix TSLint --- types/sinon/ts3.1/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/sinon/ts3.1/index.d.ts b/types/sinon/ts3.1/index.d.ts index 3898097278..b491b3cf88 100644 --- a/types/sinon/ts3.1/index.d.ts +++ b/types/sinon/ts3.1/index.d.ts @@ -1180,7 +1180,7 @@ declare namespace Sinon { * Passes if provided spies were called in the specified order. * @param spies */ - callOrder(...spies: SinonSpy[]): void; + callOrder(...spies: Array>): void; /** * Passes if spy was ever called with obj as its this value. * It’s possible to assert on a dedicated spy call: sinon.assert.calledOn(spy.firstCall, arg1, arg2, ...);. From 1f9582f217990e222ae52256495b9b706f414557 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Wed, 20 Feb 2019 12:53:26 +0100 Subject: [PATCH 4/8] Remove any --- types/sinon/ts3.1/index.d.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/types/sinon/ts3.1/index.d.ts b/types/sinon/ts3.1/index.d.ts index b491b3cf88..8307b9782d 100644 --- a/types/sinon/ts3.1/index.d.ts +++ b/types/sinon/ts3.1/index.d.ts @@ -1155,41 +1155,41 @@ declare namespace Sinon { * Passes if spy was never called * @param spy */ - notCalled(spy: SinonSpy): void; + notCalled(spy: SinonSpy): void; /** * Passes if spy was called at least once. */ - called(spy: SinonSpy): void; + called(spy: SinonSpy): void; /** * Passes if spy was called once and only once. */ - calledOnce(spy: SinonSpy): void; + calledOnce(spy: SinonSpy): void; /** * Passes if spy was called exactly twice. */ - calledTwice(spy: SinonSpy): void; + calledTwice(spy: SinonSpy): void; /** * Passes if spy was called exactly three times. */ - calledThrice(spy: SinonSpy): void; + calledThrice(spy: SinonSpy): void; /** * Passes if spy was called exactly num times. */ - callCount(spy: SinonSpy, count: number): void; + callCount(spy: SinonSpy, count: number): void; /** * Passes if provided spies were called in the specified order. * @param spies */ - callOrder(...spies: Array>): void; + callOrder(...spies: Array>): void; /** * Passes if spy was ever called with obj as its this value. * It’s possible to assert on a dedicated spy call: sinon.assert.calledOn(spy.firstCall, arg1, arg2, ...);. */ - calledOn(spyOrSpyCall: SinonSpy | SinonSpyCall, obj: any): void; + calledOn(spyOrSpyCall: SinonSpy | SinonSpyCall, obj: any): void; /** * Passes if spy was always called with obj as its this value. */ - alwaysCalledOn(spy: SinonSpy, obj: any): void; + alwaysCalledOn(spy: SinonSpy, obj: any): void; /** * Passes if spy was called with the provided arguments. * It’s possible to assert on a dedicated spy call: sinon.assert.calledWith(spy.firstCall, arg1, arg2, ...);. @@ -1249,35 +1249,35 @@ declare namespace Sinon { * It’s possible to assert on a dedicated spy call: sinon.assert.calledWithNew(spy.secondCall, arg1, arg2, ...);. * @param spyOrSpyCall */ - calledWithNew(spyOrSpyCall: SinonSpy | SinonSpyCall): void; + calledWithNew(spyOrSpyCall: SinonSpy | SinonSpyCall): void; /** * Passes if spy threw any exception. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall): void; + threw(spyOrSpyCall: SinonSpy | SinonSpyCall): void; /** * Passes if spy threw the given exception. * The exception is an actual object. * It’s possible to assert on a dedicated spy call: sinon.assert.threw(spy.thirdCall, exception);. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: string): void; + threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: string): void; /** * Passes if spy threw the given exception. * The exception is a String denoting its type. * It’s possible to assert on a dedicated spy call: sinon.assert.threw(spy.thirdCall, exception);. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: any): void; + threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: any): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy): void; + alwaysThrew(spy: SinonSpy): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy, exception: string): void; + alwaysThrew(spy: SinonSpy, exception: string): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy, exception: any): void; + alwaysThrew(spy: SinonSpy, exception: any): void; /** * Uses sinon.match to test if the arguments can be considered a match. */ From cd4db81e36a23af91718487a2cc60d133e8df44d Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Wed, 20 Feb 2019 12:57:09 +0100 Subject: [PATCH 5/8] Leave any for callOrder() --- types/sinon/ts3.1/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/sinon/ts3.1/index.d.ts b/types/sinon/ts3.1/index.d.ts index 8307b9782d..aefc93f624 100644 --- a/types/sinon/ts3.1/index.d.ts +++ b/types/sinon/ts3.1/index.d.ts @@ -1180,7 +1180,7 @@ declare namespace Sinon { * Passes if provided spies were called in the specified order. * @param spies */ - callOrder(...spies: Array>): void; + callOrder(...spies: Array>): void; /** * Passes if spy was ever called with obj as its this value. * It’s possible to assert on a dedicated spy call: sinon.assert.calledOn(spy.firstCall, arg1, arg2, ...);. From e63af8d856a7c09ee8e34e21cdb4fc59a4b843c7 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Thu, 28 Feb 2019 20:51:56 +0100 Subject: [PATCH 6/8] Extract inspectable spy API into own interface --- types/sinon/ts3.1/index.d.ts | 89 ++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/types/sinon/ts3.1/index.d.ts b/types/sinon/ts3.1/index.d.ts index aefc93f624..924fa3936e 100644 --- a/types/sinon/ts3.1/index.d.ts +++ b/types/sinon/ts3.1/index.d.ts @@ -145,7 +145,32 @@ declare namespace Sinon { calledAfter(call: SinonSpyCall): boolean; } - interface SinonSpy + /** + * A test spy is a function that records arguments, return value, + * the value of this and exception thrown (if any) for all its calls. + */ + interface SinonSpy extends SinonInspectable { + // Methods + (...args: TArgs): TReturnValue; + + /** + * Creates a spy that only records calls when the received arguments match those passed to withArgs. + * This is useful to be more expressive in your assertions, where you can access the spy with the same call. + * @param args Expected args + */ + withArgs(...args: MatchArguments): SinonSpy; + + /** + * Set the displayName of the spy or stub. + * @param name + */ + named(name: string): SinonSpy; + } + + /** + * The part of the spy API that allows inspecting the calls made on a spy. + */ + interface SinonInspectable extends Pick< SinonSpyCallApi, Exclude, 'args'> @@ -209,9 +234,6 @@ declare namespace Sinon { * If the call did not explicitly return a value, the value at the call’s location in .returnValues will be undefined. */ returnValues: TReturnValue[]; - - // Methods - (...args: TArgs): TReturnValue; /** * Returns true if the spy was called before @param anotherSpy * @param anotherSpy @@ -232,12 +254,6 @@ declare namespace Sinon { * @param anotherSpy */ calledImmediatelyAfter(anotherSpy: SinonSpy): boolean; - /** - * Creates a spy that only records calls when the received arguments match those passed to withArgs. - * This is useful to be more expressive in your assertions, where you can access the spy with the same call. - * @param args Expected args - */ - withArgs(...args: MatchArguments): SinonSpy; /** * Returns true if the spy was always called with @param obj as this. * @param obj @@ -292,11 +308,6 @@ declare namespace Sinon { * Returns an Array with all callbacks return values in the order they were called, if no error is thrown. */ invokeCallback(...args: TArgs): void; - /** - * Set the displayName of the spy or stub. - * @param name - */ - named(name: string): SinonSpy; /** * Returns the nth call. * Accessing individual calls helps with more detailed behavior verification when the spy is called more than once. @@ -1155,60 +1166,60 @@ declare namespace Sinon { * Passes if spy was never called * @param spy */ - notCalled(spy: SinonSpy): void; + notCalled(spy: SinonInspectable): void; /** * Passes if spy was called at least once. */ - called(spy: SinonSpy): void; + called(spy: SinonInspectable): void; /** * Passes if spy was called once and only once. */ - calledOnce(spy: SinonSpy): void; + calledOnce(spy: SinonInspectable): void; /** * Passes if spy was called exactly twice. */ - calledTwice(spy: SinonSpy): void; + calledTwice(spy: SinonInspectable): void; /** * Passes if spy was called exactly three times. */ - calledThrice(spy: SinonSpy): void; + calledThrice(spy: SinonInspectable): void; /** * Passes if spy was called exactly num times. */ - callCount(spy: SinonSpy, count: number): void; + callCount(spy: SinonInspectable, count: number): void; /** * Passes if provided spies were called in the specified order. * @param spies */ - callOrder(...spies: Array>): void; + callOrder(...spies: Array): void; /** * Passes if spy was ever called with obj as its this value. * It’s possible to assert on a dedicated spy call: sinon.assert.calledOn(spy.firstCall, arg1, arg2, ...);. */ - calledOn(spyOrSpyCall: SinonSpy | SinonSpyCall, obj: any): void; + calledOn(spyOrSpyCall: SinonInspectable | SinonSpyCall, obj: any): void; /** * Passes if spy was always called with obj as its this value. */ - alwaysCalledOn(spy: SinonSpy, obj: any): void; + alwaysCalledOn(spy: SinonInspectable, obj: any): void; /** * Passes if spy was called with the provided arguments. * It’s possible to assert on a dedicated spy call: sinon.assert.calledWith(spy.firstCall, arg1, arg2, ...);. * @param spyOrSpyCall * @param args */ - calledWith(spyOrSpyCall: SinonSpy | SinonSpyCall, ...args: MatchArguments): void; + calledWith(spyOrSpyCall: SinonInspectable | SinonSpyCall, ...args: MatchArguments): void; /** * Passes if spy was always called with the provided arguments. * @param spy * @param args */ - alwaysCalledWith(spy: SinonSpy, ...args: MatchArguments): void; + alwaysCalledWith(spy: SinonInspectable, ...args: MatchArguments): void; /** * Passes if spy was never called with the provided arguments. * @param spy * @param args */ - neverCalledWith(spy: SinonSpy, ...args: MatchArguments): void; + neverCalledWith(spy: SinonInspectable, ...args: MatchArguments): void; /** * Passes if spy was called with the provided arguments and no others. * It’s possible to assert on a dedicated spy call: sinon.assert.calledWithExactly(spy.getCall(1), arg1, arg2, ...);. @@ -1216,68 +1227,68 @@ declare namespace Sinon { * @param args */ calledWithExactly( - spyOrSpyCall: SinonSpy | SinonSpyCall, + spyOrSpyCall: SinonInspectable | SinonSpyCall, ...args: MatchArguments ): void; /** * Passes if spy was always called with the provided arguments and no others. */ - alwaysCalledWithExactly(spy: SinonSpy, ...args: MatchArguments): void; + alwaysCalledWithExactly(spy: SinonInspectable, ...args: MatchArguments): void; /** * Passes if spy was called with matching arguments. * This behaves the same way as sinon.assert.calledWith(spy, sinon.match(arg1), sinon.match(arg2), ...). * It’s possible to assert on a dedicated spy call: sinon.assert.calledWithMatch(spy.secondCall, arg1, arg2, ...);. */ calledWithMatch( - spyOrSpyCall: SinonSpy | SinonSpyCall, + spyOrSpyCall: SinonInspectable | SinonSpyCall, ...args: TArgs ): void; /** * Passes if spy was always called with matching arguments. * This behaves the same way as sinon.assert.alwaysCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...). */ - alwaysCalledWithMatch(spy: SinonSpy, ...args: TArgs): void; + alwaysCalledWithMatch(spy: SinonInspectable, ...args: TArgs): void; /** * Passes if spy was never called with matching arguments. * This behaves the same way as sinon.assert.neverCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...). * @param spy * @param args */ - neverCalledWithMatch(spy: SinonSpy, ...args: TArgs): void; + neverCalledWithMatch(spy: SinonInspectable, ...args: TArgs): void; /** * Passes if spy was called with the new operator. * It’s possible to assert on a dedicated spy call: sinon.assert.calledWithNew(spy.secondCall, arg1, arg2, ...);. * @param spyOrSpyCall */ - calledWithNew(spyOrSpyCall: SinonSpy | SinonSpyCall): void; + calledWithNew(spyOrSpyCall: SinonInspectable | SinonSpyCall): void; /** * Passes if spy threw any exception. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall): void; + threw(spyOrSpyCall: SinonInspectable | SinonSpyCall): void; /** * Passes if spy threw the given exception. * The exception is an actual object. * It’s possible to assert on a dedicated spy call: sinon.assert.threw(spy.thirdCall, exception);. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: string): void; + threw(spyOrSpyCall: SinonInspectable | SinonSpyCall, exception: string): void; /** * Passes if spy threw the given exception. * The exception is a String denoting its type. * It’s possible to assert on a dedicated spy call: sinon.assert.threw(spy.thirdCall, exception);. */ - threw(spyOrSpyCall: SinonSpy | SinonSpyCall, exception: any): void; + threw(spyOrSpyCall: SinonInspectable | SinonSpyCall, exception: any): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy): void; + alwaysThrew(spy: SinonInspectable): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy, exception: string): void; + alwaysThrew(spy: SinonInspectable, exception: string): void; /** * Like threw, only required for all calls to the spy. */ - alwaysThrew(spy: SinonSpy, exception: any): void; + alwaysThrew(spy: SinonInspectable, exception: any): void; /** * Uses sinon.match to test if the arguments can be considered a match. */ From 292e70357c273919f9c1aaa4fb2ae55d2ea08ff7 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Thu, 28 Feb 2019 21:52:39 +0100 Subject: [PATCH 7/8] Fix TSLint --- types/sinon/ts3.1/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/sinon/ts3.1/index.d.ts b/types/sinon/ts3.1/index.d.ts index 924fa3936e..4f5a23d450 100644 --- a/types/sinon/ts3.1/index.d.ts +++ b/types/sinon/ts3.1/index.d.ts @@ -1191,7 +1191,7 @@ declare namespace Sinon { * Passes if provided spies were called in the specified order. * @param spies */ - callOrder(...spies: Array): void; + callOrder(...spies: SinonInspectable[]): void; /** * Passes if spy was ever called with obj as its this value. * It’s possible to assert on a dedicated spy call: sinon.assert.calledOn(spy.firstCall, arg1, arg2, ...);. From 345ccdbe9e39f149e2f9684eb233b52e0cb306f2 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Thu, 28 Feb 2019 23:38:54 +0100 Subject: [PATCH 8/8] Fix wrong test https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33223/files#r261413058 --- types/sinon/ts3.1/index.d.ts | 2 +- types/sinon/ts3.1/sinon-tests.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/types/sinon/ts3.1/index.d.ts b/types/sinon/ts3.1/index.d.ts index ccd9289ba3..80ec4ee483 100644 --- a/types/sinon/ts3.1/index.d.ts +++ b/types/sinon/ts3.1/index.d.ts @@ -1725,7 +1725,7 @@ declare namespace Sinon { createStubInstance( constructor: StubbableType, overrides?: { [K in keyof TType]?: - SinonStubbedMember | TType[K] extends (...args: any[]) => infer R ? R : TType[K] } + SinonStubbedMember | (TType[K] extends (...args: any[]) => infer R ? R : TType[K]) } ): SinonStubbedInstance; } diff --git a/types/sinon/ts3.1/sinon-tests.ts b/types/sinon/ts3.1/sinon-tests.ts index 24eb5b12b7..a2f8a393d8 100644 --- a/types/sinon/ts3.1/sinon-tests.ts +++ b/types/sinon/ts3.1/sinon-tests.ts @@ -89,9 +89,12 @@ function testSandbox() { const clsBar: number = stubInstance.bar; const privateFooBar: number = privateFooStubbedInstance.bar; sb.createStubInstance(cls, { - foo: (arg1: string, arg2: number) => 2, + foo: sinon.stub<[string, number], number>().returns(1), bar: 1 }); + sb.createStubInstance(cls, { + foo: 1, // used as return value + }); } function testFakeServer() {