diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..67637be --- /dev/null +++ b/codecov.yml @@ -0,0 +1,5 @@ + +coverage: + precision: 2 + round: down + range: "80...100" \ No newline at end of file diff --git a/main/helper/index.ts b/main/helper/index.ts index 187a766..70a2c1a 100644 --- a/main/helper/index.ts +++ b/main/helper/index.ts @@ -1,3 +1,4 @@ export * from './property-replacement-helper'; export * from './module-helper'; export * from './jest-helper'; +export * from './lookup-helper'; diff --git a/main/helper/lookup-helper.ts b/main/helper/lookup-helper.ts new file mode 100644 index 0000000..9f6b980 --- /dev/null +++ b/main/helper/lookup-helper.ts @@ -0,0 +1,22 @@ +import { ConstructorFunction, FunctionCallLookup, IMocked, LookupType } from '../mock'; + +export function getLookup, U extends LookupType>( + mock: IMocked, + lookupType: U, +): FunctionCallLookup { + switch (lookupType) { + case 'function': + return mock.functionCallLookup as FunctionCallLookup; + case 'getter': + return mock.getterCallLookup as FunctionCallLookup; + case 'setter': + return mock.setterCallLookup as FunctionCallLookup; + case 'staticFunction': + return mock.staticFunctionCallLookup as FunctionCallLookup; + case 'staticGetter': + return mock.staticGetterCallLookup as FunctionCallLookup; + case 'staticSetter': + return mock.staticSetterCallLookup as FunctionCallLookup; + } + throw new Error(`Unknown lookup type: ${lookupType}`); +} diff --git a/main/mock/contracts.ts b/main/mock/contracts.ts index 21d24d5..d37df63 100644 --- a/main/mock/contracts.ts +++ b/main/mock/contracts.ts @@ -5,6 +5,9 @@ export type MatchFunction = (passedValue: T) => boolean; // tslint:disable-next-line:ban-types export type FunctionsOnly = Pick[K] extends Function ? K : never }[keyof T]>; +// tslint:disable-next-line:ban-types +export type PropertiesOnly = Pick[K] extends Function ? never : K }[keyof T]>; + /** * Allows custom logic to verify that a function parameter has the expected value. */ @@ -31,26 +34,44 @@ export type FunctionParameterMatchers = { [P in keyof T]: T[P] extends FunctionOrConstructor ? IParameterMatcher : ParameterMatcher; }; -export type FunctionCallLookup = { [key: string]: any[][] }; +export type FunctionCallLookup, U extends LookupType> = { + [P in FunctionName]?: LookupParams[]; +}; +export type LookupParams< + T, + C extends ConstructorFunction, + U extends LookupType, + K extends FunctionName +> = U extends FunctionTypes + ? FunctionParams[K]> + : U extends SetterTypes + ? [VerifierTarget[K]] + : []; export type FunctionParams = T extends (...args: infer P) => any ? P : never; export type ConstructorFunction = new (...args: any[]) => T; -export type StaticFunctionTypes = 'staticFunction' | 'staticGetter' | 'staticSetter'; -export type InstanceFunctionTypes = 'function' | 'getter' | 'setter'; +export type StaticLookupTypes = 'staticFunction' | 'staticGetter' | 'staticSetter'; +export type InstanceLookupTypes = 'function' | 'getter' | 'setter'; export type SetterTypes = 'staticSetter' | 'setter'; +export type GetterTypes = 'staticGetter' | 'getter'; +export type FunctionTypes = 'staticFunction' | 'function'; +export type LookupType = StaticLookupTypes | InstanceLookupTypes; -export type VerifierTarget, U extends FunctionType> = U extends StaticFunctionTypes - ? C +export type VerifierTarget, U extends LookupType> = U extends StaticLookupTypes + ? U extends FunctionTypes + ? FunctionsOnly + : C + : U extends FunctionTypes + ? FunctionsOnly : T; -export type FunctionType = StaticFunctionTypes | InstanceFunctionTypes; -export type FunctionName, U extends FunctionType> = keyof VerifierTarget; +export type FunctionName, U extends LookupType> = keyof VerifierTarget; export interface IFunctionWithParametersVerification< P extends Array, T, - U extends FunctionType, + U extends LookupType, C extends new (...args: any[]) => T = never > extends IFunctionVerifier { /** @@ -89,7 +110,7 @@ export interface IFunctionWithParametersVerification< withParametersEqualTo(...args: FunctionParameterMatchers

): IStrictFunctionVerification; } -export interface IStrictFunctionVerification T = never> +export interface IStrictFunctionVerification T = never> extends IFunctionVerifier { /** * verify that the function has been called ONLY with the specified parameters and never without @@ -97,7 +118,7 @@ export interface IStrictFunctionVerification; } -export interface IFunctionVerifier T = never> { +export interface IFunctionVerifier T = never> { type: U; functionName: FunctionName; parameterMatchers?: (MatchFunction | IParameterMatcher)[]; @@ -116,13 +137,15 @@ export interface IMocked T = never> { */ mockConstructor: C; - functionCallLookup: FunctionCallLookup; - setterCallLookup: FunctionCallLookup; - getterCallLookup: FunctionCallLookup; + functionCallLookup: FunctionCallLookup; + setterCallLookup: FunctionCallLookup; + getterCallLookup: FunctionCallLookup; + + staticFunctionCallLookup: FunctionCallLookup; + staticSetterCallLookup: FunctionCallLookup; + staticGetterCallLookup: FunctionCallLookup; - staticFunctionCallLookup: FunctionCallLookup; - staticSetterCallLookup: FunctionCallLookup; - staticGetterCallLookup: FunctionCallLookup; + functionReplacementLookup: Partial any) | undefined>>>; /** * Used to setup the mock with multiple operators. diff --git a/main/mock/mock.ts b/main/mock/mock.ts index 547e0c2..9ffc393 100644 --- a/main/mock/mock.ts +++ b/main/mock/mock.ts @@ -22,6 +22,8 @@ export class Mock { staticSetterCallLookup: {}, staticGetterCallLookup: {}, + functionReplacementLookup: {}, + mock: {} as T, // tslint:disable-next-line:no-empty mockConstructor: ((..._args: any[]) => {}) as any, @@ -66,13 +68,13 @@ export class Mock { return mocked.withStaticGetter(propertyName); }, - withFunction: (functionName: U) => + withFunction: >(functionName: U) => createFunctionParameterVerifier(mocked, 'function', functionName), withSetter: (functionName: U) => createFunctionParameterVerifier(mocked, 'setter', functionName), withGetter: (functionName: U) => createFunctionVerifier(mocked, 'getter', functionName), - withStaticFunction: (functionName: U) => + withStaticFunction: >(functionName: U) => createFunctionParameterVerifier(mocked, 'staticFunction', functionName), withStaticSetter: (functionName: U) => createFunctionParameterVerifier(mocked, 'staticSetter', functionName), diff --git a/main/mock/operators.ts b/main/mock/operators.ts index da84dbd..348b85e 100644 --- a/main/mock/operators.ts +++ b/main/mock/operators.ts @@ -1,11 +1,15 @@ +import { getLookup } from '../helper'; import { ConstructorFunction, FunctionCallLookup, FunctionName, - FunctionsOnly, - FunctionType, + FunctionTypes, + GetterTypes, IMocked, + LookupParams, + LookupType, OperatorFunction, + SetterTypes, } from './contracts'; /** @@ -16,24 +20,32 @@ import { * @param functionName * @param mockFunction */ -export function setupFunction, U extends keyof FunctionsOnly>( +export function setupFunction, U extends FunctionName>( functionName: U, mockFunction?: T[U], ): OperatorFunction { return (mocked: IMocked) => { - const functionReplacement = (...args: any[]) => { + const functionReplacement = (...args: LookupParams) => { let returnValue: any; - if (mockFunction instanceof Function) { - returnValue = mockFunction.apply(mocked.mock, args); + const mockedFunction = mocked.functionReplacementLookup['function']?.[functionName as string]; + + if (mockedFunction instanceof Function) { + returnValue = mockedFunction.apply(mocked.mock, args); } - trackFunctionCall(mocked, functionName as string, args, false); + trackFunctionCall(mocked, 'function', functionName, args); return returnValue; }; - mocked.mock[functionName] = functionReplacement as any; - mocked.functionCallLookup[functionName as any] = []; + const functionLookup = (mocked.functionReplacementLookup['function'] = + mocked.functionReplacementLookup['function'] || {}); + functionLookup[functionName as string] = mockFunction; + + if (mocked.mock[functionName] == null) { + mocked.mock[functionName] = functionReplacement as any; + } + mocked.functionCallLookup[functionName] = []; return mocked; }; @@ -47,24 +59,33 @@ export function setupFunction, U extends key * @param functionName * @param mockFunction */ -export function setupStaticFunction, U extends keyof FunctionsOnly>( - functionName: U, - mockFunction?: C[U], -): OperatorFunction { +export function setupStaticFunction< + T, + C extends ConstructorFunction, + U extends FunctionName +>(functionName: U, mockFunction?: C[U]): OperatorFunction { return (mocked: IMocked) => { - const functionReplacement = (...args: any[]) => { + const functionReplacement = (...args: LookupParams) => { let returnValue: any; - if (mockFunction instanceof Function) { - returnValue = mockFunction.apply(mocked.mock, args); + const mockedFunction = mocked.functionReplacementLookup['staticFunction']?.[functionName as string]; + + if (mockedFunction instanceof Function) { + returnValue = mockedFunction.apply(mocked.mock, args); } - trackFunctionCall(mocked, functionName as string, args, true); + trackFunctionCall(mocked, 'staticFunction', functionName, args); return returnValue; }; - mocked.mockConstructor[functionName] = functionReplacement as any; - mocked.staticFunctionCallLookup[functionName as any] = []; + const staticFunctionLookup = (mocked.functionReplacementLookup['staticFunction'] = + mocked.functionReplacementLookup['staticFunction'] || {}); + staticFunctionLookup[functionName as string] = mockFunction; + + if (mocked.mockConstructor[functionName] == null) { + mocked.mockConstructor[functionName] = functionReplacement as any; + } + mocked.staticFunctionCallLookup[functionName] = []; return mocked; }; @@ -78,7 +99,7 @@ export function setupStaticFunction, U exten * @param propertyName * @param value */ -export function setupProperty, U extends keyof T>( +export function setupProperty, U extends FunctionName>( propertyName: U, value?: T[U], ): OperatorFunction { @@ -93,7 +114,7 @@ export function setupProperty, U extends key * @param propertyName * @param value */ -export function setupStaticProperty, U extends keyof C>( +export function setupStaticProperty, U extends FunctionName>( propertyName: U, value?: C[U], ): OperatorFunction { @@ -108,13 +129,13 @@ export function setupStaticProperty, U exten * @param propertyName * @param value */ -export function defineProperty, U extends keyof T>( +export function defineProperty, U extends FunctionName>( propertyName: U, getter?: () => T[U], setter?: (value: T[U]) => void, ): OperatorFunction { return (mocked: IMocked) => { - return definePropertyImpl(mocked, 'getter', propertyName, false, getter, setter); + return definePropertyImpl(mocked, 'getter', propertyName, getter, setter); }; } @@ -126,101 +147,141 @@ export function defineProperty, U extends ke * @param propertyName * @param value */ -export function defineStaticProperty, U extends keyof C>( +export function defineStaticProperty, U extends FunctionName>( propertyName: U, getter?: () => C[U], setter?: (value: C[U]) => void, ): OperatorFunction { return (mocked: IMocked) => { - return definePropertyImpl(mocked, 'staticGetter', propertyName, true, getter, setter); + return definePropertyImpl(mocked, 'staticGetter', propertyName, getter, setter); }; } function definePropertyImpl< T, C extends ConstructorFunction, - U extends FunctionType, + U extends GetterTypes, K extends FunctionName >( mocked: IMocked, - _type: U, + lookupType: U, propertyName: K, - isStatic: boolean, getter?: () => any, setter?: (value: any) => void, ): IMocked { const propertyGetter = () => { - trackGetterCall(mocked, propertyName as string, isStatic); + trackGetterCall(mocked, lookupType, propertyName); - return getter ? getter() : undefined; + const mockedFunction = mocked.functionReplacementLookup[lookupType]?.[propertyName as string]; + return mockedFunction ? mockedFunction() : undefined; }; + let setterLookupType: SetterTypes; + + switch (lookupType) { + case 'getter': + setterLookupType = 'setter'; + const getterLookup = (mocked.functionReplacementLookup['getter'] = + mocked.functionReplacementLookup['getter'] || {}); + getterLookup[propertyName as string] = getter; + const setterLookup = (mocked.functionReplacementLookup['setter'] = + mocked.functionReplacementLookup['setter'] || {}); + setterLookup[propertyName as string] = setter; + break; + case 'staticGetter': + const staticGetterLookup = (mocked.functionReplacementLookup['staticGetter'] = + mocked.functionReplacementLookup['staticGetter'] || {}); + staticGetterLookup[propertyName as string] = getter; + const staticSetterLookup = (mocked.functionReplacementLookup['staticSetter'] = + mocked.functionReplacementLookup['staticSetter'] || {}); + staticSetterLookup[propertyName as string] = setter; + setterLookupType = 'staticSetter'; + break; + } + + const setterProperty: FunctionName = propertyName as any; + const propertySetter = (value: any) => { - trackSetterCall(mocked, propertyName as string, value, isStatic); + trackSetterCall(mocked, setterLookupType, setterProperty, [value]); - if (setter != null) { - setter.apply(mocked.mock, [value]); + const mockedFunction = mocked.functionReplacementLookup[setterLookupType]?.[propertyName as string]; + if (mockedFunction != null) { + mockedFunction.apply(mocked.mock, [value]); } }; - const object = isStatic ? mocked.mockConstructor : mocked.mock; - - Object.defineProperty(object, propertyName, { - enumerable: true, - get: propertyGetter, - set: propertySetter, - configurable: true, - }); - - if (isStatic) { - mocked.staticGetterCallLookup[propertyName as any] = []; - mocked.staticSetterCallLookup[propertyName as any] = []; - } else { - mocked.getterCallLookup[propertyName as any] = []; - mocked.setterCallLookup[propertyName as any] = []; + let target: T | C; + + getLookup(mocked, lookupType)[propertyName] = []; + + switch (lookupType) { + case 'staticGetter': + target = mocked.mockConstructor; + getLookup(mocked, 'staticSetter')[setterProperty] = []; + break; + default: + target = mocked.mock; + getLookup(mocked, 'setter')[setterProperty] = []; + break; + } + + if (Object.getOwnPropertyDescriptor(target, propertyName) == null) { + Object.defineProperty(target, propertyName, { + enumerable: true, + get: propertyGetter, + set: propertySetter, + configurable: true, + }); } return mocked; } -function trackFunctionCall>( - mock: IMocked, - functionName: string, - params: any[], - isStatic: boolean, -) { - const lookup = isStatic ? mock.staticFunctionCallLookup : mock.functionCallLookup; +function trackFunctionCall< + T, + C extends ConstructorFunction, + U extends FunctionTypes, + K extends FunctionName +>(mock: IMocked, lookupType: U, functionName: K, params: LookupParams) { + const lookup = getLookup(mock, lookupType); trackCall(lookup, functionName, params); } -function trackGetterCall>( +function trackGetterCall, U extends GetterTypes, K extends FunctionName>( mock: IMocked, - propertyName: string, - isStatic: boolean, + lookupType: U, + propertyName: K, ) { - const lookup = isStatic ? mock.staticGetterCallLookup : mock.getterCallLookup; + const lookup = getLookup(mock, lookupType); // it's easier to have an array of empty arrays than just keep track of a count // This allows us to use the same verification code as the setter and functions - trackCall(lookup, propertyName, []); + trackCall(lookup, propertyName, [] as LookupParams); } -function trackSetterCall>( +function trackSetterCall, U extends SetterTypes, K extends FunctionName>( mock: IMocked, - propertyName: string, - param: any, - isStatic: boolean, + lookupType: U, + propertyName: K, + param: LookupParams, ) { - const lookup = isStatic ? mock.staticSetterCallLookup : mock.setterCallLookup; + const lookup = getLookup(mock, lookupType); - trackCall(lookup, propertyName, [param]); + trackCall(lookup, propertyName, param); } -function trackCall(lookup: FunctionCallLookup, name: string, params: any[]) { - if (lookup[name as any] === undefined) { - lookup[name as any] = []; +function trackCall, U extends LookupType, K extends FunctionName>( + lookup: FunctionCallLookup, + name: K, + params: LookupParams, +) { + let functionCalls: LookupParams[] | undefined = lookup[name]; + + if (functionCalls === undefined) { + functionCalls = [] as LookupParams[]; + lookup[name] = functionCalls; } - lookup[name as any].push(params); + functionCalls.push(params); } diff --git a/main/mock/verifiers.ts b/main/mock/verifiers.ts index 7744e01..db25ad1 100644 --- a/main/mock/verifiers.ts +++ b/main/mock/verifiers.ts @@ -1,9 +1,8 @@ -import { runningInJest } from '../helper'; +import { getLookup, runningInJest } from '../helper'; import { ConstructorFunction, FunctionName, FunctionParams, - FunctionType, IFunctionVerifier, IFunctionWithParametersVerification, IJasmineCustomMatcherResult, @@ -11,6 +10,8 @@ import { IMocked, IParameterMatcher, IStrictFunctionVerification, + LookupParams, + LookupType, MatchFunction, ParameterMatcher, SetterTypes, @@ -21,14 +22,14 @@ import { isParameterMatcher, mapItemToString, toBe, toEqual } from './parameterM export type VerifierParams< T, C extends ConstructorFunction, - U extends FunctionType, + U extends LookupType, K extends FunctionName > = U extends SetterTypes ? [VerifierTarget[K]] : FunctionParams[K]>; export function createFunctionParameterVerifier< T, C extends ConstructorFunction, - U extends FunctionType, + U extends LookupType, K extends FunctionName >( mocked: IMocked, @@ -58,7 +59,7 @@ export function createFunctionParameterVerifier< export function createFunctionVerifier< T, C extends ConstructorFunction, - U extends FunctionType, + U extends LookupType, K extends FunctionName >( mocked: IMocked, @@ -79,7 +80,7 @@ export function createFunctionVerifier< export function createStrictFunctionVerifier< T, C extends ConstructorFunction, - U extends FunctionType, + U extends LookupType, K extends FunctionName >( mocked: IMocked, @@ -96,7 +97,7 @@ export function createStrictFunctionVerifier< export function verifyParameters< T, C extends ConstructorFunction, - U extends FunctionType, + U extends LookupType, K extends FunctionName >( parameters: ParameterMatcher[], @@ -128,7 +129,7 @@ function mapParameterToMatcher( return equals ? toEqual(param) : toBe(param); } -export function verifyFunctionCalled, U extends FunctionType>( +export function verifyFunctionCalled, U extends LookupType>( times: number | undefined, verifier: IFunctionVerifier, ): IJasmineCustomMatcherResult | IJestCustomMatcherResult { @@ -138,49 +139,44 @@ export function verifyFunctionCalled, U exte const parameterMatchers = verifier.parameterMatchers; const strict = verifier.strictCallCount; - let functionCalls: any[][]; let expectationMessage: string; let errorMessageSetupFunction: string; let errorMessageDescription: string; + const functionCalls: LookupParams[] | undefined = getLookup(mock, type)[functionName]; + switch (type) { case 'staticGetter': - functionCalls = mock.staticGetterCallLookup[functionName as any]; expectationMessage = `Expected static property "${functionName}" getter to be called`; errorMessageSetupFunction = `Mock.setupStaticProperty()`; errorMessageDescription = `Static property`; break; case 'staticSetter': - functionCalls = mock.staticSetterCallLookup[functionName as any]; expectationMessage = `Expected static property "${functionName}" to be set`; errorMessageSetupFunction = `Mock.setupStaticProperty()`; errorMessageDescription = `Static property`; break; case 'staticFunction': - functionCalls = mock.staticFunctionCallLookup[functionName as any]; expectationMessage = `Expected static function "${functionName}" to be called`; errorMessageSetupFunction = `Mock.setupStaticFunction()`; errorMessageDescription = `Static function`; break; case 'getter': - functionCalls = mock.getterCallLookup[functionName as any]; expectationMessage = `Expected property "${functionName}" getter to be called`; errorMessageSetupFunction = `Mock.setupProperty()`; errorMessageDescription = `Property`; break; case 'setter': - functionCalls = mock.setterCallLookup[functionName as any]; expectationMessage = `Expected property "${functionName}" to be set`; errorMessageSetupFunction = `Mock.setupProperty()`; errorMessageDescription = `Property`; break; default: - functionCalls = mock.functionCallLookup[functionName as any]; expectationMessage = `Expected "${functionName}" to be called`; errorMessageSetupFunction = `Mock.setupFunction()`; errorMessageDescription = `Function`; diff --git a/package-lock.json b/package-lock.json index a7f51a6..584a9f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@morgan-stanley/ts-mocking-bird", - "version": "0.2.3", + "version": "0.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -33,14 +33,66 @@ } }, "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "version": "25.5.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha1-TWpHk/e5WZ/DaAh3uFapfbzPKp0=", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha1-P3PCv1JlkfV0zEksUeJFY0n4ROQ=", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "@testim/chrome-version": { @@ -61,15 +113,6 @@ "integrity": "sha1-gaZzHOTfQ2GeXIyUU4Oz5iqJ6oY=", "dev": true }, - "@types/fs-extra": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.1.0.tgz", - "integrity": "sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/glob": { "version": "7.1.1", "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/@types/glob/-/glob-7.1.1.tgz", @@ -81,40 +124,25 @@ "@types/node": "*" } }, - "@types/handlebars": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.1.0.tgz", - "integrity": "sha512-gq9YweFKNNB1uFK71eRqsd4niVkXrxHugqWFQkeLRJvGjnxsLr16bYtcsG4tOFwmYi0Bax+wCkbf1reUfdl4kA==", - "dev": true, - "requires": { - "handlebars": "*" - } - }, - "@types/highlight.js": { - "version": "9.12.3", - "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", - "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", - "dev": true - }, "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "version": "2.0.3", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha1-S6jdtyAiH0MuRDvV+RF/0iz9R2I=", "dev": true }, "@types/istanbul-lib-report": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha1-wUwk8Y6oGQwRjudWK3/5mjZVJoY=", "dev": true, "requires": { "@types/istanbul-lib-coverage": "*" } }, "@types/istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "version": "1.1.2", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha1-6HXMaJ5HvOVJ7IHz315vbxHPrrI=", "dev": true, "requires": { "@types/istanbul-lib-coverage": "*", @@ -128,12 +156,13 @@ "dev": true }, "@types/jest": { - "version": "24.9.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.9.1.tgz", - "integrity": "sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==", + "version": "25.2.3", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/@types/jest/-/jest-25.2.3.tgz", + "integrity": "sha1-M9J+TEcWyq5OztNVCXpHrTY/3K8=", "dev": true, "requires": { - "jest-diff": "^24.3.0" + "jest-diff": "^25.2.1", + "pretty-format": "^25.2.1" } }, "@types/json5": { @@ -148,12 +177,6 @@ "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", "dev": true }, - "@types/marked": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.4.2.tgz", - "integrity": "sha512-cDB930/7MbzaGF6U3IwSQp6XBru8xWajF5PV2YZZeV8DyiliTuld11afVztGI9+yJZ29il5E+NpGA6ooV/Cjkg==", - "dev": true - }, "@types/mime-types": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz", @@ -172,16 +195,6 @@ "integrity": "sha512-DQ2hl/Jl3g33KuAUOcMrcAOtsbzb+y/ufakzAdeK9z/H/xsvkpbETZZbPNMIiQuk24f5ZRMCcZIViAwyFIiKmg==", "dev": true }, - "@types/shelljs": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.7.tgz", - "integrity": "sha512-Mg2qGjLIJIieeJ1/NjswAOY9qXDShLeh6JwpD1NZsvUvI0hxdUCNDpnBXv9YQeugKi2EHU+BqkbUE4jpY4GKmQ==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, "@types/uuid": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-7.0.2.tgz", @@ -189,18 +202,18 @@ "dev": true }, "@types/yargs": { - "version": "13.0.8", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", - "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "version": "15.0.12", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/@types/yargs/-/yargs-15.0.12.tgz", + "integrity": "sha1-YjTOPj4/oyxdswGhcPlqWZyWDXQ=", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", - "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "version": "20.2.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", + "integrity": "sha1-3T5mmboyN/A0jNCF5GmHgCBIQvk=", "dev": true }, "@webassemblyjs/ast": { @@ -800,6 +813,15 @@ "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", "dev": true }, + "backbone": { + "version": "1.4.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/backbone/-/backbone-1.4.0.tgz", + "integrity": "sha1-VNtN6d98OBHD8DLzR0mkzSfzvRI=", + "dev": true, + "requires": { + "underscore": ">=1.8.3" + } + }, "backo2": { "version": "1.0.2", "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/backo2/-/backo2-1.0.2.tgz", @@ -1075,15 +1097,6 @@ "pako": "~1.0.5" } }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, "buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", @@ -1304,6 +1317,15 @@ "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", "upath": "^1.1.1" + }, + "dependencies": { + "fsevents": { + "version": "1.2.13", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=", + "dev": true, + "optional": true + } } }, "chownr": { @@ -1950,9 +1972,9 @@ "dev": true }, "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "version": "25.2.6", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha1-X0Z8AO3TU1K3vKRteSfWDmh6dt0=", "dev": true }, "diffie-hellman": { @@ -2667,631 +2689,91 @@ "for-in": { "version": "1.0.2", "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-access": { - "version": "1.0.1", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fs-access/-/fs-access-1.0.1.tgz", - "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "requires": { - "null-check": "^1.0.0" - } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.7", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fsevents/-/fsevents-1.2.7.tgz", - "integrity": "sha1-SFG2ZKN4PlIAOzxm6w7uEHSTOqQ=", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "^1.0.0" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=", + "dev": true } } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -3397,28 +2879,21 @@ "dev": true }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.1.2", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha1-trN8HO0DBrIh4JT8eso+wjsTG2c=", "dev": true, "requires": { - "minimist": "^1.2.5", "neo-async": "^2.6.0", + "optimist": "^0.6.1", "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" + "uglify-js": "^3.1.4" }, "dependencies": { "source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -3531,8 +3006,8 @@ }, "highlight.js": { "version": "9.18.5", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.5.tgz", - "integrity": "sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA==", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/highlight.js/-/highlight.js-9.18.5.tgz", + "integrity": "sha1-0Yo1mGfzeME41oGe38KorNXymCU=", "dev": true }, "hmac-drbg": { @@ -3731,9 +3206,9 @@ "dev": true }, "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "version": "1.4.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha1-Zlq4vE2iendKQFhOgS4+D6RbGh4=", "dev": true }, "invariant": { @@ -4234,15 +3709,66 @@ "dev": true }, "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "version": "25.5.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/jest-diff/-/jest-diff-25.5.0.tgz", + "integrity": "sha1-HdJu1k+WZnwGjO8Ca2d9+gGvz6k=", "dev": true, "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha1-P3PCv1JlkfV0zEksUeJFY0n4ROQ=", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "jest-docblock": { @@ -4252,9 +3778,15 @@ "dev": true }, "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "version": "25.2.6", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha1-Cwoy+riQi0TVCL6BaBSH26u42Hc=", + "dev": true + }, + "jquery": { + "version": "3.5.1", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/jquery/-/jquery-3.5.1.tgz", + "integrity": "sha1-17TQjhv9uGrS8aPQOeoXMEcXq7U=", "dev": true }, "js-tokens": { @@ -4324,19 +3856,11 @@ "dev": true, "requires": { "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "jsonfile": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { @@ -4591,12 +4115,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, "log4js": { "version": "3.0.6", "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/log4js/-/log4js-3.0.6.tgz", @@ -4662,6 +4180,12 @@ "integrity": "sha1-Wrh60dTB2rjowIu/A37gwZAih88=", "dev": true }, + "lunr": { + "version": "2.3.9", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha1-GLEjFCgyM33W6WTfGlp3B7JdNeE=", + "dev": true + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -4680,12 +4204,6 @@ } } }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -4717,9 +4235,9 @@ } }, "marked": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.4.0.tgz", - "integrity": "sha512-tMsdNBgOsrUophCAFQl0XPe6Zqk/uy9gnue+jIIKhykO51hxyu6uNx7zBPy0+y/WKYVZZMspV9YeXLNdKk+iYw==", + "version": "0.8.2", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/marked/-/marked-0.8.2.tgz", + "integrity": "sha1-T6rSjSbt41Gnoaql/sZ5Fchp41U=", "dev": true }, "md5.js": { @@ -4776,14 +4294,6 @@ "read-pkg-up": "^1.0.1", "redent": "^1.0.0", "trim-newlines": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "micromatch": { @@ -4947,13 +4457,6 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "nan": { - "version": "2.14.0", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/nan/-/nan-2.14.0.tgz", - "integrity": "sha1-eBj3IgJ7JFmobwKV1DTR/CM2xSw=", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/nanomatch/-/nanomatch-1.2.13.tgz", @@ -5475,12 +4978,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -5541,21 +5038,45 @@ "dev": true }, "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "version": "25.5.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/pretty-format/-/pretty-format-25.5.0.tgz", + "integrity": "sha1-eHPB13T2gsNLjUi2dDor8qxVeRo=", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", "dev": true } } @@ -5783,8 +5304,8 @@ }, "react-is": { "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha1-eJcppNw23imZ3BVt1sHZwYzqVqQ=", "dev": true }, "read-pkg": { @@ -6155,9 +5676,9 @@ "dev": true }, "shelljs": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "version": "0.8.4", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha1-3naE/ut2f4cWsyYHiooAh1iQ48I=", "dev": true, "requires": { "glob": "^7.0.0", @@ -6932,107 +6453,6 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, - "ts-jest": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-25.4.0.tgz", - "integrity": "sha512-+0ZrksdaquxGUBwSdTIcdX7VXdwLIlSRsyjivVA9gcO+Cvr6ByqDhu/mi5+HCcb6cMkiQp5xZ8qRO7/eCqLeyw==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "buffer-from": "1.x", - "fast-json-stable-stringify": "2.x", - "json5": "2.x", - "lodash.memoize": "4.x", - "make-error": "1.x", - "micromatch": "4.x", - "mkdirp": "1.x", - "resolve": "1.x", - "semver": "6.x", - "yargs-parser": "18.x" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, "ts-loader": { "version": "5.4.5", "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/ts-loader/-/ts-loader-5.4.5.tgz", @@ -7058,12 +6478,6 @@ "strip-bom": "^3.0.0" }, "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, "strip-bom": { "version": "3.0.0", "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/strip-bom/-/strip-bom-3.0.0.tgz", @@ -7118,15 +6532,6 @@ "requires": { "path-parse": "^1.0.6" } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha1-MrSIUBRnrL7dS4VJhnOggSrKC5k=", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } } } }, @@ -7147,6 +6552,15 @@ "tslib": "^1.7.1" } }, + "tsutils": { + "version": "2.29.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha1-MrSIUBRnrL7dS4VJhnOggSrKC5k=", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -7194,69 +6608,87 @@ "dev": true }, "typedoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.14.2.tgz", - "integrity": "sha512-aEbgJXV8/KqaVhcedT7xG6d2r+mOvB5ep3eIz1KuB5sc4fDYXcepEEMdU7XSqLFO5hVPu0nllHi1QxX2h/QlpQ==", + "version": "0.16.11", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/typedoc/-/typedoc-0.16.11.tgz", + "integrity": "sha1-lfhixuunhTPtya9wltIpW3GO3cE=", "dev": true, "requires": { - "@types/fs-extra": "^5.0.3", - "@types/handlebars": "^4.0.38", - "@types/highlight.js": "^9.12.3", - "@types/lodash": "^4.14.110", - "@types/marked": "^0.4.0", "@types/minimatch": "3.0.3", - "@types/shelljs": "^0.8.0", - "fs-extra": "^7.0.0", - "handlebars": "^4.0.6", - "highlight.js": "^9.13.1", - "lodash": "^4.17.10", - "marked": "^0.4.0", + "fs-extra": "^8.1.0", + "handlebars": "^4.7.2", + "highlight.js": "^9.17.1", + "lodash": "^4.17.15", + "marked": "^0.8.0", "minimatch": "^3.0.0", - "progress": "^2.0.0", - "shelljs": "^0.8.2", - "typedoc-default-themes": "^0.5.0", - "typescript": "3.2.x" + "progress": "^2.0.3", + "shelljs": "^0.8.3", + "typedoc-default-themes": "^0.7.2", + "typescript": "3.7.x" }, "dependencies": { + "handlebars": { + "version": "4.7.6", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha1-1MBcG6+Q6ZRfd6pop6IZqkp9904=", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "progress": { + "version": "2.0.3", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/progress/-/progress-2.0.3.tgz", + "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, "typescript": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", - "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", + "version": "3.7.5", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/typescript/-/typescript-3.7.5.tgz", + "integrity": "sha1-BpLiH2X9QQi5MwI4qsEd0uF3oa4=", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true } } }, "typedoc-default-themes": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz", - "integrity": "sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic=", - "dev": true + "version": "0.7.2", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/typedoc-default-themes/-/typedoc-default-themes-0.7.2.tgz", + "integrity": "sha1-HpiW+SC1jm2gu6nX5kNzjQJAWlo=", + "dev": true, + "requires": { + "backbone": "^1.4.0", + "jquery": "^3.4.1", + "lunr": "^2.3.8", + "underscore": "^1.9.1" + } }, "typescript": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", - "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==", + "version": "3.8.3", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha1-QJ64VE6gM1cRIFhp7EWKsQnuEGE=", "dev": true }, "uglify-js": { - "version": "3.4.9", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha1-rwLxgMEgfXZDLkc+0koo9KeCuuM=", + "version": "3.12.4", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/uglify-js/-/uglify-js-3.12.4.tgz", + "integrity": "sha1-k95Iu3a7PsD8NlY/hxukbi7lx+4=", "dev": true, - "optional": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true, - "optional": true - } - } + "optional": true }, "ultron": { "version": "1.1.1", @@ -7264,6 +6696,12 @@ "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", "dev": true }, + "underscore": { + "version": "1.12.0", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/underscore/-/underscore-1.12.0.tgz", + "integrity": "sha1-SBSUBVH8gFh873hA0euw8WRTvpc=", + "dev": true + }, "union-value": { "version": "1.0.1", "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/union-value/-/union-value-1.0.1.tgz", @@ -7296,8 +6734,8 @@ }, "universalify": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "resolved": "http://msdeartprod.ms.com/artifactory/api/npm/npmjs/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", "dev": true }, "unpipe": { diff --git a/package.json b/package.json index 3f2742d..8348ad3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@morgan-stanley/ts-mocking-bird", - "version": "0.2.3", + "version": "0.3.0", "description": "A fully type safe mocking, call verification and import replacement library for jasmine and jest", "license": "Apache-2.0", "author": "Morgan Stanley", @@ -28,7 +28,7 @@ }, "devDependencies": { "@types/jasmine": "^3.5.10", - "@types/jest": "^24.9.1", + "@types/jest": "^25.2.3", "@types/lodash": "^4.14.149", "@types/node": "^10.17.18", "@types/uuid": "^7.0.2", @@ -38,6 +38,7 @@ "codecov": "^3.6.5", "concurrently": "^4.1.2", "copyfiles": "^1.2.0", + "handlebars": "^4.1.2", "istanbul-instrumenter-loader": "^3.0.1", "jasmine": "^3.5.0", "jasmine-core": "^3.5.0", @@ -54,14 +55,13 @@ "puppeteer": "^2.1.1", "rimraf": "^2.6.3", "source-map": "0.5.7", - "ts-jest": "^25.4.0", "ts-loader": "^5.4.5", "tsconfig-paths-webpack-plugin": "^3.2.0", "tslint": "^5.20.1", "tslint-config-prettier": "^1.18.0", "tslint-plugin-prettier": "^2.3.0", - "typedoc": "~0.14.2", - "typescript": "~3.1.6", + "typedoc": "^0.16.11", + "typescript": "^3.8.3", "webpack": "^4.42.1" }, "peerDependencies": { diff --git a/spec/mock/mock-static.spec.ts b/spec/mock/mock-static.spec.ts index 3cf7658..2c64436 100644 --- a/spec/mock/mock-static.spec.ts +++ b/spec/mock/mock-static.spec.ts @@ -265,7 +265,7 @@ describe('mock with statics', () => { ).wasCalledAtLeastOnce(); }); - it(`should fail when function has been called once with "two" instaed of "one"`, () => { + it(`should fail when function has been called once with "two" instead of "one"`, () => { mocked.mockConstructor.functionWithParamsAndReturn('two', 123, true); verifyFailure( @@ -275,7 +275,7 @@ describe('mock with statics', () => { ); }); - it(`should fail when function has been called once with "456" instaed of "123"`, () => { + it(`should fail when function has been called once with "456" instead of "123"`, () => { mocked.mockConstructor.functionWithParamsAndReturn('one', 456, true); verifyFailure( @@ -285,7 +285,7 @@ describe('mock with statics', () => { ); }); - it(`should fail when function has been called once with "false" instaed of "true"`, () => { + it(`should fail when function has been called once with "false" instead of "true"`, () => { mocked.mockConstructor.functionWithParamsAndReturn('one', 123, false); verifyFailure( @@ -1376,6 +1376,52 @@ describe('mock with statics', () => { mocked.mockConstructor.propertyOne = 'testTwo'; expect(values).toEqual(['testOne', 'testTwo']); }); + + it('should not change setter on mock when defineProperty called twice', () => { + const values: string[] = []; + + function setterOne(value: string) { + values.push(`${value}_setterOne`); + } + + function setterTwo(value: string) { + values.push(`${value}_setterTwo`); + } + + mocked.setup(defineStaticProperty('propertyOne', () => 'mockedValue')); + let mockedFunction = Object.getOwnPropertyDescriptor(mocked.mockConstructor, 'propertyOne')?.set; + + mocked.setup(defineStaticProperty('propertyOne', () => 'mockedValue', setterOne)); + expect(Object.getOwnPropertyDescriptor(mocked.mockConstructor, 'propertyOne')?.set).toBe(mockedFunction); + mockedFunction = Object.getOwnPropertyDescriptor(mocked.mockConstructor, 'propertyOne')?.set; + + mocked.setup(defineStaticProperty('propertyOne', () => 'mockedValue', setterTwo)); + expect(Object.getOwnPropertyDescriptor(mocked.mockConstructor, 'propertyOne')?.set).toBe(mockedFunction); + expect(values).toEqual([]); + mocked.mockConstructor.propertyOne = 'testOne'; + expect(values).toEqual(['testOne_setterTwo']); + }); + + it('should not change getter on mock when defineProperty called twice', () => { + function getterOne() { + return 'getterOne'; + } + + function getterTwo() { + return 'getterTwo'; + } + + mocked.setup(defineStaticProperty('propertyOne')); + let mockedFunction = Object.getOwnPropertyDescriptor(mocked.mockConstructor, 'propertyOne')?.get; + + mocked.setup(defineStaticProperty('propertyOne', getterOne)); + expect(Object.getOwnPropertyDescriptor(mocked.mockConstructor, 'propertyOne')?.get).toBe(mockedFunction); + mockedFunction = Object.getOwnPropertyDescriptor(mocked.mockConstructor, 'propertyOne')?.get; + + mocked.setup(defineStaticProperty('propertyOne', getterTwo)); + expect(Object.getOwnPropertyDescriptor(mocked.mockConstructor, 'propertyOne')?.get).toBe(mockedFunction); + expect(mocked.mockConstructor.propertyOne).toEqual('getterTwo'); + }); }); describe('mockedStaticFunctions', () => { @@ -1401,6 +1447,32 @@ describe('mock with statics', () => { ); }); + it('should not change function object on mock when setupFunction called twice', () => { + // underlying function should change but mock function should not + // this is to avoid issues when function is imported once and we change implementation after initial setup + + function mockFunctionOne(paramOne: string, paramTwo?: number, paramThree?: boolean) { + return `mockedReturnValue_${paramOne}_${paramTwo}_${paramThree}`; + } + + function mockFunctionTwo(paramOne: string, paramTwo?: number, paramThree?: boolean) { + return `mockedReturnValue_${paramOne}_${paramTwo}_${paramThree}`; + } + + mocked.setup(setupStaticFunction('functionWithParamsAndReturn')); + let mockedFunction = mocked.mockConstructor.functionWithParamsAndReturn; + + mocked.setup(setupStaticFunction('functionWithParamsAndReturn', mockFunctionOne)); + expect(mocked.mockConstructor.functionWithParamsAndReturn).toBe(mockedFunction); + mockedFunction = mocked.mockConstructor.functionWithParamsAndReturn; + + mocked.setup(setupStaticFunction('functionWithParamsAndReturn', mockFunctionTwo)); + expect(mocked.mockConstructor.functionWithParamsAndReturn).toBe(mockedFunction); + expect(mocked.mockConstructor.functionWithParamsAndReturn('one', 2, true)).toEqual( + 'mockedReturnValue_one_2_true', + ); + }); + it('chaining setup functions should be supported', () => { const newMock = Mock.create().setup( setupStaticFunction('functionWithNoParamsAndNoReturn'), diff --git a/spec/mock/mock.spec.ts b/spec/mock/mock.spec.ts index 80f5514..cd241be 100644 --- a/spec/mock/mock.spec.ts +++ b/spec/mock/mock.spec.ts @@ -28,6 +28,167 @@ describe('mock', () => { mock = mocked.mock; }); + describe('lookups', () => { + it('function lookup should be typed correctly', () => { + expect(mocked.functionCallLookup.functionWithParamsAndNoReturn).toBeUndefined(); + + mocked.setupFunction('functionWithParamsAndNoReturn'); + + expect(mocked.functionCallLookup.functionWithParamsAndNoReturn).toBeDefined(); + + mock.functionWithParamsAndNoReturn('one', 2, true); + + if (mocked.functionCallLookup.functionWithParamsAndNoReturn != null) { + const firstCall = mocked.functionCallLookup.functionWithParamsAndNoReturn[0]; + + const firstParam: string = firstCall[0]; + const secondParam: number = firstCall[1]; + const thirdParam: boolean | undefined = firstCall[2]; + + expect(firstParam).toBe('one'); + expect(secondParam).toBe(2); + expect(thirdParam).toBe(true); + } + }); + + it('setter lookup should be typed correctly', () => { + expect(mocked.setterCallLookup.propertyOne).toBeUndefined(); + expect(mocked.setterCallLookup.propertyTwo).toBeUndefined(); + + mocked.setupProperty('propertyOne'); + mocked.setupProperty('propertyTwo'); + + expect(mocked.setterCallLookup.propertyOne).toBeDefined(); + expect(mocked.setterCallLookup.propertyTwo).toBeDefined(); + + mock.propertyOne = 'valueOne'; + mock.propertyTwo = 2; + + if (mocked.setterCallLookup.propertyOne != null) { + const firstCall = mocked.setterCallLookup.propertyOne[0]; + const param: string = firstCall[0]; + + expect(param).toBe('valueOne'); + } + + if (mocked.setterCallLookup.propertyTwo != null) { + const firstCall = mocked.setterCallLookup.propertyTwo[0]; + const param: number = firstCall[0]; + + expect(param).toBe(2); + } + }); + + it('getter lookup should be typed correctly', () => { + expect(mocked.getterCallLookup.propertyOne).toBeUndefined(); + expect(mocked.getterCallLookup.propertyTwo).toBeUndefined(); + + mocked.setupProperty('propertyOne'); + mocked.setupProperty('propertyTwo'); + + expect(mocked.getterCallLookup.propertyOne).toBeDefined(); + expect(mocked.getterCallLookup.propertyTwo).toBeDefined(); + + const propOneValue = mock.propertyOne; + const propTwoValue = mock.propertyTwo; + + expect(propOneValue).toBeUndefined(); + expect(propTwoValue).toBeUndefined(); + + if (mocked.getterCallLookup.propertyOne != null) { + const firstCall = mocked.getterCallLookup.propertyOne[0]; + + expect(firstCall).toBeDefined(); + } + + if (mocked.getterCallLookup.propertyTwo != null) { + const firstCall = mocked.getterCallLookup.propertyTwo[0]; + + expect(firstCall).toBeDefined(); + } + }); + + it('static function lookup should be typed correctly', () => { + expect(mocked.staticFunctionCallLookup.doStuffWithParams).toBeUndefined(); + + mocked.setupStaticFunction('doStuffWithParams'); + + expect(mocked.staticFunctionCallLookup.doStuffWithParams).toBeDefined(); + + mocked.mockConstructor.doStuffWithParams('one', 2, true); + + if (mocked.staticFunctionCallLookup.doStuffWithParams != null) { + const firstCall = mocked.staticFunctionCallLookup.doStuffWithParams[0]; + + const firstParam: string = firstCall[0]; + const secondParam: number = firstCall[1]; + // @ts-expect-error type is actually boolean | undefined; + const thirdParam: boolean | undefined = firstCall[2]; + + expect(firstParam).toBe('one'); + expect(secondParam).toBe(2); + expect(thirdParam).toBe(true); + } + }); + + it('static setter lookup should be typed correctly', () => { + expect(mocked.staticSetterCallLookup.propertyOne).toBeUndefined(); + expect(mocked.staticSetterCallLookup.propertyTwo).toBeUndefined(); + + mocked.setupStaticProperty('propertyOne'); + mocked.setupStaticProperty('propertyTwo'); + + expect(mocked.staticSetterCallLookup.propertyOne).toBeDefined(); + expect(mocked.staticSetterCallLookup.propertyTwo).toBeDefined(); + + mocked.mockConstructor.propertyOne = 'valueOne'; + mocked.mockConstructor.propertyTwo = 2; + + if (mocked.staticSetterCallLookup.propertyOne != null) { + const firstCall = mocked.staticSetterCallLookup.propertyOne[0]; + const param: string = firstCall[0]; + + expect(param).toBe('valueOne'); + } + + if (mocked.staticSetterCallLookup.propertyTwo != null) { + const firstCall = mocked.staticSetterCallLookup.propertyTwo[0]; + const param: number = firstCall[0]; + + expect(param).toBe(2); + } + }); + + it('static getter lookup should be typed correctly', () => { + expect(mocked.staticGetterCallLookup.propertyOne).toBeUndefined(); + expect(mocked.staticGetterCallLookup.propertyTwo).toBeUndefined(); + + mocked.setupStaticProperty('propertyOne'); + mocked.setupStaticProperty('propertyTwo'); + + expect(mocked.staticGetterCallLookup.propertyOne).toBeDefined(); + expect(mocked.staticGetterCallLookup.propertyTwo).toBeDefined(); + + const propOneValue = mocked.mockConstructor.propertyOne; + const propTwoValue = mocked.mockConstructor.propertyTwo; + + expect(propOneValue).toBeUndefined(); + expect(propTwoValue).toBeUndefined(); + + if (mocked.staticGetterCallLookup.propertyOne != null) { + const firstCall = mocked.staticGetterCallLookup.propertyOne[0]; + + expect(firstCall).toBeDefined(); + } + + if (mocked.staticGetterCallLookup.propertyTwo != null) { + const firstCall = mocked.staticGetterCallLookup.propertyTwo[0]; + + expect(firstCall).toBeDefined(); + } + }); + }); + describe('setup', () => { it('withFunction will fail with a meaningful error if we try to assert a function that is not setup', () => { verifyFailure( @@ -1455,6 +1616,52 @@ describe('mock', () => { mocked.mock.propertyOne = 'testTwo'; expect(values).toEqual(['testOne', 'testTwo']); }); + + it('should not change setter on mock when defineProperty called twice', () => { + const values: string[] = []; + + function setterOne(value: string) { + values.push(`${value}_setterOne`); + } + + function setterTwo(value: string) { + values.push(`${value}_setterTwo`); + } + + mocked.setup(defineProperty('propertyOne', () => 'mockedValue')); + let mockedFunction = Object.getOwnPropertyDescriptor(mock, 'propertyOne')?.set; + + mocked.setup(defineProperty('propertyOne', () => 'mockedValue', setterOne)); + expect(Object.getOwnPropertyDescriptor(mock, 'propertyOne')?.set).toBe(mockedFunction); + mockedFunction = Object.getOwnPropertyDescriptor(mock, 'propertyOne')?.set; + + mocked.setup(defineProperty('propertyOne', () => 'mockedValue', setterTwo)); + expect(Object.getOwnPropertyDescriptor(mock, 'propertyOne')?.set).toBe(mockedFunction); + expect(values).toEqual([]); + mocked.mock.propertyOne = 'testOne'; + expect(values).toEqual(['testOne_setterTwo']); + }); + + it('should not change getter on mock when defineProperty called twice', () => { + function getterOne() { + return 'getterOne'; + } + + function getterTwo() { + return 'getterTwo'; + } + + mocked.setup(defineProperty('propertyOne')); + let mockedFunction = Object.getOwnPropertyDescriptor(mock, 'propertyOne')?.get; + + mocked.setup(defineProperty('propertyOne', getterOne)); + expect(Object.getOwnPropertyDescriptor(mock, 'propertyOne')?.get).toBe(mockedFunction); + mockedFunction = Object.getOwnPropertyDescriptor(mock, 'propertyOne')?.get; + + mocked.setup(defineProperty('propertyOne', getterTwo)); + expect(Object.getOwnPropertyDescriptor(mock, 'propertyOne')?.get).toBe(mockedFunction); + expect(mocked.mock.propertyOne).toEqual('getterTwo'); + }); }); describe('mockedFunctions', () => { @@ -1480,17 +1687,41 @@ describe('mock', () => { it('should changed implementation when setupFunction called a second time', () => { function mockFunctionOne() { - return `mockFunctionOne`; + return `mockFunctionOneReturnValue`; } function mockFunctionTwo() { - return `mockFunctionTwo`; + return `mockFunctionTwoReturnValue`; } mocked.setup(setupFunction('functionWithParamsAndReturn', mockFunctionOne)); mocked.setup(setupFunction('functionWithParamsAndReturn', mockFunctionTwo)); - expect(mock.functionWithParamsAndReturn('one', 2, true)).toEqual('mockFunctionTwo'); + expect(mock.functionWithParamsAndReturn('one', 2, true)).toEqual('mockFunctionTwoReturnValue'); + }); + + it('should not change function object on mock when setupFunction called twice', () => { + // underlying function should change but mock function should not + // this is to avoid issues when function is imported once and we change implementation after initial setup + + function mockFunctionOne() { + return `mockFunctionOneReturnValue`; + } + + function mockFunctionTwo() { + return `mockFunctionTwoReturnValue`; + } + + mocked.setup(setupFunction('functionWithParamsAndReturn')); + let mockedFunction = mock.functionWithParamsAndReturn; + + mocked.setup(setupFunction('functionWithParamsAndReturn', mockFunctionOne)); + expect(mock.functionWithParamsAndReturn).toBe(mockedFunction); + mockedFunction = mock.functionWithParamsAndReturn; + + mocked.setup(setupFunction('functionWithParamsAndReturn', mockFunctionTwo)); + expect(mock.functionWithParamsAndReturn).toBe(mockedFunction); + expect(mock.functionWithParamsAndReturn('one', 2, true)).toEqual('mockFunctionTwoReturnValue'); }); it('chaining setup functions should be supported', () => { @@ -1914,9 +2145,11 @@ describe('mock', () => { class SampleMockedClass { public static propertyOne = ''; + public static propertyTwo = 2; // tslint:disable-next-line:no-empty public static doStuff() {} + public static doStuffWithParams(_paramOne: string, _paramTwo: number, _paramThree?: boolean) {} public propertyOne: string = 'mocked'; public propertyTwo: number = 123;