Merge pull request #2987 from dpalou/MOBILE-3896

MOBILE-3896 test: Allow using existing instance to mock class
main
Noel De Martin 2021-11-04 16:16:56 +01:00 committed by GitHub
commit 13509e6683
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 17 deletions

View File

@ -26,6 +26,7 @@ import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { mock, mockSingleton, RenderConfig, renderTemplate, renderWrapperComponent } from '@/testing/utils'; import { mock, mockSingleton, RenderConfig, renderTemplate, renderWrapperComponent } from '@/testing/utils';
import { CoreDB } from '@services/db';
describe('CoreFormatTextDirective', () => { describe('CoreFormatTextDirective', () => {
@ -121,11 +122,13 @@ describe('CoreFormatTextDirective', () => {
it('should use external-content directive on images', async () => { it('should use external-content directive on images', async () => {
// Arrange // Arrange
const site = mock<CoreSite>({ mockSingleton(CoreDB, {
getId: () => '42', getDB: () => undefined,
});
let site = new CoreSite('42', 'https://mysite.com', 'token');
site = mock(site, {
canDownloadFiles: () => true, canDownloadFiles: () => true,
isVersionGreaterEqualThan: () => true,
isSitePluginFileUrl: () => false,
}); });
// @todo this is done because we cannot mock image being loaded, we should find an alternative... // @todo this is done because we cannot mock image being loaded, we should find an alternative...

View File

@ -126,16 +126,25 @@ export interface RenderConfig {
export type WrapperComponentFixture<T> = ComponentFixture<WrapperComponent<T>>; export type WrapperComponentFixture<T> = ComponentFixture<WrapperComponent<T>>;
export function mock<T>(instance?: Record<string, unknown>): T; /**
export function mock<T>(methods: string[], instance?: Record<string, unknown>): 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<T>(instance?: T, overrides?: string[] | Record<string, unknown>): T;
export function mock<T>(instance?: Partial<T>, overrides?: string[] | Record<string, unknown>): Partial<T>;
export function mock<T>( export function mock<T>(
methodsOrInstance: string[] | Record<string, unknown> = [], instance: T | Partial<T> = {},
instance: Record<string, unknown> = {}, overrides: string[] | Record<string, unknown> = {},
): T { ): T | Partial<T> {
instance = Array.isArray(methodsOrInstance) ? instance : methodsOrInstance; // If overrides is an object, apply them to the instance.
if (!Array.isArray(overrides)) {
const methods = Array.isArray(methodsOrInstance) ? methodsOrInstance : []; Object.assign(instance, overrides);
}
// Convert instance functions to jest functions.
for (const property of Object.getOwnPropertyNames(instance)) { for (const property of Object.getOwnPropertyNames(instance)) {
const value = instance[property]; const value = instance[property];
@ -146,11 +155,14 @@ export function mock<T>(
instance[property] = jest.fn((...args) => value.call(instance, ...args)); instance[property] = jest.fn((...args) => value.call(instance, ...args));
} }
for (const method of methods) { // If overrides is a list of methods, add them now.
if (Array.isArray(overrides)) {
for (const method of overrides) {
instance[method] = jest.fn(); instance[method] = jest.fn();
} }
}
return instance as T; return instance;
} }
export function mockSingleton<T>(singletonClass: CoreSingletonProxy<T>, instance: T): T; export function mockSingleton<T>(singletonClass: CoreSingletonProxy<T>, instance: T): T;
@ -168,8 +180,8 @@ export function mockSingleton<T>(
properties = Array.isArray(methodsOrProperties) ? properties : methodsOrProperties; properties = Array.isArray(methodsOrProperties) ? properties : methodsOrProperties;
const methods = Array.isArray(methodsOrProperties) ? methodsOrProperties : []; const methods = Array.isArray(methodsOrProperties) ? methodsOrProperties : [];
const instance = getServiceInstance(singleton.injectionToken); const instance = getServiceInstance(singleton.injectionToken) as T;
const mockInstance = mock<T>(methods, instance); const mockInstance = mock(instance, methods);
Object.assign(mockInstance, properties); Object.assign(mockInstance, properties);