тестирование событий keydown в Jasmine с определенным кодом ключа
Я пишу тесты для директивы AngularJS, которая запускает события <textarea>
при нажатии определенных клавиш. Все это отлично работает в моем ручном тестировании. Я хочу быть хорошим и иметь полный набор модульных тестов, но я столкнулся с проблемой, которую не могу решить самостоятельно:
Я хочу отправить конкретный keyCode
в своем triggerHandler()
звонок в мой тест, но я не могу найти способ указать ключ это действительно работает. Я знаю о много вопросы и ответы на тему построения и отправки событий с конкретными данными, но ни один из них не работает на моей настройке:
Мои настройки
- карма тестов
- PhantomJS browser запускает тесты (но также пробовал 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 и увидеть, что событие создается С the keyCode
свойство установлено в 40.
Итак, кажется, что он должен работать.
кроме того, когда я вызываю последнюю строку, как это textarea.triggerHandler("keydown");
он работает, и обработчик событий запускается. Однако, нет keyCode
для работы с, так что это бессмысленно.
Я подозреваю, что это может быть связано с характером теста, запущенного против DOM, который отличается от обычной страницы, запущенной в браузер. Но я не могу понять!
2 ответов
я использовал следующее решение для его тестирования и его работы в Chrome, FF, PhantomJS и IE9+ на основе этого Так что ответ. Он не работает в 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);
надеюсь, что это помогает
обновление
сегодня я нашел и протестировал это решение, которое предлагает гораздо более широкий охват браузеров (включая наследие поддержка):
https://gist.github.com/termi/4654819
вся заслуга принадлежит автору этой истории. Код поддерживает Safari, PhantomJS и IE9-протестирован для первых 2.
добавляя к ответу @MarcoL, я хотел бы указать будущим читателям, которые могут наткнуться на этот вопрос, что методы initKeyboardEvent
и initKeyEvent
являются устаревшими методами и больше не должны использоваться. См.здесь и здесь.
вместо этого, как предложили документы MDN, события должны быть созданы через их соответствующий конструктор.