Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test if an angular 2 component contains another component

I'm quite new to angular 2.

I have a component which in turn has some other components in its template.

How do I write unit tests to check if my parent component consists of other components.

Mentioning a sample or directing me to a resource would be really helpful.

MyComponent.ts:

import { Component } from '@angular/core'; @Component({ selector: 'my-component', templateUrl: `<div> <other-component></other-component> </div>` }) export class MyComponent{  } 

OtherComponent.ts:

import { Component } from '@angular/core'; @Component({ selector: 'other-component', templateUrl: `<div> <h1>Other Component</h1> </div>` }) export class OtherComponent{  } 
like image 515
Chan15 Avatar asked Nov 11 '16 04:11

Chan15


People also ask

How do I unit test a service with Angular components?

Mock Service Dependency In Angular For unit testing the method, you need to mock the service method getPosts to test the component method. Let's start by writing unit test for testing method getPostDetails when the response from service method getPosts is an empty array. Add the following unit test case to the app.

What does fixture detectChanges () do?

detectChanges(). Delayed change detection is intentional and useful. It gives the tester an opportunity to inspect and change the state of the component before Angular initiates data binding and calls lifecycle hooks.

What is beforeEach in Angular testing?

beforeEach is a global function in Jasmine that runs some setup code before each spec in the test suite. In this test suite, beforeEach is used to create a testing module using the TestBed object and declares any components that would be used in this testing module.


2 Answers

To test if a component, when compiled, contains other components:

  • Inject the component you're testing
  • Inject the child components
  • Create the parent component
  • Detect changes
  • Use querySelector or querySelectorAll to find the child components

I typically only check that the element exists and then do further testing in the spec for the individual child component.

import { TestBed, async } from '@angular/core/testing';  import { AppComponent } from './app.component'; import { OtherComponent } from './other/other.component';  describe('AppComponent', () => {   beforeEach(async(() => {     TestBed.configureTestingModule({       declarations: [         AppComponent,         OtherComponent       ],     }).compileComponents();   }));    it('should create the app', async(() => {     const fixture = TestBed.createComponent(AppComponent);     const app = fixture.debugElement.componentInstance;     expect(app).toBeTruthy();   }));    it('should have the other component', async(() => {     const fixture = TestBed.createComponent(AppComponent);     fixture.detectChanges();     const compiled = fixture.debugElement.nativeElement;     expect(compiled.querySelector('app-other')).not.toBe(null);   })); }); 

Checking for null with querySelector will determine if your component exists. From the querySelector MDN:

Returns null if no matches are found; otherwise, it returns the first matching element.


If you'd like to check that there are multiple instances of the same child component, you can use querySelectorAll and check the length property:

expect(compiled.querySelectorAll('app-other').length).toBeGreaterThan(4); 
like image 143
silencedmessage Avatar answered Sep 25 '22 06:09

silencedmessage


In most cases you are just testing the outer component. If you just want angular to ignore the inner components, the easiest way is to add the NO_ERRORS_SCHEMA to your spec.

import { NO_ERRORS_SCHEMA } from '@angular/core'

And then in your TestBed.configureTestingModule add the line:

schemas: [NO_ERRORS_SCHEMA]

The tests will then ignore the fact that you have not imported the inner components in your component HTML.

If you want to test the inner component with your outer components, if you're using the angular-cli, you'll see that the component.spec file they automatically generate for you includes a declarations array that is part of the TestBed configuration object. So all you have to do is import the file and add the component into your declarations.

So your example above:

import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { DebugElement } from '@angular/core';  import { MyComponent } from './my-component.component'; import { OtherComponent } from './other-component.component'; 

Then in your describe block you will have a beforeEach

beforeEach(async(() =>{   TestBed.configureTestingModule({     declarations: [ MyComponent,                     OtherComponent ]   })   .compileComponent(); }) 

Then your components should now compile correctly without errors. If you want to see the whole setup, just generate a new project in angular-cli and take a look at the spec docs that it generates.

like image 23
Felix Tsai Avatar answered Sep 23 '22 06:09

Felix Tsai