Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make material components work with Karma in unit testing Angular

I have an angular CLI project set up. I've made a form that uses angular material components, like <md-card>.

I'm just starting out with writing my first Karma/Jasmine unit test, following the steps in the angular docs.

This is my component template:

<md-card [ngClass]="'dialog-card'"> <md-card-title [ngClass]="'dialog-title'">     {{title}} </md-card-title> <md-card-content>      <form (ngSubmit)="login()" #loginForm="ngForm">          <md-input-container class="md-block">             <input md-input [(ngModel)]="user.email"                  name="userEmail" type="email" placeholder="Email"                  ngControl="userEmail"              required>         </md-input-container>         <br>          <md-input-container class="md-block">             <input md-input [(ngModel)]="user.password"                  name="userPassword" type="password" placeholder="Password"                  ngControl="userPassword"              required>         </md-input-container>         <br>          <tm-message msgText="Wrong username or password" *ngIf="showError"></tm-message>         <br>           <button md-button type="submit" [disabled]="!loginForm.form.valid">Login</button>          <p (click)="openForgotPasswordModal()">Forgot Password?</p>      </form>  </md-card-content> 

This is my karma spec:

import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By }              from '@angular/platform-browser'; import { DebugElement }    from '@angular/core'; import { MaterialModule, MdDialogRef, MdDialog  } from '@angular/material'; import { FormsModule } from '@angular/forms'; import { RouterTestingModule } from '@angular/router/testing';  import { TmLoginComponent } from './tm-login.component'; import { TmMessageComponent } from '../../shared/components/tm-message.component'; import { UserAuthenticationService } from '../login/user-authentication.service';  describe('TmLoginComponent (inline template)', () => {  let comp: TmLoginComponent; let fixture: ComponentFixture < TmLoginComponent > ; let de: DebugElement; let el: HTMLElement;  beforeEach(() => {     TestBed.configureTestingModule({         declarations: [TmLoginComponent, TmMessageComponent], // declare the test component         imports: [MaterialModule, FormsModule,             RouterTestingModule.withRoutes(                 [{                     path: 'login',                     component: TmLoginComponent                 }, ])         ],         providers: [UserAuthenticationService],      });      fixture = TestBed.createComponent(TmLoginComponent);      comp = fixture.componentInstance; // TmLoginComponent test instance      // query for the title <h1> by CSS element selector     de = fixture.debugElement.query(By.css('.title'));     el = de.nativeElement; });      it('should display original title', () => {         fixture.detectChanges();         expect(el.textContent).toContain(comp.title);     }); }); 

At this point, I'm just trying to run the basic unit test that the title is being displayed properly.

However, I'm getting a lot of material specific errors. Like

No provider for MdDialog.

I'm opening an md Dialog on clicking a link. THe code is in the (fairly long) .ts file, but that's not the issue here.

Where would I add MdDialog in the testbed? If I add it to providers, I get the error: "no provider for overlay". I don't know how to fix that.

Is there any way I can configure karma to include all material components at start?

Thanks.

like image 609
Snowman Avatar asked Jan 05 '17 11:01

Snowman


People also ask

Is Karma used for unit testing?

For any AngularJS development company it is a must to work with unit testing on any project, regardless of whether you choose to use a TDD (test-driven development) approach or not, using it will have a lot of advantages.


1 Answers

Current technique calls for individual imports of Angular Material modules, as MaterialModule is deprecated and was removed in 2.0.0-beta.11:

import {     MatButtonModule,     MatIconModule } from '@angular/material'; 

Then add the same list as imports in the TestBed config:

beforeEach(async(() => {     TestBed.configureTestingModule({         declarations: [ ... ],         imports: [             MatButtonModule,             MatIconModule,             ...         ],         providers: [ ... ]     })         .compileComponents(); })); 
like image 80
isherwood Avatar answered Sep 23 '22 00:09

isherwood