Skip to content
Coding

Debug 日記:setPointerCapture is not a function:React Testing Library 中 userEvent 與 vaul 庫的相容性問題

最近在為一個使用 shadcnDrawer 的 React component 寫測試時,遇到了一個令人困惑的問題:當我使用 fireEvent.click() 撰寫測試時會正常通過,但改成使用 userEvent.click() 卻出現錯誤:


問題一:setPointerCapture is not a function

當使用 userEvent 進行測試時,會出現第一個錯誤:

從 stack trace 的 node_modules/vaul/dist/index.js:990:22 可以看出,vaul 庫在 onPress 函數中嘗試呼叫 setPointerCapture API,但在 JSDOM 測試環境中這個 API 不存在,導致測試失敗。

而這個 vaul library 其實是 MUI Drawer 所需要的依賴,因此我才遇到這個錯誤。

那為什麼 userEvent 才會遇到問題, fireEvent 卻不會呢?

userEvent vs fireEvent 的差異

  • fireEvent :直接觸發 DOM 事件,不會觸發 vaul 的邏輯
  • userEvent :模擬真實使用者行為,包括 pointerdown、pointermove 等事件,觸發了 vaul 的機制

要怎麼修好他

測試中加入 pointer capture API 的 polyfill:


問題二:Cannot read properties of undefined (reading ‘match’)

修復第一個問題後,可能會遇到第二個錯誤:

為什麼會發生這個錯誤?

從 stack trace 的 node_modules/vaul/dist/index.js:426:25 可以看出,問題發生在 getTranslate 函數中:

JSDOM 的 getComputedStyle() 對於 transform 屬性回傳 undefined,當 vaul 嘗試對 undefined 呼叫 .match() 方法時就會出錯。

要怎麼修好他

在測試中 mock getComputedStyle 的 transform 屬性:


希望今天的文章對你有幫助,我們下次見 👋🏻