Angular Testing For Angular-Material On Mat-Menu


Answer :

My final test ended up looking like this:

import { TestBed, async, ComponentFixture } from '@angular/core/testing'; import { AppComponent } from './app.component'; import { RouterTestingModule } from '@angular/router/testing';  import { AppRoutes } from './app.routes'; import {   MatToolbarModule,   MatIconModule,   MatMenuModule,   MatButtonModule } from '@angular/material';  import { HomeComponent } from './home/home.component'; import { UserService } from './user/user.service'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { BehaviorSubject } from '../../node_modules/rxjs';  class MockUserService {   signedIn$: BehaviorSubject<boolean> = new BehaviorSubject(false);   signIn() {} }  describe('AppComponent', () => {   let app: AppComponent;   let fixture: ComponentFixture<AppComponent>;   let dom;   let button;    beforeEach(async(() => {     TestBed.configureTestingModule({       declarations: [AppComponent, HomeComponent],       providers: [{ provide: UserService, useClass: MockUserService }],       imports: [         NoopAnimationsModule,         MatIconModule,         MatToolbarModule,         MatMenuModule,         MatButtonModule,         RouterTestingModule.withRoutes(AppRoutes)       ]     }).compileComponents();   }));    beforeEach(() => {     fixture = TestBed.createComponent(AppComponent);     fixture.autoDetectChanges(true);                                           //this was the key fix     spyOn(MockUserService.prototype, 'signIn').and.callThrough();     app = fixture.debugElement.componentInstance;     dom = fixture.nativeElement;     button = dom.querySelector('#userMenu');   });    it('should create the app', async(() => {     expect(app).toBeTruthy();   }));    describe('user menu', () => {     it('should not have the menu open', async () => {       const menu = dom.parentNode.querySelector('.mat-menu-panel');       expect(menu).toBeFalsy();     });      it('open the menu when clicking on the account button', async () => {       button.click();       const menu = dom.parentNode.querySelector('.mat-menu-panel');       expect(menu).toBeTruthy();     });      it('call user.signIn() once sign in button is pressed', async () => {       button.click();       const mockUser = TestBed.get(UserService);       dom.parentNode.querySelector('#userSignIn').click();       expect(mockUser['signIn']).toHaveBeenCalled();     });   });    describe('navigation icons', () => {     it('navigation icons show when user.signedIn$ emits true', async () => {       const mockUser = TestBed.get(UserService);       await mockUser.signedIn$.next(true);       await fixture.detectChanges();       expect(         dom.parentNode.querySelector('button[routerLink="/emails/received"]')       ).toBeTruthy();       expect(         dom.parentNode.querySelector('button[routerLink="/emails/mapping"]')       ).toBeTruthy();     });      it('navigation icons don\t show until user.signedIn$ emits true', async () => {       expect(         dom.parentNode.querySelector('button[routerLink="/emails/received"]')       ).toBeFalsy();       expect(         dom.parentNode.querySelector('button[routerLink="/emails/mapping"]')       ).toBeFalsy();     });      it('navigation icons don\t show until user.signedIn$ emits false', async () => {       const mockUser = TestBed.get(UserService);       await mockUser.signedIn$.next(false);       await fixture.detectChanges();       expect(         dom.parentNode.querySelector('button[routerLink="/emails/received"]')       ).toBeFalsy();       expect(         dom.parentNode.querySelector('button[routerLink="/emails/mapping"]')       ).toBeFalsy();     });      it('navigation icons re-hide on user.signedIn$ false', async () => {       const mockUser = TestBed.get(UserService);       await mockUser.signedIn$.next(true);       await fixture.detectChanges();       await mockUser.signedIn$.next(false);       await fixture.detectChanges();       expect(         dom.parentNode.querySelector('button[routerLink="/emails/received"]')       ).toBeFalsy();       expect(         dom.parentNode.querySelector('button[routerLink="/emails/mapping"]')       ).toBeFalsy();     });   }); }); 

There is simpler way:

you can use @ViewChild in component

@ViewChild('menuTrigger') menuTrigger: MatMenuTrigger; 

in html template there is:

 <button mat-icon-button [matMenuTriggerFor]="menu" #menuTrigger='matMenuTrigger'>   </button> 

then there is "openMenu()" in test:

 fit('should show menu', () => {   component.menuTrigger.openMenu()  } 

Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?