JavaScript 的聚焦測試
來自: http://www.oschina.net/translate/testing-focus-in-javascript
這篇博文是關于在瀏覽器中測試焦點行為的一個概述。
在 Azure Portal 工作中,我花了相當多的時間來確保豐富的鍵盤支持。這就需要對焦點進行適當的管理。當用戶按下一些快捷鍵時,焦點應該移動到相應的元素上。焦點行為還應當非常便于測試,因為它很容易在 HTML 或 JavaScript 進行了細微變化時 被改變(打斷)。
標準測試流程如下:
-
準備:打開一些頁面
-
進行:執行一些應該能打開一個指定頁面并(或)在相應元素上設置焦點的快捷鍵
-
斷言:檢測預期的元素是否獲得焦點
</div>
如何檢查元素是否獲得焦點
最簡單的方式是使用 jQuery:
expect($(element).is(':focus')).equals(true);
然而,這可能不是在任何時候都好使,特別是當你并行運行你的單元測試的話,因為 當窗口沒有獲得焦點時 $element.is(‘:focus’) 將無法正常工作 。
更好(正確)的方式是使用 document.activeElement :
expect(document.activeElement).equals(element);
就算瀏覽器窗口沒有獲得焦點時其也能正常工作。
測試異步操作
有時,鍵盤調用異步操作最終會改變焦點。這可能會導致:
-
漏報(false negative):斷言在焦點被設置之前執行
-
誤報(false positives):最終聚焦的元素,是在斷言執行之后才獲得焦點的
對于第一個問題最簡單的方案就是延遲進行斷言:
setTimeout(() => { expect(document.activeElement).equals(element); done(); }, 100);
這種方法的難點在于選擇合適的延遲時間。因此,最好避免使用原生的 setTimeout, 而是使用我在 setTimeout 被認為是有害的 一文中寫的這種輪詢方法:
poll( () => document.activeElement === element, () => { assert(true); start(); }, () => { assert(false); start(); } );
輪詢函數也可以用來解決第二個問題(通過改變回調函數中的斷言順序)。然而,對于誤報的問題,簡單的 setTimeout 已經足夠了,因為相比于等待某些特定的時間執行斷言我們沒有其他選擇。
調用鍵盤操作
有下列 3 種可以讓我們用來模擬鍵盤操作的事件:
-
keydown
-
keyup
-
keypress
最安全的方式是使用 keydown。為啥呢? 一個示例中可能使用了特殊的功能鍵。而在使用 keypress 的情況下 —— 各個瀏覽器對其進行的處理是不同的(例如,不觸發事件),而 keydown 的行為則是相當一致的。如果你對細節感興趣的話,我建議你看看 這篇文章 。
為了檢測 鍵盤操作, 你可以在 捕獲和冒泡階段 處理事件。你應該選擇符合你需求的模型,但通常冒泡階段是最佳的解決方案。此外,它是被 jQuery 支持的,可以為你兼容瀏覽器。
為了在測試中調用 keydown 事件,你首先需要在元素上設置焦點:
$(element) .focus() .trigger("keydown", { which: keyCode });
你可以在 這里 找到 JavaScript 鍵碼。
總結
-
使用 document.activeElement 檢查哪個元素獲得了焦點。
-
使用輪詢的方法來測試異步操作。
-
使用 keydown 事件,以及冒泡階段調用(處理)鍵盤操作。