Create a component factory by using the createComponentFactory()
function, passing the component class that you want to test.
The createComponentFactory()
returns a function that will create a fresh component in each it
block:
Copy import { Spectator , createComponentFactory } from '@ngneat/spectator' ;
import { ButtonComponent } from './button.component' ;
describe ( 'ButtonComponent' , ( ) => {
let spectator : Spectator < ButtonComponent > ;
const createComponent = createComponentFactory ( ButtonComponent ) ;
beforeEach ( ( ) => spectator = createComponent ( ) ) ;
it ( 'should have a success class by default' , ( ) => {
expect ( spectator . query ( 'button' ) ) . toHaveClass ( 'success' ) ;
} ) ;
it ( 'should set the class name according to the [className] input' , ( ) => {
spectator . setInput ( 'className' , 'danger' ) ;
expect ( spectator . query ( 'button' ) ) . toHaveClass ( 'danger' ) ;
expect ( spectator . query ( 'button' ) ) . not . toHaveClass ( 'success' ) ;
} ) ;
} ) ;
The createComponentFactory
function can optionally take the following options which extends the basic Angular Testing Module options:
Copy const createComponent = createComponentFactory ( {
component : ButtonComponent ,
imports : [ ] ,
providers : [ ] ,
declarations : [ ] ,
entryComponents : [ ] ,
componentProviders : [ ] ,
componentViewProviders : [ ] ,
overrideModules : [ ] ,
mocks : [ ] ,
componentMocks : [ ] ,
componentViewProvidersMocks : [ ] ,
detectChanges : false ,
declareComponent : false ,
disableAnimations : false ,
shallow : true ,
} ) ;
The createComponent()
function optionally takes the following options:
Copy it ( 'should...' , ( ) => {
spectator = createComponent ( {
props : {
title : 'Click'
} ,
providers : [ ] ,
detectChanges : false
} ) ;
expect ( spectator . query ( 'button' ) ) . toHaveText ( 'Click' ) ;
} ) ;
The createComponent()
method returns an instance of Spectator
which exposes the following properties:
fixture
- The tested component's fixturecomponent
- The tested component's instanceelement
- The tested component's native elementdebugElement
- The tested fixture's debug elementAnd the following methods:
# inject()
Provides a wrapper for Ivy's TestBed.inject()
:
Copy const service = spectator . inject ( QueryService ) ;
const fromComponentInjector = true ;
const service = spectator . inject ( QueryService , fromComponentInjector ) ;
# detectChanges()
Runs detectChanges
on the tested element/host:
Copy spectator . detectChanges ( ) ;
# setInput()
Changes the value of an @Input()
of the tested component:
Copy it ( 'should...' , ( ) => {
spectator . setInput ( 'className' , 'danger' ) ;
spectator . setInput ( {
className : 'danger'
} ) ;
} ) ;
# output()
Returns an observable @Output()
of the tested component:
Copy it ( 'should emit the $event on click' , ( ) => {
let output ;
spectator . output ( 'click' ) . subscribe ( result => ( output = result ) ) ;
spectator . component . onClick ( { type : 'click' } ) ;
expect ( output ) . toEqual ( { type : 'click' } ) ;
} ) ;
# tick(millis?: number)
Run the fakeAsync tick()
function and call detectChanges()
:
Copy it ( 'should work with tick' , fakeAsync ( ( ) => {
spectator = createComponent ( ZippyComponent ) ;
spectator . component . update ( ) ;
expect ( spectator . component . updatedAsync ) . toBeFalsy ( ) ;
spectator . tick ( 6000 ) ;
expect ( spectator . component . updatedAsync ) . not . toBeFalsy ( ) ;
} ) )
# Component ProvidersBy default, the original component providers (e.g. the providers
on the @Component
) are not touched.
However, in most cases, you want to access the component's providers in your test or replace them with mocks.
For example:
Copy @ Component ( {
template : '...' ,
providers : [ FooService ]
} )
class FooComponent {
constructor ( private fooService : FooService } { }
}
Use the componentProviders
to replace the FooService
provider:
Copy const createComponent = createComponentFactory ( {
component : FooComponent ,
componentProviders : [
{
provide : FooService ,
useValue : someThingElse
}
]
} )
Or mock the service by using componentMocks
:
Copy const createComponent = createComponentFactory ( {
component : FooComponent ,
componentMocks : [ FooService ]
} ) ;
To access the provider, get it from the component injector using the fromComponentInjector
parameter:
Copy spectator . inject ( FooService , true )
In the same way you can also override the component view providers by using the componentViewProviders
and componentViewProvidersMocks
.
The same rules also apply to directives using the directiveProviders
and directiveMocks
parameters.
# Override ModulesUse overrideModules
option to override modules.
For Example:
Copy createComponentFactory ( {
component : SomeComponent ,
overrideModules : [
[ SomeModule , { set : { declarations : [ SomeOtherComponent ] } ] ,
[ SomeOtherModule , { set : { declarations : [ SomeOtherComponent ] } ]
]
} )
cf. https://angular.io/api/core/testing/TestBed#overrideModule