From ef00cd830401039cac6f4b62d8151dd32c31c58d Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 4 Nov 2021 14:57:41 +0100 Subject: [PATCH] MOBILE-3896 test: Allow using existing instance to mock class --- src/core/directives/tests/format-text.test.ts | 11 ++++-- src/testing/utils.ts | 38 ++++++++++++------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/core/directives/tests/format-text.test.ts b/src/core/directives/tests/format-text.test.ts index f55b01f99..8be19f17e 100644 --- a/src/core/directives/tests/format-text.test.ts +++ b/src/core/directives/tests/format-text.test.ts @@ -26,6 +26,7 @@ import { CoreSites } from '@services/sites'; import { CoreUtils } from '@services/utils/utils'; import { mock, mockSingleton, RenderConfig, renderTemplate, renderWrapperComponent } from '@/testing/utils'; +import { CoreDB } from '@services/db'; describe('CoreFormatTextDirective', () => { @@ -121,11 +122,13 @@ describe('CoreFormatTextDirective', () => { it('should use external-content directive on images', async () => { // Arrange - const site = mock({ - getId: () => '42', + mockSingleton(CoreDB, { + getDB: () => undefined, + }); + + let site = new CoreSite('42', 'https://mysite.com', 'token'); + site = mock(site, { canDownloadFiles: () => true, - isVersionGreaterEqualThan: () => true, - isSitePluginFileUrl: () => false, }); // @todo this is done because we cannot mock image being loaded, we should find an alternative... diff --git a/src/testing/utils.ts b/src/testing/utils.ts index a6ec2613b..4b8ecadd9 100644 --- a/src/testing/utils.ts +++ b/src/testing/utils.ts @@ -126,16 +126,25 @@ export interface RenderConfig { export type WrapperComponentFixture = ComponentFixture>; -export function mock(instance?: Record): T; -export function mock(methods: string[], instance?: Record): T; +/** + * Mock a certain class, converting its methods to Mock functions and overriding the specified properties and methods. + * + * @param instance Instance to mock. + * @param overrides Object with the properties or methods to override, or a list of methods to override with an empty function. + * @return Mock instance. + */ +export function mock(instance?: T, overrides?: string[] | Record): T; +export function mock(instance?: Partial, overrides?: string[] | Record): Partial; export function mock( - methodsOrInstance: string[] | Record = [], - instance: Record = {}, -): T { - instance = Array.isArray(methodsOrInstance) ? instance : methodsOrInstance; - - const methods = Array.isArray(methodsOrInstance) ? methodsOrInstance : []; + instance: T | Partial = {}, + overrides: string[] | Record = {}, +): T | Partial { + // If overrides is an object, apply them to the instance. + if (!Array.isArray(overrides)) { + Object.assign(instance, overrides); + } + // Convert instance functions to jest functions. for (const property of Object.getOwnPropertyNames(instance)) { const value = instance[property]; @@ -146,11 +155,14 @@ export function mock( instance[property] = jest.fn((...args) => value.call(instance, ...args)); } - for (const method of methods) { - instance[method] = jest.fn(); + // If overrides is a list of methods, add them now. + if (Array.isArray(overrides)) { + for (const method of overrides) { + instance[method] = jest.fn(); + } } - return instance as T; + return instance; } export function mockSingleton(singletonClass: CoreSingletonProxy, instance: T): T; @@ -168,8 +180,8 @@ export function mockSingleton( properties = Array.isArray(methodsOrProperties) ? properties : methodsOrProperties; const methods = Array.isArray(methodsOrProperties) ? methodsOrProperties : []; - const instance = getServiceInstance(singleton.injectionToken); - const mockInstance = mock(methods, instance); + const instance = getServiceInstance(singleton.injectionToken) as T; + const mockInstance = mock(instance, methods); Object.assign(mockInstance, properties);