Директивы Angular - важная конструкция в angular, позволяющая сделать DOM манипуляциями и / или обработкой событий абстрактными.

Мы должны использовать директивы Unit Test, имитируя все зависимости с помощью жасминовых моков и шпионов.

Мы также должны использовать директивы Shallow / Deep Test с использованием конкретных компонентов (скомпилированный DOM). Разумный подход - создать TestComponent или выбрать любой компонент, который использует директиву, которую мы хотим протестировать.
Зависимости от TestComponent имитируются, но сама директива проверяет конкретный компонент (скомпилированный DOM).

Это включает в себя настройку TestBed для создания TestModule (также создает зону для тестирования) и компиляцию TestComponent с директивой для тестирования.

Давайте напишем простую директиву DisableLinkDirective, которая обеспечит [attr.disabled] = ”condition” функциональность якорных ссылок ‹a/›, чтобы они можно отключить так же, как ‹button /› изначально.

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

@Directive({
  selector: 'a[disabled]'
})
export class DisableLinkDirective {

  @HostListener('click', ['$event'])
  click(event: Event) {
    console.log('event', event);
    event.preventDefault();
  }
}

Теперь мы протестируем эту директиву с помощью компонента TestDisableLinkComponent, который компилирует ссылки привязки ‹a/› с атрибутом disabled.

import {DisableLinkDirective} from './disable-link.directive';
import {Component, DebugElement} from '@angular/core';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
// creating a test component in the spec file
@Component(
  {
    selector: 'ngx-mix-test-disable-link-directive',
    template: `
    <div>
     <a id="disabled-link" disabled (click)="onClick()">Disabled</a>
     <a id="normal-link" (click)="onClick()">Normal</a> 
    </div>
    `
  }
)
class TestDisableLinkComponent {
toggle = false;
onClick() {
    this.toggle = !this.toggle;
  }
}
// tests start here
describe('DisableLinkDirective', () => {
let component: TestDisableLinkComponent;
  let fixture: ComponentFixture ;
beforeEach(async () => {
await TestBed.configureTestingModule({
      declarations: [TestDisableLinkComponent, DisableLinkDirective]
    }).compileComponents();
  });
beforeEach(async () => {
    fixture = TestBed.createComponent(TestDisableLinkComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
it('should create an instance', () => {
    const directive = new DisableLinkDirective();
    expect(directive).toBeTruthy();
  });
it('should not toggle between enabled / disabled when the link with disabled attribute is clicked', async () => {
    const testDe: DebugElement = fixture.debugElement;
    const linkDe = testDe.query(By.css('#disabled-link'));
    const link: HTMLElement = linkDe.nativeElement;
    await expect(link.getAttribute('disabled')).not.toBe(null);
    const toggleValueBeforeClick = component.toggle;
    linkDe.triggerEventHandler('click', null);
    fixture.detectChanges();
    await fixture.whenStable();
    await expect(toggleValueBeforeClick).toBe(component.toggle);
  });
it('should toggle between enabled / disabled when the link does not have disabled attribute', async () => {
    const testDe: DebugElement = fixture.debugElement;
    const linkDe = testDe.query(By.css('#normal-link'));
    const link: HTMLElement = linkDe.nativeElement;
    await expect(link.getAttribute('disabled')).toBe(null);
    const toggleValueBeforeClick = component.toggle;
    linkDe.triggerEventHandler('click', null);
    fixture.detectChanges();
    await fixture.whenStable();
    await expect(toggleValueBeforeClick).not.toBe(component.toggle);
  });
});