Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change tabs in the unit test of a component that uses Angular Material Tabs

I have a LoginView component in which I have Angular Material Tabs. In one tab there's a LoginForm component displayed and in a second tab there's a RegistrationForm component.

What I try to test in LoginView is that when I click on a second tab, a RegistrationForm would be displayed. However, I have no idea how to click a tab. I've tried adding name or id to mat-tab but it isn't being generated in DOM, querySelectorAll() also returns null.

Source:

<mat-tab-group dynamicHeight class="py-5">
  <mat-tab label="{{'form.letsLogIn' | translate}}">
    <app-login-form></app-login-form>
  </mat-tab>
  <mat-tab label="{{'form.letsRegister' | translate}}">
      <app-registration-form></app-registration-form>
  </mat-tab>
</mat-tab-group>

Spec file:

import { Component } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginViewComponent } from './login-view.component';
import { TranslateModule } from '@ngx-translate/core';
import { MatTabsModule } from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@Component({selector: 'app-login-form', template: ''})
class LoginFormStubComponent {}

@Component({selector: 'app-registration-form', template: ''})
class RegistrationFormStubComponent {}

describe('LoginViewComponent', () => {
  let component: LoginViewComponent;
  let fixture: ComponentFixture<LoginViewComponent>;
  let compiled: any;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ 
        LoginViewComponent,
        LoginFormStubComponent,
        RegistrationFormStubComponent ],
      imports: [
        TranslateModule.forRoot(),
        MatTabsModule,
        BrowserAnimationsModule
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(LoginViewComponent);
    component = fixture.componentInstance;
    compiled = fixture.nativeElement;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should have a title', () => {
    expect(compiled.querySelector('h1')).toBeTruthy();
  });

  it('should display login form at start', () => {
    expect(compiled.querySelector('app-login-form')).toBeTruthy();
  });

  it('should display registration form after clicking second tab', () => {
    compiled = fixture.nativeElement;
    compiled.querySelectorAll('mat-tab')[1].click();
    fixture.detectChanges();
    expect(compiled.querySelector('app-registration-form')).toBeTruthy();
  });
});
like image 942
Dandy Avatar asked Sep 21 '18 15:09

Dandy


People also ask

How do you conditionally prevent users from navigating to other tab in Mat tab group?

The solution 🕶 First, we need to add a click listener on the mat-tab-group and disable all tabs because if tabs are not disabled then the user will be able to navigate on them and we want to navigate on tabs conditionally not manually.

What is angular TestBed?

TestBed is the primary api for writing unit tests for Angular applications and libraries.

What is matTabContent?

Material tabs (with matTabContent ) are rendering multiple instances of the tab body inside the same tab when switching away and back too fast.


1 Answers

I just worked the same problem. Your test is fine. Just add async() and use whenStable().

it('should display registration form after clicking second tab', async(() => {
  compiled = fixture.nativeElement;
  compiled.querySelectorAll('mat-tab')[1].click();
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    expect(compiled.querySelector('app-registration-form')).toBeTruthy();
  });
}));
like image 76
Christoph Avatar answered Oct 29 '22 23:10

Christoph