iT邦幫忙

2022 iThome 鐵人賽

DAY 23
0
Modern Web

Angular TDD (Test-driven development ) 從0到1系列 第 23

Angular TDD 測試從0到1: Day 23 HTML Template Unit Test(4) - @Input, @Output

  • 分享至 

  • xImage
  •  

來到 UI 測試最後一篇,要來學習元件有內外部參數傳遞的情境

  • Testing Child Component Outputs
  • Testing Child Component Inputs

Child Component

子元件會有 @Input 接收 parent 傳遞的參數,處理後用 @Output emit 方式把值傳回 parent。接下來的測試會用 child component 做 input, output 範例測試。

  • TS
export class ChildComponent {
  title = 'example-angular-app';
  @Input() public inputData;
  @Output() public outputData: EventEmitter<string> = new EventEmitter<string>();
}

Component @Output

在 parent 使用 child component 的 output event (outputData)

  • HTML
<app-child-component id="title" (outputData)="updateData($event)"></app-child-component>
  • TS
export class TestingChildComponentOutputsComponent {
  title = 'example-angular-app';
  public updateData(val) {};
}
  • Spec
    要如何 tigger output event?這邊會用 dispatchEvent 自訂義事件觸發器,還呼叫 output event,那他是做什麼用的呢?在應用程式中通常會用「互動」的方式觸發event,像是 clickchange,但有時候需要用「程式」互動來觸發event,那麼就會用 dispatchEvent (如果有理解錯誤,歡迎讀者不吝指正 > <)。所以 line 9 用到 dispatchEvent 來 trigger output event。最後預期 spy 的 'updateData' 有被呼叫到。
describe('query', () => {
    it('should call the correct function on child component output event', () => {
      //Assign
      const spy = spyOn(component,'updateData');
      const event = new Event('outputData');

      //Act
      const element = componentFixture.debugElement.query(By.css('#title'));
      element.nativeElement.dispatchEvent(event);
  
      //Assert
      expect(spy).toHaveBeenCalledWith(event);
    });
  })

Component @Input

在 parent 使用 child component 的 input event (inputData)

  • HTML
<app-child-component id="title" [inputData]="title"></app-child-component>
<button id="button" type="submit" [disabled]="isDisabled">Submit</button>
  • TS
export class TestingChildComponentInputsComponent {
  title = '';
  isDisabled = false;
}
  • Spec 解釋我們看下方圖片
 describe('query', () => {
    it('should pass down the correct data to app-child-component', () => {
      //Assign
      component.title = "a title";
      
      //Act
      componentFixture.detectChanges();
  
      //Assert
      const element = componentFixture.debugElement.query(By.css('#title'));
      expect(element.componentInstance.inputData).toEqual(component.title);
    });

    it('should set the button to disabled when isDisabled is true', () => {
      //Assign
      component.isDisabled = true;
      
      //Act
      componentFixture.detectChanges();
  
      //Assert
      const element = componentFixture.debugElement.query(By.css('#button'));
      expect(element.nativeElement.disabled).toEqual(component.isDisabled);
    });
  })
  • 圖來解釋
    一開始還看不明白,console 印出來就大概知道了,這邊印了 element 會是拿到整個 DOM 元素,因為一開始設定資料就是 a title,所以用 id 取的元素就會看到 ng-reflect-input-data='a title' ,接著印出來的 inputData 就是前面設定的資料,最後預期設定的資料和查詢的結果要一樣,那麼測例2也是一樣的只是測試的參數是 disabled

今日心得

來到 HTML 測試的最後一篇,認識新的方法 dispatchEvent,平時開發的使用場景真的蠻少的,瞭解到有些功能即使不是從介面互動發動,也能從程式面發動,覺得技術發開發好像沒有什麼場景是沒辦法應用的,只要有一點開頭,就能慢慢挖掘不同的技術可能。

測試範例已經結束,接下來延續課程,下一篇要來認識 Azure Pipeline,是筆者完全沒碰過的工具,一起邁向鐵人賽的尾聲吧!


上一篇
Angular TDD 測試從0到1: Day 22 HTML Template Unit Test(3) - ngIf, ngFor, ngClass
下一篇
Angular TDD 測試從0到1: Day 24 Tips For Writing Unit Tests
系列文
Angular TDD (Test-driven development ) 從0到130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言