Skip to content

Commit

Permalink
perf: cc cognitive complexity
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Nov 23, 2020
1 parent 4e81ff9 commit 74783a9
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 61 deletions.
127 changes: 67 additions & 60 deletions lib/common/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,73 @@

import { EventEmitter, Injector, Optional } from '@angular/core';
import { NgControl } from '@angular/forms';
import { AnyType } from 'ng-mocks/dist/lib/common/core.types';

import { IMockBuilderConfig } from '../mock-builder/types';
import mockServiceHelper from '../mock-service/helper';

import ngMocksUniverse from './ng-mocks-universe';

const applyNgValueAccessor = (instance: Mock, injector?: Injector) => {
if (injector && instance.__ngMocksConfig && instance.__ngMocksConfig.setNgValueAccessor) {
try {
const ngControl = (injector.get as any)(/* A5 */ NgControl, undefined, 0b1010);
if (ngControl && !ngControl.valueAccessor) {
ngControl.valueAccessor = instance;
}
} catch (e) {
// nothing to do.
}
}
};

const applyOutputs = (instance: Mock & Record<keyof any, any>) => {
const mockOutputs = [];
for (const output of instance.__ngMocksConfig?.outputs || []) {
mockOutputs.push(output.split(':')[0]);
}

for (const output of mockOutputs) {
if (instance[output] || Object.getOwnPropertyDescriptor(instance, output)) {
continue;
}
instance[output] = new EventEmitter<any>();
}
};

const applyPrototype = (instance: Mock, prototype: AnyType<any>) => {
for (const prop of [
...mockServiceHelper.extractMethodsFromPrototype(prototype),
...mockServiceHelper.extractPropertiesFromPrototype(prototype),
]) {
const descriptor = mockServiceHelper.extractPropertyDescriptor(prototype, prop);
/* istanbul ignore next */
if (!descriptor) {
continue;
}
Object.defineProperty(instance, prop, descriptor);
}
};

const applyMethods = (instance: Mock, prototype: AnyType<any>) => {
for (const method of mockServiceHelper.extractMethodsFromPrototype(prototype)) {
if ((this as any)[method] || Object.getOwnPropertyDescriptor(this, method)) {
continue;
}
mockServiceHelper.mock(instance, method);
}
};

const applyProps = (instance: Mock, prototype: AnyType<any>) => {
for (const prop of mockServiceHelper.extractPropertiesFromPrototype(prototype)) {
if ((this as any)[prop] || Object.getOwnPropertyDescriptor(this, prop)) {
continue;
}
mockServiceHelper.mock(instance, prop, 'get');
mockServiceHelper.mock(instance, prop, 'set');
}
};

export type ngMocksMockConfig = {
config?: IMockBuilderConfig;
outputs?: string[];
Expand All @@ -16,71 +77,17 @@ export type ngMocksMockConfig = {
};

export class Mock {
public readonly __ngMocksConfig?: ngMocksMockConfig;
public readonly __ngMocksMock: true = true;

protected readonly __ngMocksConfig?: ngMocksMockConfig;

public constructor(@Optional() injector?: Injector) {
const mockOf = (this.constructor as any).mockOf;

if (injector && this.__ngMocksConfig && this.__ngMocksConfig.setNgValueAccessor) {
try {
const ngControl = (injector.get as any)(/* A5 */ NgControl, undefined, 0b1010);
if (ngControl && !ngControl.valueAccessor) {
ngControl.valueAccessor = this;
}
} catch (e) {
// nothing to do.
}
}

// setting outputs

const mockOutputs = [];
for (const output of this.__ngMocksConfig && this.__ngMocksConfig.outputs ? this.__ngMocksConfig.outputs : []) {
mockOutputs.push(output.split(':')[0]);
}

for (const output of mockOutputs) {
if ((this as any)[output] || Object.getOwnPropertyDescriptor(this, output)) {
continue;
}
(this as any)[output] = new EventEmitter<any>();
}

// setting our mock methods and props
const prototype = Object.getPrototypeOf(this);
for (const method of mockServiceHelper.extractMethodsFromPrototype(prototype)) {
const descriptor = mockServiceHelper.extractPropertyDescriptor(prototype, method);
/* istanbul ignore next */
if (!descriptor) {
continue;
}
Object.defineProperty(this, method, descriptor);
}
for (const prop of mockServiceHelper.extractPropertiesFromPrototype(prototype)) {
const descriptor = mockServiceHelper.extractPropertyDescriptor(prototype, prop);
/* istanbul ignore next */
if (!descriptor) {
continue;
}
Object.defineProperty(this, prop, descriptor);
}

// setting mocks for original class methods and props
for (const method of mockServiceHelper.extractMethodsFromPrototype(mockOf.prototype)) {
if ((this as any)[method] || Object.getOwnPropertyDescriptor(this, method)) {
continue;
}
mockServiceHelper.mock(this, method);
}
for (const prop of mockServiceHelper.extractPropertiesFromPrototype(mockOf.prototype)) {
if ((this as any)[prop] || Object.getOwnPropertyDescriptor(this, prop)) {
continue;
}
mockServiceHelper.mock(this, prop, 'get');
mockServiceHelper.mock(this, prop, 'set');
}
applyNgValueAccessor(this, injector);
applyOutputs(this);
applyPrototype(this, Object.getPrototypeOf(this));
applyMethods(this, mockOf.prototype);
applyProps(this, mockOf.prototype);

// and faking prototype
Object.setPrototypeOf(this, mockOf.prototype);
Expand Down
2 changes: 1 addition & 1 deletion lib/mock/decorate-declaration.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Component, Directive, Provider, ViewChild } from '@angular/core';
import ngMocksUniverse from 'ng-mocks/dist/lib/common/ng-mocks-universe';

import { AnyType } from '../common/core.types';
import decorateInputs from '../common/decorate.inputs';
import decorateOutputs from '../common/decorate.outputs';
import decorateQueries from '../common/decorate.queries';
import { MockOf } from '../common/mock-of';
import ngMocksUniverse from '../common/ng-mocks-universe';
import mockServiceHelper from '../mock-service/helper';
import cloneProviders from '../mock/clone-providers';
import toExistingProvider from '../mock/to-existing-provider';
Expand Down

0 comments on commit 74783a9

Please sign in to comment.