Skip to content

Commit

Permalink
fix(#354): better error instead of is not in JIT mode
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Apr 6, 2021
1 parent d8fa51c commit 45f05fb
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 1 deletion.
5 changes: 5 additions & 0 deletions libs/ng-mocks/src/lib/common/func.import-exists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default (value: any, funcName: string) => {
if (value === undefined || value === null) {
throw new Error(`An empty parameter has been passed into ${funcName}. Please check that its import is correct.`);
}
};
3 changes: 3 additions & 0 deletions libs/ng-mocks/src/lib/mock-component/mock-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { extendClass } from '../common/core.helpers';
import coreReflectDirectiveResolve from '../common/core.reflect.directive-resolve';
import { Type } from '../common/core.types';
import { getMockedNgDefOf } from '../common/func.get-mocked-ng-def-of';
import funcImportExists from '../common/func.import-exists';
import funcIsMock from '../common/func.is-mock';
import { MockConfig } from '../common/mock';
import { LegacyControlValueAccessor } from '../common/mock-control-value-accessor';
Expand Down Expand Up @@ -216,6 +217,8 @@ export function MockComponents(...components: Array<Type<any>>): Array<Type<Mock
* @see https://ng-mocks.sudo.eu/api/MockComponent
*/
export function MockComponent<TComponent>(component: Type<TComponent>): Type<MockedComponent<TComponent>> {
funcImportExists(component, 'MockComponent');

// We are inside of an 'it'. It is fine to to return a mock copy.
if ((getTestBed() as any)._instantiated) {
try {
Expand Down
3 changes: 3 additions & 0 deletions libs/ng-mocks/src/lib/mock-directive/mock-directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { extendClass } from '../common/core.helpers';
import coreReflectDirectiveResolve from '../common/core.reflect.directive-resolve';
import { Type } from '../common/core.types';
import { getMockedNgDefOf } from '../common/func.get-mocked-ng-def-of';
import funcImportExists from '../common/func.import-exists';
import { LegacyControlValueAccessor } from '../common/mock-control-value-accessor';
import ngMocksUniverse from '../common/ng-mocks-universe';
import decorateDeclaration from '../mock/decorate-declaration';
Expand Down Expand Up @@ -103,6 +104,8 @@ export function MockDirectives(...directives: Array<Type<any>>): Array<Type<Mock
* @see https://ng-mocks.sudo.eu/api/MockDirective
*/
export function MockDirective<TDirective>(directive: Type<TDirective>): Type<MockedDirective<TDirective>> {
funcImportExists(directive, 'MockDirective');

// We are inside of an 'it'.
// It is fine to to return a mock copy or to throw an exception if it was not replaced with its mock copy in TestBed.
if ((getTestBed() as any)._instantiated) {
Expand Down
3 changes: 3 additions & 0 deletions libs/ng-mocks/src/lib/mock-instance/mock-instance.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { InjectionToken, Injector } from '@angular/core';

import { AbstractType, Type } from '../common/core.types';
import funcImportExists from '../common/func.import-exists';
import ngMocksUniverse from '../common/ng-mocks-universe';

const stack: any[][] = [[]];
Expand Down Expand Up @@ -187,6 +188,8 @@ export function MockInstance<T>(
): void;

export function MockInstance<T>(declaration: Type<T> | AbstractType<T> | InjectionToken<T>, ...args: any[]) {
funcImportExists(declaration, 'MockInstance');

const { key, value, accessor, data } = parseMockInstanceArgs(args);
if (key) {
return mockInstanceMember(declaration, key, value, accessor);
Expand Down
3 changes: 3 additions & 0 deletions libs/ng-mocks/src/lib/mock-module/mock-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import coreReflectModuleResolve from '../common/core.reflect.module-resolve';
import { Type } from '../common/core.types';
import decorateMock from '../common/decorate.mock';
import { getMockedNgDefOf } from '../common/func.get-mocked-ng-def-of';
import funcImportExists from '../common/func.import-exists';
import { isNgDef } from '../common/func.is-ng-def';
import { isNgModuleDefWithProviders, NgModuleWithProviders } from '../common/func.is-ng-module-def-with-providers';
import { Mock } from '../common/mock';
Expand Down Expand Up @@ -153,6 +154,8 @@ export function MockModule<T>(module: Type<T>): Type<T>;
export function MockModule<T>(module: NgModuleWithProviders<T>): NgModuleWithProviders<T>;

export function MockModule(module: any): any {
funcImportExists(module, 'MockModule');

const { ngModule, ngModuleProviders } = extractModuleAndProviders(module);

// We are inside of an 'it'. It is fine to to return a mock copy.
Expand Down
3 changes: 3 additions & 0 deletions libs/ng-mocks/src/lib/mock-pipe/mock-pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import coreReflectPipeResolve from '../common/core.reflect.pipe-resolve';
import { Type } from '../common/core.types';
import decorateMock from '../common/decorate.mock';
import { getMockedNgDefOf } from '../common/func.get-mocked-ng-def-of';
import funcImportExists from '../common/func.import-exists';
import { Mock } from '../common/mock';
import ngMocksUniverse from '../common/ng-mocks-universe';
import helperMockService from '../mock-service/helper.mock-service';
Expand Down Expand Up @@ -48,6 +49,8 @@ export function MockPipe<TPipe extends PipeTransform>(
pipe: Type<TPipe>,
transform?: TPipe['transform'],
): Type<MockedPipe<TPipe>> {
funcImportExists(pipe, 'MockPipe');

// We are inside of an 'it'. It is fine to return a mock copy.
if ((getTestBed() as any)._instantiated) {
try {
Expand Down
3 changes: 3 additions & 0 deletions libs/ng-mocks/src/lib/mock-provider/mock-provider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FactoryProvider, InjectionToken, Provider } from '@angular/core';

import { AnyType } from '../common/core.types';
import funcImportExists from '../common/func.import-exists';
import mockHelperStub from '../mock-helper/mock-helper.stub';
import helperUseFactory from '../mock-service/helper.use-factory';
import { MockService } from '../mock-service/mock-service';
Expand All @@ -27,6 +28,8 @@ export function MockProvider<I>(provider: InjectionToken<I> | string, useValue?:
export function MockProvider<I = any>(provider: string, useValue?: Partial<I>): FactoryProvider;

export function MockProvider(provide: any, overrides: any = defaultValue): Provider {
funcImportExists(provide, 'MockProvider');

return helperUseFactory(
provide,
() => MockService(provide),
Expand Down
3 changes: 3 additions & 0 deletions libs/ng-mocks/src/lib/mock-render/mock-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { extendClass } from '../common/core.helpers';
import coreReflectDirectiveResolve from '../common/core.reflect.directive-resolve';
import { AnyType, Type } from '../common/core.types';
import funcImportExists from '../common/func.import-exists';
import { isNgDef } from '../common/func.is-ng-def';
import { ngMocks } from '../mock-helper/mock-helper';
import { MockService } from '../mock-service/mock-service';
Expand Down Expand Up @@ -220,6 +221,8 @@ function MockRender<MComponent, TComponent extends Record<keyof any, any>>(
params?: TComponent,
flags: boolean | IMockRenderOptions = true,
): any {
funcImportExists(template, 'MockRender');

const flagsObject: IMockRenderOptions = typeof flags === 'boolean' ? { detectChanges: flags } : flags;
const meta: Directive = typeof template === 'string' || isNgDef(template, 't') ? {} : reflectTemplate(template);

Expand Down
74 changes: 74 additions & 0 deletions tests/issue-354/test.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
MockComponent,
MockDirective,
MockInstance,
MockModule,
MockPipe,
MockProvider,
MockRender,
} from 'ng-mocks';

describe('issue-354', () => {
it('does not accept an empty module', () => {
expect(() => MockModule(undefined as any)).toThrowError(
'An empty parameter has been passed into MockModule. Please check that its import is correct.',
);
expect(() => MockModule(null as any)).toThrowError(
'An empty parameter has been passed into MockModule. Please check that its import is correct.',
);
});

it('does not accept an empty component', () => {
expect(() => MockComponent(undefined as any)).toThrowError(
'An empty parameter has been passed into MockComponent. Please check that its import is correct.',
);
expect(() => MockComponent(null as any)).toThrowError(
'An empty parameter has been passed into MockComponent. Please check that its import is correct.',
);
});

it('does not accept an empty directive', () => {
expect(() => MockDirective(undefined as any)).toThrowError(
'An empty parameter has been passed into MockDirective. Please check that its import is correct.',
);
expect(() => MockDirective(null as any)).toThrowError(
'An empty parameter has been passed into MockDirective. Please check that its import is correct.',
);
});

it('does not accept an empty pipe', () => {
expect(() => MockPipe(undefined as any)).toThrowError(
'An empty parameter has been passed into MockPipe. Please check that its import is correct.',
);
expect(() => MockPipe(null as any)).toThrowError(
'An empty parameter has been passed into MockPipe. Please check that its import is correct.',
);
});

it('does not accept an empty provider', () => {
expect(() => MockProvider(undefined as any)).toThrowError(
'An empty parameter has been passed into MockProvider. Please check that its import is correct.',
);
expect(() => MockProvider(null as any)).toThrowError(
'An empty parameter has been passed into MockProvider. Please check that its import is correct.',
);
});

it('does not accept an empty render', () => {
expect(() => MockRender(undefined as any)).toThrowError(
'An empty parameter has been passed into MockRender. Please check that its import is correct.',
);
expect(() => MockRender(null as any)).toThrowError(
'An empty parameter has been passed into MockRender. Please check that its import is correct.',
);
});

it('does not accept an empty instance', () => {
expect(() => MockInstance(undefined as any)).toThrowError(
'An empty parameter has been passed into MockInstance. Please check that its import is correct.',
);
expect(() => MockInstance(null as any)).toThrowError(
'An empty parameter has been passed into MockInstance. Please check that its import is correct.',
);
});
});
2 changes: 1 addition & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"max-file-line-count": [true, 250],
"max-func-body-length": [
true,
25,
30,
{
"ignore-parameters-to-function-regex": "^(([fx]?(describe|it))|beforeEach|fakeAsync|inject)$"
}
Expand Down

0 comments on commit 45f05fb

Please sign in to comment.