File

projects/ng-magic-test-bed/src/test-bed/ng-magic-setup-test-bed.class.ts

Constructor

constructor(initialConfig: TestModuleMetadata)
Parameters :
  • initialConfig

    initial config which will be extended by the other methods of this NgMagicSetupTestBed instance.
    The final config will be used to call TestBed.configureTestingModule implicitly by
    calling e.g. .injection()

Methods

Private configureTestingModule
configureTestingModule()
Returns: void
Private expectToBePreConfiguration
expectToBePreConfiguration()
Returns: void
Public declarations
declarations(declarations: any[])
Parameters :
Returns: void
Public declaration
declaration(declaration: any)
Parameters :
Returns: void
Public schemas
schemas(schemas: (any[] | SchemaMetadata)[])
Parameters :
Returns: void
Public schema
schema(schema: any[] | SchemaMetadata)
Parameters :
Returns: void
Public imports
imports(imports: any[])
Parameters :
Returns: void
Public import
import(aImport: any)
Parameters :
Returns: void
Public providers
providers(providers: any[])
Parameters :
Returns: void
Public provider
provider(provider: any)
Parameters :
Returns: void
Public pipeServiceMock
pipeServiceMock(pipeClass: Type, serviceClass: AbstractType, mock: M, dontSpy: true)

If you have pipe that provides a service you can mock it using this method.

Returns: S & M
Public pipeServiceMock
pipeServiceMock(pipeClass: Type, serviceClass: AbstractType, mock: M)

If you have pipe that provides a service you can mock it using this method.

Returns: any
Public pipeServiceMock
pipeServiceMock(pipeClass: Type, serviceClass: AbstractType)

If you have pipe that provides a service you can mock it using this method.

Returns: any
Public pipeServiceMock
pipeServiceMock(pipeClass: Type, serviceClass: AbstractType, mock: M, dontSpy: boolean)

If you have pipe that provides a service you can mock it using this method.

Parameters :
  • pipeClass

    the pipeClass is the reference of the class of your angular pipe.

  • serviceClass

    the serviceClass is the reference to the class of the service that you want to mock

  • mock

    the mock mocks the service and should implement a partial of the service class

  • dontSpy

    optional parameter to prevent the default spy creation on the mock using the prototype of the serviceClass

Returns: any
Public pipeProviderMock
pipeProviderMock(pipeClass: Type, token: any, mock: M, dontSpy: boolean, spySource: AbstractType)

If you have pipe that provides a provider you can mock it using this method.

Parameters :
  • pipeClass

    the pipeClass is the reference of the class of your angular pipe.

  • token

    the provider token that you want to mock

  • mock

    the mock

  • dontSpy

    optional parameter to prevent the default spy creation on the mock

Returns: M
Public directiveServiceMock
directiveServiceMock(directiveClass: Type, serviceClass: AbstractType, mock: M, dontSpy: true)

If you have directive that provides a service you can mock it using this method.

Parameters :
  • directiveClass

    the directiveClass is the reference of the class of your angular directive.

  • serviceClass

    the serviceClass is the reference to the class of the service that you want to mock

  • mock

    the mock mocks the service and should implement a partial of the service class

  • dontSpy

    optional parameter to prevent the default spy creation on the mock using the prototype of the serviceClass

Returns: S & M
Public directiveServiceMock
directiveServiceMock(directiveClass: Type, serviceClass: AbstractType, mock: M)

If you have directive that provides a service you can mock it using this method.

Returns: any
Public directiveServiceMock
directiveServiceMock(directiveClass: Type, serviceClass: AbstractType)

If you have directive that provides a service you can mock it using this method.

Returns: any
Public directiveServiceMock
directiveServiceMock(directiveClass: Type, serviceClass: AbstractType, mock: M, dontSpy: boolean)

If you have directive that provides a service you can mock it using this method.

Returns: any
Public directiveProviderMock
directiveProviderMock(directiveClass: Type, token: any, mock: M, dontSpy: boolean, spySource: AbstractType)

If you have directive that provides a provider you can mock it using this method.

Parameters :
  • directiveClass

    the directiveClass is the reference of the class of your angular directive.

  • token

    the provider token that you want to mock

  • mock

    the mock

  • dontSpy

    optional parameter to prevent the default spy creation on the mock

Returns: M
Public componentServiceMock
componentServiceMock(componentClass: Type, serviceClass: AbstractType, mock: M, dontSpy: true)

If you have component that provides a service you can mock it using this method.

Returns: S & M
Public componentServiceMock
componentServiceMock(componentClass: Type, serviceClass: AbstractType, mock: M)

If you have component that provides a service you can mock it using this method.

Returns: any
Public componentServiceMock
componentServiceMock(componentClass: Type, serviceClass: AbstractType)

If you have component that provides a service you can mock it using this method.

Returns: any
Public componentServiceMock
componentServiceMock(componentClass: Type, serviceClass: AbstractType, mock: M, dontSpy: boolean)

If you have component that provides a service you can mock it using this method.

Parameters :
  • componentClass

    the componentClass is the reference of the class of your angular component.

  • serviceClass

    the serviceClass is the reference to the class of the service that you want to mock

  • mock

    the mock mocks the service and should implement a partial of the service class

  • dontSpy

    optional parameter to prevent the default spy creation on the mock using the prototype of the serviceClass

Returns: any
Public componentProviderMock
componentProviderMock(componentClass: Type, token: any, mock: M, dontSpy: boolean, spySource: AbstractType)

If you have component provides a provider you can mock it using this method.

Parameters :
  • componentClass

    the componentClass is the reference of the class of your angular component.

  • token

    the provider token that you want to mock

  • mock

    the mock

  • dontSpy

    optional parameter to prevent the default spy creation on the mock

Returns: M
Private uiThingProviderMock
uiThingProviderMock(methodName: string, uiThingClass: Type, token: any, mock: M, dontSpy: boolean, spySource: AbstractType)
Returns: M
Public directiveMocks
directiveMocks(directiveClass: Type)
Returns: C[]
Public componentMocks
componentMocks(componentClass: Type)

declare that you want to mock a component for a selector and retrieve all created component mock instances after fixture
creation.

Parameters :
  • componentClass

    class of the component that should be used in the fixture for a specific selector you want to mock.

Returns: C[]

an arry of all component instances that were found statically inside the fixture. The array's members can only be
used after calling .fixture(). Before that time the array is initialized like this:
['this array can only be used after fixture called'].

Public fixture
fixture(componentClass: Type, initialInputs: Partial, disableNoErrorSchema: boolean)

Use this method to create a component fixture. This method may only be called once per NgMagicTestBed instance.

Parameters :
  • componentClass

    class of the root component you want to compile and create.

  • disableNoErrorSchema

    by default the NgMagicTestBed uses the NO_ERROR_SCHEMA of angular to prevent the compiler from
    throwing exceptions e.g. for missing or unknown inputs.

Returns: ComponentFixture<C>

a component fixture like standard TestBed.createComponent(componentClass) would have returned it.

Public objectMock
objectMock(objectClass: AbstractType, mock: M, dontSpy: true)

Can be used to create a mock for an object that should not be registered at angular TestBed.

Parameters :
  • objectClass

    This class' prototype will be used to extend the result mock by a spy for each method on the prototype.

  • mock

    An object that should implement partial of objectClass and contain all methods that you want to return something.

  • dontSpy

    optional parameter to prevent the default spy creation on the mock.

Returns: O & M

Your mocks methods will be overwritten with spies that call through to the mocks methods like jasmine's spyOn method.
In addition to that a spy will be added for each additional method that was found on the objectClass' prototype.

Public objectMock
objectMock(objectClass: AbstractType, mock: M)

Can be used to create a mock for an object that should not be registered at angular TestBed.

Returns: any
Public objectMock
objectMock(objectClass: undefined, mock: M)

Can be used to create a mock for an object that should not be registered at angular TestBed.

Returns: any
Public objectMock
objectMock(objectClass: AbstractType, mock: any, dontSpy: boolean)

Can be used to create a mock for an object that should not be registered at angular TestBed.

Returns: any
Public providerMock
providerMock(token: any, mock: Partial, dontSpy: boolean, spySource: AbstractType)

mocks a provider for a given token with a given mock. If wanted your mock can be extended by spies
from a given spySource class.

Parameters :
  • token

    token for provider provision

  • mock

    mock that will be registered for the token

  • dontSpy

    optional parameter to prevent the default spy creation on the mock.

  • spySource

    for each method in spySources prototype an additional jasmine spy will be created on the mock

Returns: void

Your mocks methods will be overwritten with spies that call through to the mocks methods like jasmine's spyOn method.
In addition to that a spy will be added for each additional method that was found on the objectClass' prototype.

Public factoryMock
factoryMock(factoryClass: AbstractType, instances: (M & I)[])

mocks a service that has a "create" method.

Parameters :
  • factoryClass

    service that has a "create" method that you want to mock.

  • instances

    will be returned by the mock this method return when "create" is called.
    The first call of mock.create() will return the first item in the instances-array and so on.

Returns: any

a mock for the factory. mock.create will return the one of the given instances every time it is called

Public serviceMock
serviceMock(serviceClass: AbstractType, mock: M, dontSpy: true)

mocks a service with the given mock

Returns: S & M
Public serviceMock
serviceMock(serviceClass: AbstractType, mock: M)

mocks a service with the given mock

Returns: any
Public serviceMock
serviceMock(serviceClass: AbstractType)

mocks a service with the given mock

Returns: any
Public serviceMock
serviceMock(serviceClass: AbstractType, mock: M, dontSpy: boolean)

mocks a service with the given mock

Parameters :
  • serviceClass

    service that you want to mock

  • mock

    that should mock the service. All methods on the mock will become spies. For each method on serviceClass'
    prototype another spy will be added to the mock.

  • dontSpy

    optional parameter to prevent the default spy creation on the mock.

Returns: any

the mock after creating some spies on it (if not disabled)

Private mock
mock(token: any, mock: M, dontSpy: boolean, spySource: AbstractType)
Returns: any
Public injection
injection(service: AbstractType)

return you the service or provider for a given token from the angular dependency injection.
This will trigger the TestBed configureTestingModule step. After this step you can not create any more mocks.
Make sure you create all your mocks before calling this mehtod.

Returns: S
Public injection
injection(token: any)

return you the service or provider for a given token from the angular dependency injection.
This will trigger the TestBed configureTestingModule step. After this step you can not create any more mocks.
Make sure you create all your mocks before calling this mehtod.

Returns: S
Public injection
injection(token: any)

return you the service or provider for a given token from the angular dependency injection.
This will trigger the TestBed configureTestingModule step. After this step you can not create any more mocks.
Make sure you create all your mocks before calling this mehtod.

Parameters :
  • serviceClass

    service that you want to inject

  • token

    of the prider that you want to inject

Returns: S
Public observer
observer(observable: any, name: string)

Subscribes to a given observable and spies on its states and emitted values.

Parameters :
  • observable

    Observable you want to spy

  • name

    Optional name that prefixes all jasmine spies that are created by the observer. This makes it easier to read the
    test output if anything fails.

Returns: SpyObserver<T>
  • observer that can be used to make assertions in your test cases e.g.:
    expect(observer.next).toHaveBeenCalledWith(expectedValue);
    For more information check SpyObserver documentation

Properties

Private compiled
compiled: boolean
Default value: false
Private config
config: FullTestModuleMetadata
Private configured
configured: boolean
Default value: false
Private fixtureInstance
fixtureInstance: ComponentFixture<any>
Default value: undefined
Private fixtureJobs
fixtureJobs: (() => void)[]
Private postConfigureJobs
postConfigureJobs: (() => void)[]
import { TestBed, TestModuleMetadata, ComponentFixture, MetadataOverride, ComponentFixtureAutoDetect } from '@angular/core/testing';
import { SchemaMetadata, Type, AbstractType, Component, NO_ERRORS_SCHEMA } from '@angular/core';
import { spyOnFunctionsOf } from '../spy-on-functions/spy-on-functions-of.function';
import { Observable } from 'rxjs';
import { observe } from '../observe/observe.function';
import { SpyObserver } from '../observe/spy-observer.class';
import { By } from '@angular/platform-browser';

export interface FullTestModuleMetadata extends TestModuleMetadata{
    providers: any[];
    declarations: any[];
    imports: any[];
    schemas: Array<SchemaMetadata | any[]>;
    teardown: {
        destroyAfterEach: boolean;
        rethrowErrors: boolean;
    };
    errorOnUnknownElements: boolean;
    errorOnUnknownProperties: boolean;
}

export interface IFactory<I> {
    create(...args: Array<any>): I;
}

export class NgMagicSetupTestBed {

    /**
    * @ignore
    */
    private config: FullTestModuleMetadata;

    /**
    * @ignore
    */
    private configured = false;

    /**
    * @ignore
    */
    private compiled = false;

    /**
    * @ignore
    */
    private postConfigureJobs: Array<() => void> = [];

    /**
    * @ignore
    */
    private fixtureJobs: Array<() => void> = [];

    /**
    * @ignore
    */
    private fixtureInstance?: ComponentFixture<any> = undefined;

    /**
    * @param initialConfig  initial config which will be extended by the other methods of this NgMagicSetupTestBed instance.
    *  The final config will be used to call TestBed.configureTestingModule implicitly by
    * calling e.g. .injection()
    */
    constructor(initialConfig: TestModuleMetadata = {}) {
        this.config = {
            providers: initialConfig.providers ? initialConfig.providers.slice() : [],
            declarations: initialConfig.declarations ? initialConfig.declarations.slice() : [],
            imports: initialConfig.imports ? initialConfig.imports.slice() : [],
            schemas: initialConfig.schemas ? initialConfig.schemas.slice() : [],
            errorOnUnknownElements: initialConfig.errorOnUnknownElements ?? false,
            errorOnUnknownProperties: initialConfig.errorOnUnknownProperties ?? false,
            teardown: {
                destroyAfterEach: initialConfig.teardown?.destroyAfterEach ?? true,
                rethrowErrors: initialConfig.teardown?.rethrowErrors ?? false
            }
        };
    }

    /**
    * @ignore
    */
    private configureTestingModule() {
        if (this.configured) {
            return;
        }
        this.configured = true;
        TestBed.configureTestingModule(this.config);
        this.postConfigureJobs.forEach(job => job());
        this.postConfigureJobs.length = 0;
    }

    /**
    * @ignore
    */
    private expectToBePreConfiguration() {
        if (this.configured) {
            throw new Error('The TestBed has been implicitly configured by calling e.g.' +
                '"injection" or "fixture" the method you called needs a not configured TestBed to be executed');
        }
    }

    /**
    * @param declarations declarations will be pushed to the declarations of the testing module config.
    * check out angular docs for more information
    * https://angular.io/guide/testing-services#angular-testbed
    * https://angular.io/api/core/testing/TestBed#configuretestingmodule
    * https://angular.io/api/core/testing/TestModuleMetadata
    */
    public declarations(declarations: Array<any>) {
        this.expectToBePreConfiguration();
        this.config.declarations.push(...declarations);
    }

    /**
    * @param declaration declaration will be pushed to the declarations of the testing module config.
    * check out angular docs for more information
    * https://angular.io/guide/testing-services#angular-testbed
    * https://angular.io/api/core/testing/TestBed#configuretestingmodule
    * https://angular.io/api/core/testing/TestModuleMetadata
    */
    public declaration(declaration: any) {
        this.declarations([declaration]);
    }

    /**
    * @param schemas schemas will be pushed to the schemas of the testing module config. Note that the NO_ERRORS_SCHEMA
    * is pushed by default. This can be disabled when calling .fixture().
    * check out angular docs for more information
    * https://angular.io/guide/testing-services#angular-testbed
    * https://angular.io/api/core/testing/TestBed#configuretestingmodule
    * https://angular.io/api/core/testing/TestModuleMetadata
    */
    public schemas(schemas: Array<SchemaMetadata | any[]>) {
        this.expectToBePreConfiguration();
        this.config.schemas.push(...schemas);
    }

    /**
    * @param schema schema will be pushed to the schemas of the testing module config. Note that the NO_ERRORS_SCHEMA
    * is pushed by default. This can be disabled when calling .fixture().
    * check out angular docs for more information
    * https://angular.io/guide/testing-services#angular-testbed
    * https://angular.io/api/core/testing/TestBed#configuretestingmodule
    * https://angular.io/api/core/testing/TestModuleMetadata
    */
    public schema(schema: SchemaMetadata | any[]) {
        this.schemas([schema]);
    }

    /**
    * @param imports imports will be pushed to the imports of the testing module config.
    * check out angular docs for more information
    * https://angular.io/guide/testing-services#angular-testbed
    * https://angular.io/api/core/testing/TestBed#configuretestingmodule
    * https://angular.io/api/core/testing/TestModuleMetadata
    */
    public imports(imports: any[]) {
        this.expectToBePreConfiguration();
        this.config.imports.push(...imports);
    }

    /**
    * @param imports import will be pushed to the imports of the testing module config.
    * check out angular docs for more information
    * https://angular.io/guide/testing-services#angular-testbed
    * https://angular.io/api/core/testing/TestBed#configuretestingmodule
    * https://angular.io/api/core/testing/TestModuleMetadata
    */
    public import(aImport: any) {
        this.imports([aImport]);
    }

    /**
    * @param providers providers will be pushed to the providers of the testing module config.
    * check out angular docs for more information
    * https://angular.io/guide/testing-services#angular-testbed
    * https://angular.io/api/core/testing/TestBed#configuretestingmodule
    * https://angular.io/api/core/testing/TestModuleMetadata
    */
    public providers(providers: any[]) {
        this.expectToBePreConfiguration();
        this.config.providers.push(...providers);
    }

    /**
    * @param provider import will be pushed to the providers of the testing module config.
    * check out angular docs for more information
    * https://angular.io/guide/testing-services#angular-testbed
    * https://angular.io/api/core/testing/TestBed#configuretestingmodule
    * https://angular.io/api/core/testing/TestModuleMetadata
    */
    public provider(provider: any) {
        this.providers([provider]);
    }

    public pipeServiceMock<S, M extends Partial<S>>(pipeClass: Type<any>, serviceClass: AbstractType<S>, mock: M,
        dontSpy: true): S & M;
    public pipeServiceMock<S, M extends Partial<S>>(pipeClass: Type<any>, serviceClass: AbstractType<S>, mock: M):
        jasmine.SpyObj<S> & M;
    public pipeServiceMock<S, M extends Partial<S>>(pipeClass: Type<any>, serviceClass: AbstractType<S>):
        jasmine.SpyObj<S>;
    /**
    *  If you have pipe that provides a service you can mock it using this method.
    * @param pipeClass the pipeClass is the reference of the class of your angular pipe.
    * @param serviceClass the serviceClass is the reference to the class of the service that you want to mock
    * @param mock the mock mocks the service and should implement a partial of the service class
    * @param dontSpy optional parameter to prevent the default spy creation on the mock using the prototype of the serviceClass
    */
    public pipeServiceMock<S, M extends Partial<S>>(pipeClass: Type<any>, serviceClass: AbstractType<S>,
        mock?: M, dontSpy?: boolean):
        jasmine.SpyObj<S> & M | S & M | jasmine.SpyObj<S> | S  {
        return <any> this.componentProviderMock(pipeClass, serviceClass, mock, dontSpy, serviceClass);
    }

    /**
     *  If you have pipe that provides a provider you can mock it using this method.
     * @param pipeClass the pipeClass is the reference of the class of your angular pipe.
     * @param token the provider token that you want to mock
     * @param mock the mock
     * @param dontSpy optional parameter to prevent the default spy creation on the mock
     */
    public pipeProviderMock<M>(pipeClass: Type<any>, token: any, mock: M, dontSpy = false,
        spySource?: AbstractType<any>): M {
        return this.uiThingProviderMock('overridePipe', pipeClass, token, mock, dontSpy, spySource);
    }

    /**
    * If you have directive that provides a service you can mock it using this method.
    * @param directiveClass the directiveClass is the reference of the class of your angular directive.
    * @param serviceClass the serviceClass is the reference to the class of the service that you want to mock
    * @param mock the mock mocks the service and should implement a partial of the service class
    * @param dontSpy optional parameter to prevent the default spy creation on the mock using the prototype of the serviceClass
    */
    public directiveServiceMock<S, M extends Partial<S>>(directiveClass: Type<any>, serviceClass: AbstractType<S>, mock: M,
        dontSpy: true): S & M;
    public directiveServiceMock<S, M extends Partial<S>>(directiveClass: Type<any>, serviceClass: AbstractType<S>, mock: M):
        jasmine.SpyObj<S> & M;
    public directiveServiceMock<S, M extends Partial<S>>(directiveClass: Type<any>, serviceClass: AbstractType<S>):
        jasmine.SpyObj<S>;
    public directiveServiceMock<S, M extends Partial<S>>(directiveClass: Type<any>, serviceClass: AbstractType<S>,
        mock?: M, dontSpy?: boolean):
        S & M | jasmine.SpyObj<S> & M | jasmine.SpyObj<S> {
        return <any> this.componentProviderMock(directiveClass, serviceClass, mock, dontSpy, serviceClass);
    }

    /**
    *  If you have directive that provides a provider you can mock it using this method.
    * @param directiveClass the directiveClass is the reference of the class of your angular directive.
    * @param token the provider token that you want to mock
    * @param mock the mock
    * @param dontSpy optional parameter to prevent the default spy creation on the mock
    */
    public directiveProviderMock<M>(directiveClass: Type<any>, token: any, mock: M, dontSpy = false,
        spySource?: AbstractType<any>): M {
        return this.uiThingProviderMock('overrideDirective', directiveClass, token, mock, dontSpy, spySource);
    }


    public componentServiceMock<S, M extends Partial<S>>(componentClass: Type<any>, serviceClass: AbstractType<S>, mock: M,
        dontSpy: true): S & M;
    public componentServiceMock<S, M extends Partial<S>>(componentClass: Type<any>, serviceClass: AbstractType<S>, mock: M):
        jasmine.SpyObj<S> & M;
    public componentServiceMock<S, M extends Partial<S>>(componentClass: Type<any>, serviceClass: AbstractType<S>):
        jasmine.SpyObj<S>;
    /**
    *  If you have component that provides a service you can mock it using this method.
    * @param componentClass the componentClass is the reference of the class of your angular component.
    * @param serviceClass the serviceClass is the reference to the class of the service that you want to mock
    * @param mock the mock mocks the service and should implement a partial of the service class
    * @param dontSpy optional parameter to prevent the default spy creation on the mock using the prototype of the serviceClass
    */
    public componentServiceMock<S, M extends Partial<S>>(componentClass: Type<any>, serviceClass: AbstractType<S>,
        mock?: M, dontSpy?: boolean):
        S & M | jasmine.SpyObj<S> & M | jasmine.SpyObj<S> {
        return <any>this.componentProviderMock(componentClass, serviceClass, mock, dontSpy, serviceClass);
    }

    /**
    *  If you have component provides a provider you can mock it using this method.
    * @param componentClass the componentClass is the reference of the class of your angular component.
    * @param token the provider token that you want to mock
    * @param mock the mock
    * @param dontSpy optional parameter to prevent the default spy creation on the mock
    */
    public componentProviderMock<M>(componentClass: Type<any>, token: any, mock: M, dontSpy = false,
        spySource?: AbstractType<any>): M {
        return this.uiThingProviderMock('overrideComponent', componentClass, token, mock, dontSpy, spySource);
    }

    /**
    * @ignore
    */
    private uiThingProviderMock<M>(methodName: string, uiThingClass: Type<any>, token: any, mock: M, dontSpy = false,
        spySource?: AbstractType<any>): M {
        this.expectToBePreConfiguration();
        if (!dontSpy) {
            spyOnFunctionsOf(mock, spySource ? spySource.prototype : undefined);
        }
        if (!this.config.declarations.includes(uiThingClass)) {
            this.config.declarations.push(uiThingClass);
        }
        this.postConfigureJobs.push(() => {
            (TestBed as any)[methodName](uiThingClass, {
                add: {
                    providers: [
                        { provide: token, useValue: mock }
                    ]
                }
            });
        });
        return mock;
    }

    public directiveMocks<C>(directiveClass: Type<C>): Array<C> {
        return this.componentMocks(directiveClass);
    }

    /**
    *  declare that you want to mock a component for a selector and retrieve all created component mock instances after fixture
    * creation.
    * @param componentClass class of the component that should be used in the fixture for a specific selector you want to mock.
    * @returns an arry of all component instances that were found statically inside the fixture. The array's members can only be
    * used after calling .fixture(). Before that time the array is initialized like this:
    * ['this array can only be used after fixture called'].
    */
    public componentMocks<C>(componentClass: Type<C>): Array<C> {
        const result: Array<any> = ['this array can only be used after fixture called'];
        this.expectToBePreConfiguration();
        if (!this.config.declarations.includes(componentClass)) {
            this.config.declarations.push(componentClass);
        }
        this.fixtureJobs.push(() => {
            result.length = 0;
            const componentDebugElements = this.fixtureInstance?.debugElement.queryAll(By.directive(componentClass));
            componentDebugElements?.forEach(componentDebugElement => result.push(componentDebugElement.injector.get(componentClass)));
        });
        return result;
    }

    /**
    *  Use this method to create a component fixture. This method may only be called once per NgMagicTestBed instance.
    * @param componentClass class of the root component you want to compile and create.
    * @param disableNoErrorSchema by default the NgMagicTestBed uses the NO_ERROR_SCHEMA of angular to prevent the compiler from
    * throwing exceptions e.g. for missing or unknown inputs.
    * @returns a component fixture like standard TestBed.createComponent(componentClass) would have returned it.
    */
    public fixture<C>(componentClass: Type<C>, initialInputs: Partial<C> = {}, disableNoErrorSchema = false): ComponentFixture<C> {
        if (this.fixtureInstance) {
            throw new Error('.fixture can only be called once per NgMagicTestBed instance');
        }
        if (!this.config.declarations.includes(componentClass) && this.configured) {
            throw new Error('Declaration of component needs to be done before you can create the fixture');
        }
        if (!this.config.declarations.includes(componentClass) && !this.configured) {
            this.config.declarations.push(componentClass);
        }
        if (!disableNoErrorSchema && !this.config.schemas.includes(NO_ERRORS_SCHEMA)) {
            this.config.schemas.push(NO_ERRORS_SCHEMA);
        }
        if (!this.configured) {
            this.configureTestingModule();
        }
        if (!this.compiled) {
            this.compiled = true;
            TestBed.compileComponents();
        }
        this.fixtureInstance = TestBed.createComponent(componentClass);
        Object.assign(this.fixtureInstance.componentInstance, initialInputs);
        this.fixtureInstance.detectChanges();
        this.fixtureJobs.forEach(job => job());
        return this.fixtureInstance;
    }

    /**
     * Can be used to create a mock for an object that should not be registered at angular TestBed.
     * @param objectClass This class' prototype will be used to extend the result mock by a spy for each method on the prototype.
     * @param mock An object that should implement partial of objectClass and contain all methods that you want to return something.
     * @param dontSpy optional parameter to prevent the default spy creation on the mock.
     * @returns Your mocks methods will be overwritten with spies that call through to the mocks methods like jasmine's spyOn method.
     * In addition to that a spy will be added for each additional method that was found on the objectClass' prototype.
     */
    public objectMock<O, M extends Partial<O>>(objectClass: AbstractType<O>, mock: M,
        dontSpy: true): O & M;
    public objectMock<O, M extends Partial<O>>(objectClass: AbstractType<O>, mock: M):
        jasmine.SpyObj<O> & M & O;
    public objectMock<O, M extends Partial<O>>(objectClass: undefined, mock: M): jasmine.SpyObj<M>;

    public objectMock<O, M extends Partial<O>>(objectClass: AbstractType<O> | undefined, mock: M | any, dontSpy = false):
        O & M | jasmine.SpyObj<O> & M {
        return <O & M | jasmine.SpyObj<O> & M>this.mock(undefined, mock, dontSpy, objectClass);
    }

    /**
     *  mocks a provider for a given token with a given mock. If wanted your mock can be extended by spies
     * from a given spySource class.
     * @param token token for provider provision
     * @param mock mock that will be registered for the token
     * @param dontSpy optional parameter to prevent the default spy creation on the mock.
     * @param spySource for each method in spySources prototype an additional jasmine spy will be created on the mock
     * @returns Your mocks methods will be overwritten with spies that call through to the mocks methods like jasmine's spyOn method.
     * In addition to that a spy will be added for each additional method that was found on the objectClass' prototype.
     */
    public providerMock<M>(token: any, mock: Partial<M>, dontSpy: boolean = false, spySource?: AbstractType<any>) {
        return this.mock(token, mock, dontSpy, spySource);
    }

    /**
   *  mocks a service that has a "create" method.
   * @param factoryClass service that has a "create" method that you want to mock.
   * @param instances will be returned by the mock this method return when "create" is called.
   * The first call of mock.create() will return the first item in the instances-array and so on.
   * @returns a mock for the factory. mock.create will return the one of the given instances every time it is called
   */
    public factoryMock<I, F extends IFactory<I>, M>(factoryClass: AbstractType<F>, instances: Array<M & I>): jasmine.SpyObj<Partial<F>> {
        let index = -1;
        return <any>this.mock(factoryClass, <any>{
            create: (...args: any) => {
                index++;
                return instances[index];
            },
        }, false, factoryClass);
    }

    public serviceMock<S, M extends Partial<S>>(serviceClass: AbstractType<S>, mock: M,
        dontSpy: true): S & M;
    public serviceMock<S, M extends Partial<S>>(serviceClass: AbstractType<S>, mock: M):
        jasmine.SpyObj<S> & M;
    public serviceMock<S, M extends Partial<S>>(serviceClass: AbstractType<S>): jasmine.SpyObj<S>;

    /**
     *  mocks a service with the given mock
     * @param serviceClass service that you want to mock
     * @param mock that should mock the service. All methods on the mock will become spies. For each method on serviceClass'
     * prototype another spy will be added to the mock.
     * @param dontSpy optional parameter to prevent the default spy creation on the mock.
     * @returns the mock after creating some spies on it (if not disabled)
     */
    public serviceMock<S, M extends Partial<S>>(serviceClass: AbstractType<S>, mock?: M, dontSpy?: boolean):
        S & M | jasmine.SpyObj<S> & M | jasmine.SpyObj<S> {
        return this.mock(serviceClass, mock, dontSpy, serviceClass);
    }

    /**
    * @ignore
    */
    private mock<S, M extends Partial<S>>(token?: any, mock: M = <any>{}, dontSpy?: boolean, spySource?: AbstractType<S>):
        S & M | jasmine.SpyObj<S> & M | jasmine.SpyObj<S> {
        if (!dontSpy) {
            spyOnFunctionsOf(mock, spySource ? spySource.prototype : undefined);
        }
        if (token) {
            this.expectToBePreConfiguration();
            this.config.providers.push({
                useValue: mock,
                provide: token
            });
        }
        return <any> mock;
    }

    public injection<S>(service: AbstractType<S>): S;
    /* tslint:disable */
    public injection<S>(token: any): S;
    /* tslint:enable */
    /**
     *  return you the service or provider for a given token from the angular dependency injection.
     * This will trigger the TestBed configureTestingModule step. After this step you can not create any more mocks.
     * Make sure you create all your mocks before calling this mehtod.
     * @param serviceClass service that you want to inject
     * @param token of the prider that you want to inject
     * @return whatever angular dependency injection finds for your token
     */
    public injection<S>(token: AbstractType<S> | any): S {
        this.configureTestingModule();
        return TestBed.get(token);
    }

    /**
    *
    * Subscribes to a given observable and spies on its states and emitted values.
    * @param observable
    * Observable you want to spy
    * @param name
    * Optional name that prefixes all jasmine spies that are created by the observer. This makes it easier to read the
    * test output if anything fails.
    * @returns
    * observer that can be used to make assertions in your test cases e.g.:
    * expect(observer.next).toHaveBeenCalledWith(expectedValue);
    * For more information check SpyObserver documentation
    */
    public observer<T>(observable: Observable<T>, name?: string): SpyObserver<T> {
        return observe(observable, name);
    }


}

results matching ""

    No results matching ""