Angular 測(cè)試屬性型指令

2022-07-08 09:13 更新

測(cè)試屬性型指令

屬性型指令會(huì)修改元素、組件或其他指令的行為。它的名字反映了該指令的應(yīng)用方式:作為宿主元素的一個(gè)屬性。

如果你要試驗(yàn)本指南中所講的應(yīng)用,請(qǐng)在瀏覽器中運(yùn)行它下載并在本地運(yùn)行它。

測(cè)試 HighlightDirective

本范例應(yīng)用的 ?HighlightDirective ?會(huì)根據(jù)數(shù)據(jù)綁定中的顏色或默認(rèn)顏色(淺灰)來設(shè)置元素的背景色。它還會(huì)把該元素的自定義屬性(?customProperty?)設(shè)置為 ?true?,當(dāng)然這除了示范本技術(shù)之外別無它用。

import { Directive, ElementRef, Input, OnChanges } from '@angular/core';

@Directive({ selector: '[highlight]' })
/**
 * Set backgroundColor for the attached element to highlight color
 * and set the element's customProperty to true
 */
export class HighlightDirective implements OnChanges {

  defaultColor =  'rgb(211, 211, 211)'; // lightgray

  @Input('highlight') bgColor = '';

  constructor(private el: ElementRef) {
    el.nativeElement.style.customProperty = true;
  }

  ngOnChanges() {
    this.el.nativeElement.style.backgroundColor = this.bgColor || this.defaultColor;
  }
}

它在整個(gè)應(yīng)用中都用到過,也許最簡(jiǎn)單的是在 ?AboutComponent ?中:

import { Component } from '@angular/core';
@Component({
  template: `
  <h2 highlight="skyblue">About</h2>
  <h3>Quote of the day:</h3>
  <twain-quote></twain-quote>
  `
})
export class AboutComponent { }

要想在 ?AboutComponent ?中測(cè)試 ?HighlightDirective ?的特定用法,只需要瀏覽組件測(cè)試場(chǎng)景中的“嵌套組件測(cè)試”一節(jié)中提到的各種技巧。

beforeEach(() => {
  fixture = TestBed.configureTestingModule({
    declarations: [ AboutComponent, HighlightDirective ],
    schemas:      [ CUSTOM_ELEMENTS_SCHEMA ]
  })
  .createComponent(AboutComponent);
  fixture.detectChanges(); // initial binding
});

it('should have skyblue <h2>', () => {
  const h2: HTMLElement = fixture.nativeElement.querySelector('h2');
  const bgColor = h2.style.backgroundColor;
  expect(bgColor).toBe('skyblue');
});

但是,測(cè)試單個(gè)用例不太可能涉及指令的全部能力。要找到并測(cè)試那些使用了該指令的所有組件會(huì)很乏味、很脆弱,而且?guī)缀醪豢赡茏龅酵耆采w。

純類測(cè)試可能會(huì)有一點(diǎn)幫助,但像這種屬性型指令往往會(huì)操縱 DOM。孤立的單元測(cè)試不會(huì)觸及 DOM,因此也無法給人帶來對(duì)指令功效的信心。

更好的解決方案是創(chuàng)建一個(gè)人工測(cè)試組件來演示應(yīng)用該指令的所有方法。

@Component({
  template: `
  <h2 highlight="yellow">Something Yellow</h2>
  <h2 highlight>The Default (Gray)</h2>
  <h2>No Highlight</h2>
  <input #box [highlight]="box.value" value="cyan"/>`
})
class TestComponent { }


這個(gè) ?<input>? 用例將 ?HighlightDirective ?綁定到輸入框中顏色值的名稱。初始值是單詞“cyan”,應(yīng)該把它設(shè)為輸入框的背景顏色。

下面是對(duì)該組件的一些測(cè)試:

beforeEach(() => {
  fixture = TestBed.configureTestingModule({
    declarations: [ HighlightDirective, TestComponent ]
  })
  .createComponent(TestComponent);

  fixture.detectChanges(); // initial binding

  // all elements with an attached HighlightDirective
  des = fixture.debugElement.queryAll(By.directive(HighlightDirective));

  // the h2 without the HighlightDirective
  bareH2 = fixture.debugElement.query(By.css('h2:not([highlight])'));
});

// color tests
it('should have three highlighted elements', () => {
  expect(des.length).toBe(3);
});

it('should color 1st <h2> background "yellow"', () => {
  const bgColor = des[0].nativeElement.style.backgroundColor;
  expect(bgColor).toBe('yellow');
});

it('should color 2nd <h2> background w/ default color', () => {
  const dir = des[1].injector.get(HighlightDirective) as HighlightDirective;
  const bgColor = des[1].nativeElement.style.backgroundColor;
  expect(bgColor).toBe(dir.defaultColor);
});

it('should bind <input> background to value color', () => {
  // easier to work with nativeElement
  const input = des[2].nativeElement as HTMLInputElement;
  expect(input.style.backgroundColor)
    .withContext('initial backgroundColor')
    .toBe('cyan');

  input.value = 'green';

  // Dispatch a DOM event so that Angular responds to the input value change.
  input.dispatchEvent(new Event('input'));
  fixture.detectChanges();

  expect(input.style.backgroundColor)
    .withContext('changed backgroundColor')
    .toBe('green');
});


it('bare <h2> should not have a customProperty', () => {
  expect(bareH2.properties['customProperty']).toBeUndefined();
});

一些技巧值得注意:

  • ?By.directive? 謂詞是一種獲取那些不知道類型但都附有本指令的元素的好辦法。
  • ?By.css('h2:not([highlight])')? 中的 :not偽類可以幫助你找到那些沒有該指令的 ?<h2>? 元素。?By.css('*:not([highlight])')? 可以找到?jīng)]有該指令的任意元素。
  • ?DebugElement.styles? 提供了對(duì)元素樣式的訪問,即使沒有真正的瀏覽器也是如此,這要?dú)w功于 ?DebugElement ?提供的抽象。但是,如果 ?nativeElement ?顯得比使用其抽象版本更容易或更清晰,那就把它暴露出來。
  • Angular 會(huì)在指令宿主元素的注入器中添加上該指令。對(duì)默認(rèn)顏色的測(cè)試使用第二個(gè) ?<h2>? 上的注入器來獲取它的 ?HighlightDirective ?實(shí)例及其 ?defaultColor?。
  • ?DebugElement.properties? 允許訪問本指令設(shè)置的自定義屬性。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)