iT邦幫忙

2021 iThome 鐵人賽

DAY 19
2
Modern Web

前端工程師在工作中的各種實戰技能 (Vue 3)系列 第 19

[Day19] Vue 3 單元測試 (Unit Testing) - Event Handling

Event Handling

在開發元件時一定少不了會需要觸發事件的時候,像是 click 事件、input 事件等等,所以我來用簡單的 Counter 來示範要怎麼為事件攥寫單元測試。

import { ref } from 'vue'

const Component = {
  template: `
    <div>
      <button data-test="button" @click="increment">Increment</button>
      <p data-test="count">{{count}}</p>
    </div>
  `,
  setup () {
    const count = ref(0)
    const increment = () => {
      count.value += 1
    }

    return {
      count,
      increment
    }
  }
}

在元件中有一個掛載 click 事件的 button 以及一個會顯示目前 count 數值的 p。

要測試這個元件是否正常,我們應該驗證三種情況是否正確運行:

  • Case 1: button 應該要存在。
  • Case 2: count 的初始值為 0。
  • Case 3: click 一次 button 後,count 的值變成 1。

Case 1 & Case 2。

// Case 1: button 應該要存在。 
test('render button', () => {
  const wrapper = mount(Component)

  expect(wrapper.get('[data-test="button"]').exists()).toBe(true)
})

// Case 2: count 的初始值為 0。
test('The initial value of count is 0', () => {
  const wrapper = mount(Component)

  expect(wrapper.get('[data-test="count"]').text()).toBe('0')
})

因為 case 1 和 case 2 使用的語法都是我們昨天有介紹的,所以我就直接放上程式碼不多做解釋,如果看不太懂的朋友可以趕快去看昨天的文章 Vue 3 單元測試 (Unit Testing) - Conditional rendering & Elements visibility

Case 3: click 一次 button 後,count 的值變成 1。

test('after click, count will be 1', async () => {
  const wrapper = mount(Component)

  await wrapper.get('[data-test="button"]').trigger('click')

  expect(wrapper.get('[data-test="count"]').text()).toBe('1')
})

語法說明:

  • trigger(): trigger 可以用來觸發 DOM 事件,例如 click、submit 或 keyup 等操作,值得注意的是, trigger 回傳的是一個 Promise,也因此我使用了 async & await 的方式來等待 promise resolve。

Emitted Events

除了瀏覽器定義的事件類型,如 click、submit 或 keyup 以外,在 Vue 中我們也可以利用 emits 來定義客製化的事件類型,這類型的事件通常是由子元件向父元件所觸發的。

import { ref } from 'vue'

const Component = {
  template: `
    <div>
      <button data-test="button" @click="increment">Increment</button>
    </div>
  `,
  emits: ['increment'],
  setup (props, context) {
    const count = ref(0)
    const increment = () => {
      count.value += 1
      context.emit('increment', count.value)
    }

    return {
      count,
      increment
    }
  }
}

在元件中有一個掛載 click 事件的 button,click 後會將 count 的值加 1 並且 emit 出去。

要測試這個元件是否正常,我們應該驗證四種情況是否正確運行:

  • Case 1: button 應該要存在。
  • Case 2: count 的初始值為 0。
  • Case 3: click 後觸發 emit('increment') 事件。
  • Case 4: emit('increment') 將最新的 count 值拋出。

case 1 我們一樣跳過不多做說明,不過 case 2 在這邊就有點不一樣了,因為現在 template 中少了呈現 count 的元素,所以底下會馬上介紹要如何應對!

Case 2: count 的初始值為 0。

test('The initial value of count is 0', async () => {
  const wrapper = mount(Component)

  expect(wrapper.vm.count).toBe(0)
})

語法說明:

  • vm: vm 是 VueWrapper 的一個屬性,我們可以透過 vm 來取得 Vue instance,如此一來就能再透過 vm 取得 count 變數了。

Case 3: click 後觸發 emit('increment') 事件。

test('emits an event when clicked', async () => {
  const wrapper = mount(Component)

  await wrapper.get('[data-test="button"]').trigger('click')

  expect(wrapper.emitted()).toHaveProperty('increment')
})

語法說明:

  • emitted() : emitted() 會回傳一個紀錄元件發出的所有事件的物件,其中也包含著 emit 的參數。
  • toHaveProperty(): jest 有提供一個 toHaveProperty 的匹配器 (matcher),可以用來檢查物件中是否存在某屬性。

我稍微再解釋一下 emitted() 的回傳值,以上面為例子, 回傳的內容會長得像這樣。

{
  increment: [ [ 1 ] ],
  click: [ [ MouseEvent ] ]
}

物件中的 key (increment 和 click) 是觸發的事件名稱,value 則是事件的參數,然而因為同一個事件可能會觸發多次,因此是用二維陣列來儲存,第一層的陣列代表著不同次事件的參數,第二層的陣列代表著同一次事件的不同參數,所以如果 increment 觸發兩次的話,它的回傳值會長的像。

{
  increment: [ [ 1 ], [2] ]
}

Case 4: emit('increment') 將最新的 count 值拋出。

test('after clicked, it will emit value 1', async () => {
  const wrapper = mount(Component)

  await wrapper.get('[data-test="button"]').trigger('click')

  const incrementEvent = wrapper.emitted('increment')

  expect(incrementEvent[0]).toEqual([1])
})

語法說明:

  • toEqual(): toEqual() 匹配器會去比較物件的所有屬性或陣列的所有元素是否相等。

參考資料


今天的分享就到這邊,如果大家對我分享的內容有興趣歡迎點擊追蹤 & 訂閱系列文章,如果對內容有任何疑問,或是文章內容有錯誤,都非常歡迎留言討論或指教的!

明天要來分享的是 Vu3 單元測試 (Unit Testing) 主題的第五篇 Form Elements Handling ,那我們明天見!


上一篇
[Day18] Vue 3 單元測試 (Unit Testing) - Conditional rendering & Elements visibility
下一篇
[Day20] Vue 3 單元測試 (Unit Testing) - Form Elements Handling
系列文
前端工程師在工作中的各種實戰技能 (Vue 3)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言