sinon: 5.x release and cleanup (#25491)

* sinon: cleanup types and rewrite tests

* Used a conditional type for Sinon's stub class typings  (#25656)

* Used a conditional type for Sinon's stub class typings

* mochaccino

* sinon: fix some whitespace

* sinon: stub/spy test case

* sinon: cleanup mixed indent
This commit is contained in:
James Garbutt
2018-05-24 16:03:23 +01:00
committed by Andy
parent 25916bc288
commit 73f6eb2bca
13 changed files with 556 additions and 438 deletions

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/tubalmartin/karma-chai-sinon
// Definitions by: Václav Ostrožlík <https://github.com/vasek17>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
/// <reference types="chai" />
import Sinon = require("sinon");

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/pawelgalazka/mochaccino#readme
// Definitions by: Thomas-P <https://github.com/thomas-p>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
import * as Sinon from "sinon";
export interface Expect {
not: Expect;

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/shouldjs/sinon
// Definitions by: AryloYeung <https://github.com/Arylo>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
import * as s from "sinon";
import should = require("should");

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/bendrucker/sinon-as-promised
// Definitions by: igrayson <https://github.com/igrayson>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
import * as s from "sinon";

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/domenic/sinon-chai
// Definitions by: Kazi Manzur Rashid <https://github.com/kazimanzurrashid>, Jed Mao <https://github.com/jedmao>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
/// <reference types="chai" />
/// <reference types="sinon" />

View File

@@ -4,7 +4,7 @@
// CRIMX <https://github.com/crimx>
// kobanyan <https://github.com/kobanyan>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.4
// TypeScript Version: 2.8
/// <reference types="chrome"/>
/// <reference types="sinon"/>

View File

@@ -3,7 +3,7 @@
// Definitions by: Jared Chapiewsky <https://github.com/jpchip>
// Tomek Łaziuk <https://github.com/tlaziuk>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
import {
SinonStub,

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/underscopeio/sinon-mongoose
// Definitions by: stevehipwell <https://github.com/stevehipwell>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
import * as s from "sinon";

View File

@@ -3,7 +3,7 @@
// Definitions by: Thiago Temple <https://github.com/vintem>
// Tim Stackhouse <https://github.com/tstackhouse>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
/// <reference types="sinon"/>

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/sinonjs/sinon-test
// Definitions by: Francis Saul <https://github.com/mummybot>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
import * as Sinon from 'sinon';

291
types/sinon/index.d.ts vendored
View File

@@ -1,12 +1,13 @@
// Type definitions for Sinon 4.3
// Type definitions for Sinon 5.0
// Project: http://sinonjs.org/
// Definitions by: William Sears <https://github.com/mrbigdog2u>
// Jonathan Little <https://github.com/rationull>
// Lukas Spieß <https://github.com/lumaxis>
// Nico Jansen <https://github.com/nicojs>
// James Garbutt <https://github.com/43081j>
// Josh Goldberg <https://github.com/joshuakgoldberg>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.8
// sinon uses DOM dependencies which are absent in browser-less environment like node.js
// to avoid compiler errors this monkey patch is used
@@ -17,15 +18,13 @@ interface Document { } // tslint:disable-line no-empty-interface
declare namespace Sinon {
interface SinonSpyCallApi {
// Properties
thisValue: any;
args: any[];
exception: any;
returnValue: any;
// Methods
calledOn(obj: any): boolean;
calledWith(...args: any[]): boolean;
calledWithExactly(...args: any[]): boolean;
calledWithNew(): boolean;
calledOnceWith(...args: any[]): boolean;
calledOnceWithExactly(...args: any[]): boolean;
calledWithMatch(...args: any[]): boolean;
@@ -46,9 +45,14 @@ declare namespace Sinon {
}
interface SinonSpyCall extends SinonSpyCallApi {
thisValue: any;
exception: any;
returnValue: any;
callback: Function | undefined;
lastArg: any;
calledBefore(call: SinonSpyCall): boolean;
calledAfter(call: SinonSpyCall): boolean;
calledWithNew(call: SinonSpyCall): boolean;
}
interface SinonSpy extends SinonSpyCallApi {
@@ -74,7 +78,6 @@ declare namespace Sinon {
calledAfter(anotherSpy: SinonSpy): boolean;
calledImmediatelyBefore(anotherSpy: SinonSpy): boolean;
calledImmediatelyAfter(anotherSpy: SinonSpy): boolean;
calledWithNew(): boolean;
withArgs(...args: any[]): SinonSpy;
alwaysCalledOn(obj: any): boolean;
alwaysCalledWith(...args: any[]): boolean;
@@ -89,8 +92,6 @@ declare namespace Sinon {
invokeCallback(...args: any[]): void;
getCall(n: number): SinonSpyCall;
getCalls(): SinonSpyCall[];
/// @deprecated Use resetHistory() instead
reset(): void;
resetHistory(): void;
printf(format: string, ...args: any[]): string;
restore(): void;
@@ -102,13 +103,9 @@ declare namespace Sinon {
<T>(obj: T, method: keyof T): SinonSpy;
}
interface SinonStatic {
spy: SinonSpyStatic;
}
interface SinonStub extends SinonSpy {
resetBehavior(): void;
resetHistory(): void;
reset(): void;
usingPromise(promiseLibrary: any): SinonStub;
returns(obj: any): SinonStub;
@@ -132,7 +129,7 @@ declare namespace Sinon {
callsArgOnAsync(index: number, context: any): SinonStub;
callsArgWithAsync(index: number, ...args: any[]): SinonStub;
callsArgOnWithAsync(index: number, context: any, ...args: any[]): SinonStub;
callsFake(func: (...args: any[]) => void): SinonStub;
callsFake(func: (...args: any[]) => any): SinonStub;
get(func: () => any): SinonStub;
set(func: (v: any) => void): SinonStub;
onCall(n: number): SinonStub;
@@ -156,11 +153,6 @@ declare namespace Sinon {
(): SinonStub;
<T>(obj: T): SinonStubbedInstance<T>;
<T>(obj: T, method: keyof T): SinonStub;
<T>(obj: T, method: keyof T, func: Function): SinonStub;
}
interface SinonStatic {
stub: SinonStubStatic;
}
interface SinonExpectation extends SinonStub {
@@ -193,23 +185,29 @@ declare namespace Sinon {
(obj: any): SinonMock;
}
interface SinonStatic {
expectation: SinonExpectationStatic;
mock: SinonMockStatic;
}
type SinonTimerId = number | { id: number };
interface SinonFakeTimers {
now: number;
create(now: number): SinonFakeTimers;
setTimeout(callback: (...args: any[]) => void, timeout: number, ...args: any[]): number;
clearTimeout(id: number): void;
setInterval(callback: (...args: any[]) => void, timeout: number, ...args: any[]): number;
clearInterval(id: number): void;
tick(ms: number): number;
setTimeout(callback: (...args: any[]) => void, timeout: number, ...args: any[]): SinonTimerId;
clearTimeout(id: SinonTimerId): void;
setInterval(callback: (...args: any[]) => void, timeout: number, ...args: any[]): SinonTimerId;
clearInterval(id: SinonTimerId): void;
setImmediate(callback: (...args: any[]) => void, ...args: any[]): SinonTimerId;
clearImmediate(id: SinonTimerId): void;
requestAnimationFrame(callback: (...args: any[]) => void): number;
cancelAnimationFrame(id: number): void;
nextTick(callback: () => void): void;
tick(ms: number | string): void;
next(): void;
runAll(): void;
runToLast(): void;
reset(): void;
runMicrotasks(): void;
runToFrame(): void;
Date(): Date;
Date(year: number): Date;
Date(year: number, month: number): Date;
@@ -218,7 +216,9 @@ declare namespace Sinon {
Date(year: number, month: number, day: number, hour: number, minute: number): Date;
Date(year: number, month: number, day: number, hour: number, minute: number, second: number): Date;
Date(year: number, month: number, day: number, hour: number, minute: number, second: number, ms: number): Date;
restore(): void;
uninstall(): void;
/**
* Simulate the user changing the system clock while your program is running. It changes the 'now' timestamp
@@ -240,16 +240,6 @@ declare namespace Sinon {
shouldAdvanceTime: boolean;
}
interface SinonFakeTimersStatic {
(now?: number | Date): SinonFakeTimers;
(config?: Partial<SinonFakeTimersConfig>): SinonFakeTimers;
}
interface SinonStatic {
useFakeTimers: SinonFakeTimersStatic;
clock: SinonFakeTimers;
}
interface SinonFakeUploadProgress {
eventListeners: {
progress: any[];
@@ -265,7 +255,6 @@ declare namespace Sinon {
interface SinonFakeXMLHttpRequest {
// Properties
onCreate(xhr: SinonFakeXMLHttpRequest): void;
url: string;
method: string;
requestHeaders: any;
@@ -283,8 +272,6 @@ declare namespace Sinon {
// Methods
restore(): void;
useFilters: boolean;
addFilter(filter: (method: string, url: string, async: boolean, username: string, password: string) => boolean): void;
setResponseHeaders(headers: any): void;
setResponseBody(body: string): void;
respond(status: number, headers: any, body: string): void;
@@ -293,11 +280,11 @@ declare namespace Sinon {
onerror(): void;
}
type SinonFakeXMLHttpRequestStatic = () => SinonFakeXMLHttpRequest;
interface SinonStatic {
useFakeXMLHttpRequest: SinonFakeXMLHttpRequestStatic;
FakeXMLHttpRequest: SinonFakeXMLHttpRequest;
interface SinonFakeXMLHttpRequestStatic {
new(): SinonFakeXMLHttpRequest;
useFilters: boolean;
addFilter(filter: (method: string, url: string, async: boolean, username: string, password: string) => boolean): void;
onCreate(xhr: SinonFakeXMLHttpRequest): void;
}
interface SinonFakeServer extends SinonFakeServerOptions {
@@ -326,24 +313,19 @@ declare namespace Sinon {
}
interface SinonFakeServerOptions {
autoRespond?: boolean;
autoRespondAfter?: number;
fakeHTTPMethods?: boolean;
respondImmediately?: boolean;
autoRespond: boolean;
autoRespondAfter: number;
fakeHTTPMethods: boolean;
respondImmediately: boolean;
}
interface SinonFakeServerStatic {
create(options?: SinonFakeServerOptions): SinonFakeServer;
}
interface SinonStatic {
fakeServer: SinonFakeServerStatic;
fakeServerWithClock: SinonFakeServerStatic;
create(options?: Partial<SinonFakeServerOptions>): SinonFakeServer;
}
interface SinonExposeOptions {
prefix?: string;
includeFail?: boolean;
prefix: string;
includeFail: boolean;
}
interface SinonAssert {
@@ -378,16 +360,13 @@ declare namespace Sinon {
alwaysThrew(spy: SinonSpy, exception: string): void;
alwaysThrew(spy: SinonSpy, exception: any): void;
match(actual: any, expected: any): void;
expose(obj: any, options?: SinonExposeOptions): void;
}
interface SinonStatic {
assert: SinonAssert;
expose(obj: any, options?: Partial<SinonExposeOptions>): void;
}
interface SinonMatcher {
and(expr: SinonMatcher): SinonMatcher;
or(expr: SinonMatcher): SinonMatcher;
test(val: any): boolean;
}
interface SinonArrayMatcher extends SinonMatcher {
@@ -443,8 +422,8 @@ declare namespace Sinon {
(value: number): SinonMatcher;
(value: string): SinonMatcher;
(expr: RegExp): SinonMatcher;
(obj: any): SinonMatcher;
(callback: (value: any) => boolean, message?: string): SinonMatcher;
(obj: object): SinonMatcher;
any: SinonMatcher;
defined: SinonMatcher;
truthy: SinonMatcher;
@@ -474,86 +453,16 @@ declare namespace Sinon {
instanceOf(type: any): SinonMatcher;
has(property: string, expect?: any): SinonMatcher;
hasOwn(property: string, expect?: any): SinonMatcher;
}
interface SinonStatic {
match: SinonMatch;
hasNested(path: string, expect?: any): SinonMatcher;
every(matcher: SinonMatcher): SinonMatcher;
some(matcher: SinonMatcher): SinonMatcher;
}
interface SinonSandboxConfig {
injectInto?: any;
properties?: string[];
useFakeTimers?: any;
useFakeServer?: any;
}
interface SinonSandbox {
assert: SinonAssert;
clock: SinonFakeTimers;
requests: SinonFakeXMLHttpRequest;
server: SinonFakeServer;
spy: SinonSpyStatic;
stub: SinonStubStatic;
mock: SinonMockStatic;
useFakeTimers: SinonFakeTimersStatic;
useFakeXMLHttpRequest: SinonFakeXMLHttpRequestStatic;
useFakeServer(): SinonFakeServer;
restore(): void;
reset(): void;
resetHistory(): void;
resetBehavior(): void;
usingPromise(promiseLibrary: any): SinonSandbox;
verify(): void;
verifyAndRestore(): void;
createStubInstance(constructor: any): any;
createStubInstance<TType>(constructor: StubbableType<TType>): SinonStubbedInstance<TType>;
}
interface SinonSandboxStatic {
create(config?: SinonSandboxConfig): SinonSandbox;
}
interface SinonStatic {
createSandbox(config?: SinonSandboxConfig): SinonSandbox;
defaultConfig: SinonSandboxConfig;
sandbox: SinonSandboxStatic;
}
interface SinonTestConfig {
injectIntoThis?: boolean;
injectInto?: any;
properties?: string[];
useFakeTimers?: boolean;
useFakeServer?: boolean;
}
interface SinonTestWrapper extends SinonSandbox {
(...args: any[]): any;
}
// Utility overridables
interface SinonStatic {
/**
* Creates a new object with the given functions as the prototype and stubs all implemented functions.
*
* @param constructor Object or class to stub.
* @returns A stubbed version of the constructor.
* @remarks The given constructor function is not invoked. See also the stub API.
*/
createStubInstance(constructor: any): any;
/**
* Creates a new object with the given functions as the prototype and stubs all implemented functions.
*
* @template TType Type being stubbed.
* @param constructor Object or class to stub.
* @returns A stubbed version of the constructor.
* @remarks The given constructor function is not invoked. See also the stub API.
*/
createStubInstance<TType>(constructor: StubbableType<TType>): SinonStubbedInstance<TType>;
format(obj: any): string;
restore(object: any): void;
injectInto: object | null;
properties: string[];
useFakeTimers: boolean | Partial<SinonFakeTimersConfig>;
useFakeServer: boolean | SinonFakeServer;
}
/**
@@ -566,15 +475,103 @@ declare namespace Sinon {
}
/**
* An instance of a stubbed object type with members replaced by stubs.
* An instance of a stubbed object type with functions replaced by stubs.
*
* @template TType Object type being stubbed.
*/
type SinonStubbedInstance<TType> = {
// TODO: this should really only replace functions on TType with SinonStubs, not all properties
// Likely infeasible without mapped conditional types, per https://github.com/Microsoft/TypeScript/issues/12424
[P in keyof TType]: SinonStub;
[P in keyof TType]: SinonStubbedMember<TType[P]>;
};
/**
* Replaces a type with a Sinon stub if it's a function.
*/
type SinonStubbedMember<T> = T extends Function ? SinonStub : T;
interface SinonFake {
(): SinonSpy;
(fn: Function): SinonSpy;
returns(val: any): SinonSpy;
throws(val: Error | string): SinonSpy;
resolves(val: any): SinonSpy;
rejects(val: any): SinonSpy;
yields(...args: any[]): SinonSpy;
yieldsAsync(...args: any[]): SinonSpy;
}
interface SinonSandbox {
assert: SinonAssert;
clock: SinonFakeTimers;
requests: SinonFakeXMLHttpRequest[];
server: SinonFakeServer;
spy: SinonSpyStatic;
stub: SinonStubStatic;
mock: SinonMockStatic;
useFakeTimers(config?: number | Date | Partial<SinonFakeTimersConfig>): SinonFakeTimers;
useFakeXMLHttpRequest(): SinonFakeXMLHttpRequestStatic;
useFakeServer(): SinonFakeServer;
restore(): void;
reset(): void;
resetHistory(): void;
resetBehavior(): void;
usingPromise(promiseLibrary: any): SinonSandbox;
verify(): void;
verifyAndRestore(): void;
replace<T, TKey extends keyof T>(
obj: T,
prop: TKey,
replacement: T[TKey]): T[TKey];
replaceGetter<T, TKey extends keyof T>(
obj: T,
prop: TKey,
replacement: () => T[TKey]): () => T[TKey];
replaceSetter<T, TKey extends keyof T>(
obj: T,
prop: TKey,
replacement: (val: T[TKey]) => void): (val: T[TKey]) => void;
/**
* Creates a new object with the given functions as the prototype and stubs all implemented functions.
*
* @template TType Type being stubbed.
* @param constructor Object or class to stub.
* @returns A stubbed version of the constructor.
* @remarks The given constructor function is not invoked. See also the stub API.
*/
createStubInstance<TType>(constructor: StubbableType<TType>): SinonStubbedInstance<TType>;
}
interface SinonApi {
fake: SinonFake;
match: SinonMatch;
spyCall(...args: any[]): SinonSpyCall;
expectation: SinonExpectationStatic;
clock: {
create(now: number | Date): SinonFakeTimers;
};
FakeXMLHttpRequest: SinonFakeXMLHttpRequestStatic;
fakeServer: SinonFakeServerStatic;
fakeServerWithClock: SinonFakeServerStatic;
createSandbox(config?: Partial<SinonSandboxConfig>): SinonSandbox;
defaultConfig: Partial<SinonSandboxConfig>;
}
interface LegacySandbox {
sandbox: {
/**
* @deprecated Since 5.0, use `sinon.createSandbox` instead
*/
create(config?: Partial<SinonSandboxConfig>): SinonSandbox;
};
}
type SinonStatic = SinonSandbox & LegacySandbox & SinonApi;
}
declare const Sinon: Sinon.SinonStatic;

View File

@@ -1,317 +1,437 @@
import sinon = require("sinon");
function once(fn: Function) {
let called = false;
let returnValue: any;
return function(this: any) {
if (!called) {
called = true;
returnValue = fn.apply(this, arguments);
}
return returnValue;
};
}
function testOne() {
const callback = sinon.spy();
const proxy = once(callback);
proxy();
if (callback.calledOnce) { console.log("test1 calledOnce success"); } else { console.log("test1 calledOnce failure"); }
}
function testTwo() {
const callback = sinon.spy(() => { });
const proxy = once(callback);
proxy();
proxy();
if (callback.calledOnce) { console.log("test2 calledOnce success"); } else { console.log("test2 calledOnce failure"); }
}
function testThree() {
const obj = { thisObj: true };
const callback = sinon.spy<any>({}, "method");
const proxy = once(callback);
proxy.call(obj, callback, 1, 2, 3);
if (callback.calledOn(obj)) { console.log("test3 calledOn success"); } else { console.log("test3 calledOn failure"); }
if (callback.calledWith(callback, 1, 2, 3)) { console.log("test3 calledWith success"); } else { console.log("test3 calledWith failure"); }
}
function testFour() {
const callback = sinon.stub().returns(42);
const proxy = once(callback);
const val = proxy.apply(callback, [1, 2, 3]);
if (val === 42) { console.log("test4 returns success"); } else { console.log("test4 returns failure"); }
}
function testFive() {
const callback = sinon.stub().returnsArg(1);
const proxy = once(callback);
const val = proxy.apply(callback, [1, 2, 3]);
if (val === 2) { console.log("test5 returnsArg success"); } else { console.log("test5 returnsArg failure"); }
}
const objectUnderTest: any = {
process: (obj: any) => {
// It doesn't really matter what's here because the stub is going to replace this function
return obj.success(99);
}
};
function testSix() {
const stub = sinon.stub(objectUnderTest, "process").yieldsTo("success");
objectUnderTest.process({
success: () => { console.log("test6 yieldsTo success"); },
failure: () => { console.log("test6 yieldsTo failure"); }
});
stub.restore();
}
function testSeven() {
const obj = { functionToTest: () => { } };
const mockObj = sinon.mock(obj);
obj.functionToTest();
mockObj.expects('functionToTest').once();
}
function testEight() {
sinon.match.typeOf("object").and(sinon.match.has("pages"));
}
function testNine() {
const callback = sinon.stub().returns(42);
callback({ x: 5, y: 5 });
callback.calledWithMatch({ x: 5 });
callback.alwaysCalledWithMatch({ y: 5 });
callback.neverCalledWithMatch({ x: 6 });
callback.notCalledWithMatch({ x: 6 });
callback.calledOnceWith({ x: 5, y: 5 });
callback.calledOnceWithExactly({ x: 5, y: 5 });
sinon.assert.calledWithMatch(callback, { x: 5 });
sinon.assert.alwaysCalledWithMatch(callback, { y: 5 });
sinon.assert.neverCalledWithMatch(callback, { x: 6 });
callback.call("this", "that");
callback.throws("Error");
try {
callback(15);
} catch (e) { }
sinon.assert.calledWith(callback.firstCall, { x: 5, y: 5});
sinon.assert.calledWithExactly(callback.firstCall, { x: 5, y: 5 });
sinon.assert.calledWithMatch(callback.firstCall, { x: 5 });
sinon.assert.calledOn(callback.secondCall, "this");
sinon.assert.threw(callback.thirdCall);
sinon.assert.threw(callback.thirdCall, "Error");
new (callback as any)();
sinon.assert.calledWithNew(callback);
sinon.assert.calledWithNew(callback.getCall(4));
}
function testAssert() {
sinon.assert.match(1, 1 + 1);
sinon.assert.match("abc", "abc");
sinon.assert.match({ a: 1 }, { b: 2, c: "abc" });
}
function testSandbox() {
const config = {
injectInto: null,
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
useFakeServer: true,
const obj = {};
sinon.createSandbox({
injectInto: obj,
properties: ['spy', 'stub'],
useFakeTimers: true,
};
let sandbox = sinon.sandbox.create();
sandbox = sinon.sandbox.create(config);
sandbox = sinon.sandbox.create(sinon.defaultConfig);
sandbox = sinon.createSandbox();
sandbox = sinon.createSandbox(config);
sandbox = sinon.createSandbox(sinon.defaultConfig);
sandbox = sandbox.usingPromise(Promise);
sandbox.assert.notCalled(sinon.spy());
if (sandbox.spy().called) {
sandbox.stub(objectUnderTest, "process").yieldsTo("success");
sandbox.mock(objectUnderTest).expects("process").once();
}
sandbox.useFakeTimers();
sandbox.useFakeTimers({
now: 1,
toFake: ['Date']
useFakeServer: true
});
sandbox.useFakeXMLHttpRequest();
sandbox.useFakeServer();
sandbox.restore();
sandbox.reset();
sandbox.resetHistory();
sandbox.resetBehavior();
sandbox.verify();
sandbox.verifyAndRestore();
sandbox.createStubInstance(TestCreateStubInstance).someTestMethod('some argument');
sandbox.createStubInstance<TestCreateStubInstance>(TestCreateStubInstance).someTestMethod('some argument');
}
sinon.createSandbox({
injectInto: null
});
sinon.createSandbox({
useFakeTimers: {
now: 1000,
shouldAdvanceTime: false
},
useFakeServer: sinon.fakeServer.create()
});
sinon.createSandbox(sinon.defaultConfig);
sinon.sandbox.create();
sinon.sandbox.create(sinon.defaultConfig);
function testPromises() {
let resolveStub = sinon.stub().resolves();
resolveStub = sinon.stub().resolves(10);
const rejectStub1 = sinon.stub().rejects();
let rejectsStub2 = sinon.stub().rejects(new Error('Specified error'));
rejectsStub2 = sinon.stub().rejects("TypeError");
}
const sb = sinon.createSandbox();
function testMatchInvoke() {
const stub = sinon.stub();
stub(123);
stub.calledWithMatch(sinon.match(123));
stub.calledWithMatch(sinon.match((value: any) => value === 123));
stub.calledWithMatch(sinon.match((value: any) => value === 123, "Must be 123"));
}
sb.assert.pass('foo');
sb.clock.tick(1000);
sb.spy();
sb.stub();
sb.mock(obj);
function testSymbolMatch() {
const stub = sinon.stub();
stub(Symbol('TestSymbol'));
stub.calledWithMatch(sinon.match.symbol);
}
sb.useFakeTimers();
sb.useFakeTimers(1000);
sb.useFakeTimers(new Date());
sb.useFakeTimers({
now: 1000
});
function testResetHistory() {
sinon.stub().resetHistory();
sinon.spy().resetHistory();
}
const xhr = sb.useFakeXMLHttpRequest();
xhr.useFilters = true;
function testUsingPromises() {
const stub: sinon.SinonStub = sinon.stub().usingPromise(Promise);
}
const server = sb.useFakeServer();
server.respondWith('foo');
function testArrayMatchers() {
const stub = sinon.stub();
stub([{ a: 'b' }]);
stub.calledWithMatch(sinon.match.array);
stub.calledWithMatch(sinon.match.array.deepEquals([{ a: 'b' }]));
stub.calledWithMatch(sinon.match.array.startsWith([{ a: 'b' }]));
stub.calledWithMatch(sinon.match.array.deepEquals([{ a: 'b' }]));
stub.calledWithMatch(sinon.match.array.contains([{ a: 'b' }]));
}
sb.restore();
sb.reset();
sb.resetHistory();
sb.resetBehavior();
sb.usingPromise(Promise);
sb.verify();
sb.verifyAndRestore();
function testMapMatcher() {
const stub = sinon.stub();
stub(new Map([['a', true], ['b', false]]));
stub.calledWithMatch(sinon.match.map);
stub.calledWithMatch(sinon.match.map.deepEquals(new Map([['a', true], ['b', false]])));
stub.calledWithMatch(sinon.match.map.contains(new Map([['a', true]])));
}
function testSetMatcher() {
const stub = sinon.stub();
stub(new Set(['a', true]));
stub.calledWithMatch(sinon.match.set);
stub.calledWithMatch(sinon.match.set.deepEquals(new Set(['a', true])));
stub.calledWithMatch(sinon.match.set.contains(new Set([true])));
}
function testGetterStub() {
const myObj = {
prop: 'foo'
const replaceMe = {
prop: 5,
method() { return 6; },
get getter() { return 7; },
get setter() { return true; },
set setter(val) { }
};
const stub = sinon.stub(myObj, 'prop').get(() => 'bar');
stub.restore();
}
sb.replace(replaceMe, 'prop', 10);
sb.replace(replaceMe, 'method', sb.spy());
sb.replaceGetter(replaceMe, 'getter', () => 14);
sb.replaceSetter(replaceMe, 'setter', (v) => { });
function testSetterStub() {
const myObj = {
prop: 'foo',
prop2: 'bar'
const cls = class {
foo() {}
bar: number;
};
const stub = sinon.stub(myObj, 'prop').set((val: string) => myObj.prop2 = val);
stub.restore();
}
function testValueStub() {
const myObj = {
prop: 'foo'
};
const stub = sinon.stub(myObj, 'prop').value('bar');
stub.restore();
}
function testThrowsStub() {
sinon.stub().throws(new Error('foo'));
sinon.stub().throwsException(new Error('foo'));
sinon.stub().throws('foo');
sinon.stub().throwsException('foo');
}
function testSpy() {
const otherSpy = sinon.spy();
sinon.spy().calledAfter(otherSpy);
sinon.spy().calledBefore(otherSpy);
sinon.spy().calledImmediatelyAfter(otherSpy);
sinon.spy().calledImmediatelyBefore(otherSpy);
const stubInstance = sb.createStubInstance(cls);
stubInstance.foo.calledWith('foo');
const clsFoo: sinon.SinonStub = stubInstance.foo;
const clsBar: number = stubInstance.bar;
}
function testFakeServer() {
let s = sinon.fakeServer.create();
s = sinon.fakeServerWithClock.create();
sinon.fakeServer.create({
autoRespond: true,
autoRespondAfter: 3,
fakeHTTPMethods: true,
respondImmediately: false
});
sinon.fakeServer.create({
autoRespond: true,
autoRespondAfter: 3
});
}
function testStubObject() {
const myObj = {
setStatus() {},
json() {}
function testXHR() {
const xhr = new sinon.FakeXMLHttpRequest();
const headers = xhr.getAllResponseHeaders();
const header = xhr.getResponseHeader('foo');
xhr.restore();
xhr.setResponseHeaders({ 'Content-Type': 'text/html' });
xhr.setResponseBody('foo');
xhr.respond(200, { 'Content-Type': 'foo' }, 'bar');
xhr.error();
sinon.FakeXMLHttpRequest.useFilters = true;
sinon.FakeXMLHttpRequest.addFilter((method, url, async, user, pass) => true);
sinon.FakeXMLHttpRequest.onCreate = (xhr) => {};
}
function testClock() {
let clock = sinon.clock.create(1000);
clock = sinon.clock.create(new Date());
let now = 0;
now = clock.now;
const fn = () => {};
clock.setTimeout(fn, 0);
clock.setTimeout(fn, 0, 'a', 'b');
clock.setInterval(fn, 0);
clock.setInterval(fn, 0, 'a', 'b');
clock.setImmediate(fn);
clock.setImmediate(fn, 'a', 'b');
clock.requestAnimationFrame(fn);
let timer = clock.setTimeout(fn, 0);
clock.clearTimeout(timer);
timer = clock.setInterval(fn, 0);
clock.clearInterval(timer);
timer = clock.setImmediate(fn);
clock.clearImmediate(timer);
const animTimer = clock.requestAnimationFrame(fn);
clock.cancelAnimationFrame(animTimer);
clock.nextTick(fn);
clock.tick(1);
clock.tick('00:10');
clock.next();
clock.runAll();
clock.runToLast();
clock.reset();
clock.runMicrotasks();
clock.runToFrame();
clock.restore();
clock.uninstall();
clock.setSystemTime(1000);
clock.setSystemTime(new Date());
}
function testExpectation() {
const obj = {};
let ex = sinon.expectation.create();
ex = sinon.expectation.create('some name');
ex.atLeast(5).atMost(10);
ex.never();
ex.once();
ex.twice();
ex.thrice();
ex.exactly(5);
ex.withArgs('a', 'b');
ex.withExactArgs('a', 'b');
ex.on(obj);
ex.verify();
ex.restore();
}
function testMatch() {
const obj = {};
const fn = () => {};
sinon.match(5).test(5);
sinon.match('str').test('foo');
sinon.match(/foo/).test('foo');
sinon.match({ a: 5, b: 6 }).test({});
sinon.match((v) => true).test('foo');
sinon.match((v) => true, 'some message').test('foo');
sinon.match.any.test('foo');
sinon.match.defined.test('foo');
sinon.match.truthy.test('foo');
sinon.match.falsy.test('foo');
sinon.match.bool.test('foo');
sinon.match.number.test('foo');
sinon.match.string.test('foo');
sinon.match.object.test('foo');
sinon.match.func.test(fn);
sinon.match.map.test(new Map([['a', 1], ['b', 2]]));
sinon.match.set.test(new Set([1, 2, 3]));
sinon.match.array.test([1, 2, 3]);
sinon.match.regexp.test('foo');
sinon.match.date.test('foo');
sinon.match.symbol.test('foo');
sinon.match.same(obj);
sinon.match.typeOf('string').test('foo');
sinon.match.instanceOf(fn).test('foo');
sinon.match.has('prop').test(obj);
sinon.match.has('prop', 123).test(obj);
sinon.match.hasOwn('prop').test(obj);
sinon.match.hasOwn('prop', 123).test(obj);
sinon.match.hasNested('prop.foo.bar').test(obj);
sinon.match.hasNested('prop.foo.bar', 123).test(obj);
sinon.match.every(sinon.match.number).test([1, 2, 'three']);
sinon.match.some(sinon.match.number).test([1, 2, 'three']);
sinon.match.array.deepEquals([{ a: 'b' }]).test([]);
sinon.match.array.startsWith([{ a: 'b' }]).test([]);
sinon.match.array.deepEquals([{ a: 'b' }]).test([]);
sinon.match.array.contains([{ a: 'b' }]).test([]);
sinon.match.map.deepEquals(new Map([['a', true], ['b', false]])).test(new Map());
sinon.match.map.contains(new Map([['a', true]])).test(new Map());
}
function testFake() {
const fn = () => {};
let fake = sinon.fake();
fake = sinon.fake(() => true);
fake = sinon.fake.returns(5);
fake = sinon.fake.throws('foo');
fake = sinon.fake.throws(new Error('foo'));
fake = sinon.fake.resolves('foo');
fake = sinon.fake.rejects('foo');
fake = sinon.fake.yields(1, 2, fn);
fake = sinon.fake.yieldsAsync(1, 2, fn);
fake.calledWith('foo');
}
function testAssert() {
const spy = sinon.spy();
const spyTwo = sinon.spy();
const obj = {};
sinon.assert.fail();
sinon.assert.fail('foo');
sinon.assert.pass('foo');
sinon.assert.notCalled(spy);
sinon.assert.called(spy);
sinon.assert.calledOnce(spy);
sinon.assert.calledTwice(spy);
sinon.assert.calledThrice(spy);
sinon.assert.callCount(spy, 3);
sinon.assert.callOrder(spy, spyTwo);
sinon.assert.calledOn(spy, obj);
sinon.assert.calledOn(spy.firstCall, obj);
sinon.assert.alwaysCalledOn(spy, obj);
sinon.assert.alwaysCalledWith(spy, 'a', 'b', 'c');
sinon.assert.neverCalledWith(spy, 'a', 'b', 'c');
sinon.assert.calledWithExactly(spy, 'a', 'b', 'c');
sinon.assert.alwaysCalledWithExactly(spy, 'a', 'b', 'c');
sinon.assert.calledWithMatch(spy, 'a', 'b', 'c');
sinon.assert.calledWithMatch(spy.firstCall, 'a', 'b', 'c');
sinon.assert.alwaysCalledWithMatch(spy, 'a', 'b', 'c');
sinon.assert.neverCalledWithMatch(spy, 'a', 'b', 'c');
sinon.assert.calledWithNew(spy);
sinon.assert.calledWithNew(spy.firstCall);
sinon.assert.threw(spy);
sinon.assert.threw(spy.firstCall);
sinon.assert.threw(spy, 'foo error');
sinon.assert.threw(spy.firstCall, 'foo error');
sinon.assert.threw(spy, new Error('foo'));
sinon.assert.threw(spy.firstCall, new Error('foo'));
sinon.assert.alwaysThrew(spy);
sinon.assert.alwaysThrew(spy, 'foo error');
sinon.assert.alwaysThrew(spy, 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 testSpy() {
const fn = () => {};
const obj = class {
foo() {}
};
const stub = sinon.stub(myObj);
stub.setStatus.returns(stub);
stub.json.callCount;
const instance = new obj();
let spy = sinon.spy();
const spyTwo = sinon.spy();
spy = sinon.spy(fn);
spy = sinon.spy(instance, 'foo');
let count = 0;
count = spy.callCount;
let called = false;
called = spy.called;
called = spy.notCalled;
called = spy.calledOnce;
called = spy.calledTwice;
called = spy.calledThrice;
let arr: any[] = [];
arr = spy.thisValues;
arr = spy.args;
arr = spy.exceptions;
arr = spy.returnValues;
spy('a', 'b');
spy(1, 2);
spy(true);
spy.calledBefore(spyTwo);
spy.calledAfter(spyTwo);
spy.calledImmediatelyBefore(spyTwo);
spy.calledImmediatelyAfter(spyTwo);
spy.calledWithNew();
spy.withArgs('a', 1).calledBefore(spyTwo);
spy.alwaysCalledOn(instance);
spy.alwaysCalledWith('a', 1);
spy.alwaysCalledWith('a');
spy.alwaysCalledWithExactly('a', 1);
spy.alwaysCalledWithMatch('foo');
spy.neverCalledWith('b', 2);
spy.neverCalledWith('b');
spy.neverCalledWithMatch('foo', 'bar');
spy.alwaysThrew();
spy.alwaysThrew('foo');
spy.alwaysThrew(new Error('foo'));
spy.alwaysReturned('foo');
spy.invokeCallback('a', 'b');
spy.calledOn(instance);
spy.calledWith('a', 2);
spy.calledWithExactly('a', 2);
spy.calledOnceWith('a', 2);
spy.calledOnceWithExactly('a', 2);
spy.calledWithMatch('bar', 2);
spy.notCalledWith('a', 2);
spy.notCalledWithMatch('a', 2);
spy.returned(true);
spy.returned('foo');
spy.returned(2);
spy.threw();
spy.threw('foo');
spy.threw(new Error('foo'));
spy.callArg(1);
spy.callArgOn(1, instance);
spy.callArgOn(1, instance, 'a', 2);
spy.callArgWith(1, 'a', 2);
spy.callArgOnWith(1, instance, 'a', 2);
spy.yield('a', 2);
spy.yieldOn(instance, 'a', 2);
spy.yieldTo('prop', 'a', 2);
spy.yieldToOn('prop', instance, 'a', 2);
let call = spy.firstCall;
call = spy.secondCall;
call = spy.thirdCall;
call = spy.lastCall;
call = spy.getCall(1);
call = spy.getCalls()[0];
call.calledBefore(call);
call.calledAfter(call);
call.calledWithNew();
spy.resetHistory();
spy.restore();
}
testOne();
testTwo();
testThree();
testFour();
testFive();
testSix();
testSeven();
testEight();
testNine();
testPromises();
testSandbox();
testSpy();
testSymbolMatch();
testResetHistory();
testUsingPromises();
testGetterStub();
testSetterStub();
testValueStub();
testThrowsStub();
testFakeServer();
function testStub() {
const obj = class {
foo() {}
};
const instance = new obj();
const clock = sinon.useFakeTimers();
clock.setSystemTime(1000);
clock.setSystemTime(new Date());
let stub = sinon.stub();
stub = sinon.stub(instance, 'foo');
class TestCreateStubInstance {
someTestMethod(testArg: string) { }
const spy: sinon.SinonSpy = stub;
sinon.stub(instance);
stub.reset();
stub.resetBehavior();
stub.usingPromise(Promise);
stub.returns(true);
stub.returns(5);
stub.returns('foo');
stub.returnsArg(1);
stub.returnsThis();
stub.resolves();
stub.resolves('foo');
stub.throws();
stub.throws('err');
stub.throws(new Error('err'));
stub.throwsArg(1);
stub.throwsException('err');
stub.throwsException(new Error('err'));
stub.rejects();
stub.rejects('TypeError');
stub.rejects(1234);
stub.callsArg(1);
stub.callThrough();
stub.callsArgOn(1, instance);
stub.callsArgWith(1, 'a', 2);
stub.callsArgAsync(1);
stub.callsArgOnAsync(1, instance);
stub.callsArgWithAsync(1, 'a', 2);
stub.callsArgOnWithAsync(1, instance, 'a', 2);
stub.callsFake(() => {});
stub.get(() => true);
stub.set((v) => {});
stub.onCall(1).returns(true);
stub.onFirstCall().resolves('foo');
stub.onSecondCall().resolves('foo');
stub.onThirdCall().resolves('foo');
stub.value('foo');
stub.yields('a', 2);
stub.yieldsOn(instance, 'a', 2);
stub.yieldsRight('a', 2);
stub.yieldsTo('foo', 'a', 2);
stub.yieldsToOn('foo', instance, 'a', 2);
stub.yieldsAsync('a', 2);
stub.yieldsOnAsync(instance, 'a', 2);
stub.yieldsToAsync('foo', 'a', 2);
stub.yieldsToOnAsync('foo', instance, 'a', 2);
stub.withArgs('a', 2).returns(true);
}
sinon.createStubInstance(TestCreateStubInstance).someTestMethod('some argument');
sinon.createStubInstance<TestCreateStubInstance>(TestCreateStubInstance).someTestMethod('some argument');
function testMock() {
const obj = {};
const mock = sinon.mock(obj);
function testGetCalls() {
const double = sinon.spy((a: number) => a * 2);
double(2);
double(4);
double.getCall(0).args.length === 1;
const secondCall = double.getCalls().find(call => call.args[0] === 4);
if (secondCall) {
secondCall.returnValue === 8;
}
mock.expects('method').atLeast(2).atMost(5);
mock.restore();
mock.verify();
}

View File

@@ -1,5 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": [
"es6",
@@ -21,4 +22,4 @@
"index.d.ts",
"sinon-tests.ts"
]
}
}