Search code examples
angularjasmine

How to unit test angular directive with @host() and conditional parameter


I have a directive which call forceErrorStateUpdate method on input control. how to unit test below code to achieve full code coverage? the problem I have is that I am not able to get full code coverage for the line this._textInput?.forceErrorStateUpdate(); which is called in onInit.

import { Directive, Host. OnInit, Optional } from '@angular/core';

@Directive({
  selector: '[showValidationError]'
});

export class TestDirective implements onInit {

  constructor(@Host() @Optional() private _textInput: any) { }

  ngOnInit(): void {
    this._textInput?.forceErrorStateUpdate();
  }

}

Below is the unit test code. the code coverage is around 75%.

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TestComponent } from '../test/test.component';
import { TestDirective } from './test.directive';

describe('TestDirective', () => {
  let testComponent: TestComponent;
  let testFixture: ComponentFixture<TestComponent>;
  let directiveInstance: TestDirective;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [],
      declarations: [TestComponent, TestDirective]
    }).compileComponents();
  });

  beforeEach(() => {
    testFixture = TestBed.createComponent(TestComponent);
    testComponent = testFixture.componentInstance;
    testFixture.detectChanges();
    const directiveEl = testFixture.debugElement.query(By.directive(TestDirective));
    expect(directiveEl).not.toBeNull();
    directiveInstance = directiveEl.injector.get(TestDirective);
  });
  
  it('should create', () => {
    expect(directiveInstance).toBeTruthy();
  });

  it('should have ngOnInit', () => {
    expect(directiveInstance.ngOnInit).toBeDefined();
  });

  it('should invoke forceErrorUpdate on input component', () => {
    directiveInstance.ngOnInit();
    expect(directiveInstance.ngOnInit).toBeDefined();
  });
});

Solution

  • If you want to check that conditional parameter you could like this:

    beforeEach(() => {
        directive = new TestDirective(null);
      });
      
      it('should not throw an error if _textInput is not provided', () => {
        directive['_textInput'] = null;
        expect(() => directive.ngOnInit()).not.toThrow();
      });
      
       it('should call forceErrorStateUpdate() on input initialization', () => {
        const mockInput = { forceErrorStateUpdate: jest.fn() };
        directive['_textInput'] = mockInput;
        directive.ngOnInit();
        expect(mockInput.forceErrorStateUpdate).toHaveBeenCalled();
      });