'Unit test for Button with disable

I am trying to write a unit test for a button that has disabled assigned to a boolean.

html looks like:

<button *ngIf="!data" id="createBtn" mat-button color="primary" (click)="submitNewCase()" [disabled]="disableCreate">{{ 'ACTIONS.create' | translate }}</button>

my unit test:

beforeEach(() => {
 fixture = TestBed.createComponent(CaseComponent);
 component = fixture.componentInstance;
 fixture.detectChanges();
 submitEl = fixture.debugElement.query(By.css('button'));
});


  it('DisableCreate set to true disables the submit button', () => {
   component.disableCreate = true;
   fixture.detectChanges();
   expect(submitEl.nativeElement.disabled).toBeTruthy();
  });

  it('DisableCreate set to false enables the submit button', () => {
   component.disableCreate = false;
   fixture.detectChanges();
   expect(submitEl.nativeElement.disabled).toBeFalsy();
  });

My second unit test succeeds and my first one does not. I am getting back a "Expected false to be truthy.". I cannot find where this is failing and why.

Any help would be much appreciated.



Solution 1:[1]

So after banging my head against the table a little longer it looks like I was selecting the button incorrectly. Using querySelector for button has my test succeeding. Also to @Fateh Mohamed's comment setting component.data to null is required since there is a ngIf for data on the button.

    beforeEach(() => {
     fixture = TestBed.createComponent(CaseComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
     submitEl = fixture.debugElement
    });

    it('DisableCreate set to true disables the submit button', () => {
     component.disableCreate = true;
     component.data = null;
     fixture.detectChanges();
     expect(submitEl.nativeElement.querySelector('button').disabled).toBeTruthy();
    });

    it('DisableCreate set to false enables the submit button', () => {
     component.disableCreate = false;
     component.data = null;
     fixture.detectChanges();
     expect(submitEl.nativeElement.querySelector('button').disabled).toBeFalsy();
    });

Solution 2:[2]

Found another way,

in your HTML add id to button, i.e

<button id="myButtonId" [disabled]="someCondition">/<button>

in test file get the button (by id or any other way) and check disabled state by ng-reflect-disabled attribute

const addButton = fixture.debugElement.nativeElement.querySelector('#myButtonId');
expect(addButton.attributes.getNamedItem('ng-reflect-disabled').value).toBeTruthy();

Solution 3:[3]

None of the answers worked for me on Angular 11 so leaving my 2 cents here:

Template:

<div class="actions">
    <button [disabled]="loading">
        Submit
    </button>
</div>

Class (simplified):

export class SubmitComponent {
    loading = false;
}

Test:

import { By } from '@angular/platform-browser';
...
let component: SubmitComponent;
let fixture: ComponentFixture<SubmitComponent>;

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

it('should disable on load', () => {
    fixture.componentInstance.loading = true;
    fixture.detectChanges();
    const button: HTMLButtonElement = fixture.debugElement.query(By.css('.actions > button')).nativeElement;
    expect(button.attributes.getNamedItem('ng-reflect-is-disabled')?.value).toEqual('true');
    // or 
    expect(button.attributes.getNamedItem('ng-reflect-is-disabled')?.value).toBeTruthy();
});

Solution 4:[4]

import { By } from '@angular/platform-browser';
...
let component: SubmitComponent;
let fixture: ComponentFixture<SubmitComponent>;

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

it('should disable on load', () => {
    fixture.componentInstance.loading = true;
    fixture.detectChanges();
    const buttons= fixture.nativeElement.querySelectorAll(
      '.actions > button'
    );
  buttons.forEach(button => {
      expect(button.attributes['disabled'].value).toEqual('true');
    });
    // or in false case .
   buttons.forEach(button => {
      expect(button.attributes['disabled']).toBeUndefined();
    });
});

Solution 5:[5]

If anyone is using the @ngneat/spectator package and testing values declared as @Input(), use spectator.setInput({ myInputValue: true }) instead of component.myInputValue = true; in your tests.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Liam
Solution 2 Liam
Solution 3 Erwol
Solution 4 hrushikesh das
Solution 5 Jan Nicklas