/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as sinon from 'sinon'; import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; interface IServiceMock { id: ServiceIdentifier; service: any; } export class TestInstantiationService extends InstantiationService { private _servciesMap: Map, any>; constructor(private _serviceCollection: ServiceCollection = new ServiceCollection()) { super(_serviceCollection); this._servciesMap = new Map, any>(); } public get(service: ServiceIdentifier): T { return this._serviceCollection.get(service); } public set(service: ServiceIdentifier, instance: T): T { return this._serviceCollection.set(service, instance); } public mock(service: ServiceIdentifier): T | sinon.SinonMock { return this._create(service, { mock: true }); } public stub(service: ServiceIdentifier, ctor: Function): T; public stub(service: ServiceIdentifier, obj: Partial): T; public stub(service: ServiceIdentifier, ctor: Function, property: string, value: any): sinon.SinonStub; public stub(service: ServiceIdentifier, obj: Partial, property: string, value: any): sinon.SinonStub; public stub(service: ServiceIdentifier, property: string, value: any): sinon.SinonStub; public stub(serviceIdentifier: ServiceIdentifier, arg2: any, arg3?: string, arg4?: any): sinon.SinonStub { let service = typeof arg2 !== 'string' ? arg2 : undefined; let serviceMock: IServiceMock = { id: serviceIdentifier, service: service }; let property = typeof arg2 === 'string' ? arg2 : arg3; let value = typeof arg2 === 'string' ? arg3 : arg4; let stubObject = this._create(serviceMock, { stub: true }, service && !property); if (property) { if (stubObject[property]) { if (stubObject[property].hasOwnProperty('restore')) { stubObject[property].restore(); } if (typeof value === 'function') { stubObject[property] = value; } else { let stub = value ? sinon.stub().returns(value) : sinon.stub(); stubObject[property] = stub; return stub; } } else { stubObject[property] = value; } } return stubObject; } public stubPromise(service?: ServiceIdentifier, fnProperty?: string, value?: any): T | sinon.SinonStub; public stubPromise(service?: ServiceIdentifier, ctor?: any, fnProperty?: string, value?: any): sinon.SinonStub; public stubPromise(service?: ServiceIdentifier, obj?: any, fnProperty?: string, value?: any): sinon.SinonStub; public stubPromise(arg1?: any, arg2?: any, arg3?: any, arg4?: any): sinon.SinonStub { arg3 = typeof arg2 === 'string' ? Promise.resolve(arg3) : arg3; arg4 = typeof arg2 !== 'string' && typeof arg3 === 'string' ? Promise.resolve(arg4) : arg4; return this.stub(arg1, arg2, arg3, arg4); } public spy(service: ServiceIdentifier, fnProperty: string): sinon.SinonSpy { let spy = sinon.spy(); this.stub(service, fnProperty, spy); return spy; } private _create(serviceMock: IServiceMock, options: SinonOptions, reset?: boolean): any; private _create(ctor: any, options: SinonOptions): any; private _create(arg1: any, options: SinonOptions, reset: boolean = false): any { if (this.isServiceMock(arg1)) { let service = this._getOrCreateService(arg1, options, reset); this._serviceCollection.set(arg1.id, service); return service; } return options.mock ? sinon.mock(arg1) : this._createStub(arg1); } private _getOrCreateService(serviceMock: IServiceMock, opts: SinonOptions, reset?: boolean): any { let service: any = this._serviceCollection.get(serviceMock.id); if (!reset && service) { if (opts.mock && service['sinonOptions'] && !!service['sinonOptions'].mock) { return service; } if (opts.stub && service['sinonOptions'] && !!service['sinonOptions'].stub) { return service; } } return this._createService(serviceMock, opts); } private _createService(serviceMock: IServiceMock, opts: SinonOptions): any { serviceMock.service = serviceMock.service ? serviceMock.service : this._servciesMap.get(serviceMock.id); let service = opts.mock ? sinon.mock(serviceMock.service) : this._createStub(serviceMock.service); service['sinonOptions'] = opts; return service; } private _createStub(arg: any): any { return typeof arg === 'object' ? arg : sinon.createStubInstance(arg); } private isServiceMock(arg1: any): boolean { return typeof arg1 === 'object' && arg1.hasOwnProperty('id'); } } interface SinonOptions { mock?: boolean; stub?: boolean; }