How to get material components to work with karma in Angular unit testing

I have a CLI corner project. I created a form in which angular components of the material are used, for example, <md-card> .

I'm just starting out by writing my first Karma / Jasmine unit test, following the instructions in the corner docs .

This is my template component:

 <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 specification:

 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 the moment, I'm just trying to run a basic unit test so that the title displays correctly.

However, I get a lot of material errors. like

There is no provider for MdDialog.

I open the md dialog when I click on the link. The code is in the (rather long) .ts file, but that is not the problem here.

Where would I add MdDialog in a test bench? If I add it to the providers, I get the error: "there is no provider to overlay." I do not know how to fix this.

Is it possible to somehow configure karma to include all components of the material at startup?

Thank you

+16
source share
3 answers

All providers are provided by calling forRoot() in the module

 imports: [ MaterialModule.forRoot() ] 

For versions 2.0.0-beta.4 and later (since the forRoot method forRoot been removed):

 imports: [ MaterialModule ] 

For versions 2.0.0-beta.11 and later, since the MaterialModule been removed, you need to import the modules yourself necessary for test cases:

 imports: [ MatButtonModule, MatDialogModule ] 
+3
source

The current technique requires the individual import of Angular material modules, as the MaterialModule deprecated and removed in 2.0.0-beta.11 :

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

Then add the same list as the import in the TestBed configuration:

 beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ ... ], imports: [ MatButtonModule, MatIconModule, ... ], providers: [ ... ] }) .compileComponents(); })); 
+7
source

I struggled with this today, and you need to model the necessary classes yourself using providers in jasmine. This is a hassle, and I wish there was a better way, but at least there are no more errors ...

If anyone has a better idea, educate the rest of the community!

 import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { AlertDialogComponent } from './alert-dialog.component'; import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; describe('AlertDialogComponent', () => { let component: AlertDialogComponent; let fixture: ComponentFixture<AlertDialogComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [MatDialogModule], declarations: [AlertDialogComponent], providers: [ { provide: MatDialogRef, useValue: {} }, { provide: MAT_DIALOG_DATA, useValue:{} } ], }).compileComponents(); })); 
0
source

Source: https://habr.com/ru/post/1013787/


All Articles