decebal
decebal

Reputation: 1211

Angular unit testing - change component variable inside the test

I want to test the functionality of a button, but that element is not visible on the page because it's under an *ngIf. I would like to set the variable from *ngIf to be truthy in order to be able to display the data. I tried doing it with:

beforeEach(() => {
    fixture = TestBed.createComponent(HeaderComponent);
    component = fixture.componentInstance;
    component.currentUser = {firstName: 'xxx'} as User; // Changing currentUser so it won't be undefined anymore 
    fixture.detectChanges();
  });

but still doesn't work. Here is my component:

<div class="menu-button-container">
    <div class="menu-button" [ngClass]="{'menu-open': isMenuOpen}" (click)="toggleMenu()" *ngIf="currentUser">
        <div class="line-menu-button line-menu-button__top"></div>
        <div class="line-menu-button line-menu-button__middle"></div>
        <div class="line-menu-button line-menu-button__bottom"></div>
    </div>
</div>

and the test I try to run:

it('should open the menu when the button menu is clicked', () => {
    const fixture = TestBed.createComponent(HeaderComponent);
    fixture.detectChanges();
    const menuDebugElement = fixture.debugElement.query(By.css('.menu-button'));
    expect(menuDebugElement).toBeTruthy();
  });

this always fails. If I define the *ngIf rule as *ngIf="currentUser", the test is working. How can I do this variable change from the test? Please advise! Thanks!

Upvotes: 1

Views: 17040

Answers (2)

Mattia Fravezzi
Mattia Fravezzi

Reputation: 440

The problem is fixture.detectChanges(); triggers change detaction cycle and when you read value from html component not finished to update itself.

You solve using "whenStable()" function

  it('should open the menu when the button menu is clicked', () => {
    const fixture = TestBed.createComponent(HeaderComponent);
    component.currentUser = true;

    fixture.detectChanges();

    fixture.whenStable()
        .then(() => {
            const menuDebugElement = fixture.debugElement.query(By.css('.menu-button'));
            expect(menuDebugElement).toBeTruthy();
        });
    
  });

Upvotes: 0

Chris
Chris

Reputation: 2397

change the value of the currentUser variable:

it('should open the menu when the button menu is clicked', () => {
  const fixture = TestBed.createComponent(HeaderComponent);
  const component = fixture.componentInstance;
  component.currentUser = true;

  fixture.detectChanges();

  const menuDebugElement = fixture.debugElement.query(By.css('.menu-button'));
  expect(menuDebugElement).toBeTruthy();
});

I created an entire test and it works for me

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { TestTComponent } from './test-t.component';
import { By } from '@angular/platform-browser';

fdescribe('TestTComponent', () => {
  let component: TestTComponent;
  let fixture: ComponentFixture<TestTComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [TestTComponent]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(TestTComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

    fixture.detectChanges();

    const menuDebugElement = fixture.debugElement.query(By.css('.menu-button'));
    expect(menuDebugElement).toBeTruthy();
  });
});

Upvotes: 6

Related Questions