user1040363
user1040363

Reputation: 139

testing directive with jasmine

I have this directive but Im struggling with the jasmine test for it, any ideas?

import { Directive, Output, EventEmitter, HostListener } from '@angular/core';

@Directive({
   selector: '[ctrlKeys]',
})
export class CtrlKeysDirective {
   @Output() ctrlZ = new EventEmitter();
   @Output() ctrlY = new EventEmitter();

   @HostListener('document:keydown.control.z') onCtrlZ() {
       this.ctrlZ.emit();
   }

   @HostListener('document:keydown.control.y') onCtrlY() {
       this.ctrlY.emit();
   }
}

Upvotes: 2

Views: 823

Answers (1)

AliF50
AliF50

Reputation: 18899

Usually with directives, I just attach it to a dummy component/HTML element and test from there. I am going all without an IDE so there may be some mistakes.

describe('CtrlKeysDirective', () => {
  @Component({
    selector: 'dummy',
    template: `<div class="under-test" ctrlKeys>Hello</div>`
  })
  class DummyComponent {}
  
  let fixture: ComponentFixture<DummyComponent>;
  let component: DummyComponent;
  let ctrlKeysDirective: CtrlKeysDirective;

  beforeEach(waitForAsync(() => {
   TestBed.configureTestingModule({
     // declare both your directive and dummy component
     declarations: [DummyComponent, CtrlKeysDirective],
   }).compileComponents();
  }));

  beforeEach(() => {
    // get a handle on your component
    fixture = TestBed.createComponent(DummyComponent);
    component = fixture.componentInstance;
    // call ngOnInit of the component (not required)
    fixture.detectChanges();
    // get a handle on your directive (inspired from here https://stackoverflow.com/a/40282709/7365461)
    const ctrlKeysDirectiveEls = fixture.debugElement.query(By.directive(CtrlKeysDirective));
    ctrlKeysDirective = ctrlKeysDirectiveEls[0].injector.get(CtrlKeysDirective) as CtrlKeysDirective;
  });

  it('should create', () => {
    // expect the component to be truthy. Make sure this test passes to ensure
   // the TestBed was configured correctly.
    expect(component).toBeTruthy();
  });

  it('should emit ctrlZ', () => {
    const ctrlZSpy = spyOn(ctrlKeysDirective.ctrlZ, 'emit');
    window.dispatchEvent(new KeyboardEvent('keydown', { key: 'z', ctrlKey: true }));
    // !! try this !!
    const div = fixture.debugElement.query(By.css('.under-test')).nativeElement;
    div.dispatchEvent(new KeyboardEvent('keydown', { key: 'z', ctrlKey: true }));
    fixture.detectChanges();
    expect(ctrlZSpy).toHaveBeenCalled();
  });
});

I got inspired with the dispatchEvent from here: https://johngrahamdev.com/Unit-Testing-Keyboard-Shortcuts-Angular/

Upvotes: 1

Related Questions