Тестирование событий keydown в Jasmine с помощью специального keyCode
Я пишу тесты для директивы AngularJS, которая запускает события <textarea>
при нажатии определенных клавиш. Все это прекрасно работает при моем ручном тестировании. Я хочу быть хорошим и иметь полный набор модулей тестирования, но у меня возникла проблема, которую я не могу решить самостоятельно:
Я хочу отправить конкретный keyCode
в мой вызов triggerHandler()
в моем тесте, но я не могу найти способ указать ключ , который действительно работает. Я знаю много вопросов и ответов на тему создания и отправки событий с конкретными данными, но никто из них не работает над моей настройкой:
Моя настройка
- Тест-драйв Karma
- PhantomJS-браузер, выполняющий тесты (но также безуспешно использовал Firefox и Chrome)
- Я не использую jQuery, и я надеюсь, что есть регулярное решение JS. Должно быть!
Тестовый код
var event = document.createEvent("Events");
event.initEvent("keydown", true, true);
event.keyCode = 40; // in debugging the test in Firefox, the event object can be seen to have no "keyCode" property even after this step
textarea.triggerHandler(event); // my keydown handler does not fire
Странно то, что я могу ввести первые 3 строки в консоль в Chrome и увидеть, что событие создается с свойством keyCode
, установленным в 40.
Похоже, он должен работать.
Кроме того, когда я вызываю последнюю строку, подобную этой textarea.triggerHandler("keydown");
, она работает, и обработчик события запускается. Тем не менее, нет keyCode
для работы, поэтому это бессмысленно.
Я подозреваю, что это может быть связано с характером теста, выполняющегося с DOM, который отличается от обычной страницы, запущенной в браузере. Но я не могу понять это!
Ответы
Ответ 1
Я использовал следующее решение для тестирования и работу в Chrome, FF, PhantomJS и IE9 + на основе этого SO-ответа.
Он не работает в Safari - без проблем пытался миллионы других решений...
function jsKeydown(code){
var oEvent = document.createEvent('KeyboardEvent');
// Chromium Hack: filter this otherwise Safari will complain
if( navigator.userAgent.toLowerCase().indexOf('chrome') > -1 ){
Object.defineProperty(oEvent, 'keyCode', {
get : function() {
return this.keyCodeVal;
}
});
Object.defineProperty(oEvent, 'which', {
get : function() {
return this.keyCodeVal;
}
});
}
if (oEvent.initKeyboardEvent) {
oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, false, false, false, false, code, code);
} else {
oEvent.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, code, 0);
}
oEvent.keyCodeVal = code;
if (oEvent.keyCode !== code) {
console.log("keyCode mismatch " + oEvent.keyCode + "(" + oEvent.which + ") -> "+ code);
}
document.getElementById("idToUseHere").dispatchEvent(oEvent);
}
// press DEL key
jsKeydown(46);
Надеюсь, что это поможет
Update
Сегодня я нашел и протестировал это решение, которое предлагает гораздо более широкий охват браузеров (включая поддержку старых):
https://gist.github.com/termi/4654819
Весь кредит принадлежит автору этого GIST.
Код поддерживает Safari, PhantomJS и IE9 - проверен на первые 2.