I've been building a directive that restricts a user from pressing certain invalid characters, in this case, using the keypress
event binding to the input element that uses my directive.
I've been trying to test this functionality, but i don't understand how to achieve this.
My directive
angular
.module('gp.rutValidator')
.directive('gpRutValidator', directive);
directive.$inject = ['$filter'];
function directive($filter){
var ddo = {
restrict: 'A',
require: 'ngModel',
link: linkFn
};
return ddo;
function linkFn(scope, element, attrs, ngModel){
//valid characters are digits, dash and letter k
var regexValidKeys = (/[\d\.\-k]/i);
element.bind('keypress', function(e){
var key = e.key || String.fromCharCode(e.keyCode);
if (!regexValidKeys.test(key)) {
e.preventDefault();
return false;
}
});
}
}
My test
describe('Angular Rut Validator Directive',validatorDirectiveSpec);
function validatorDirectiveSpec(){
////////////// GLOBALS ////////////////////////////////
var scope, element, evt;
////////////// BEFORE EACH ////////////////////////////////
beforeEach(module('gp.rutValidator'));
beforeEach(inject(eachSpec));
function eachSpec($rootScope, $compile){
element = angular.element('<input ng-model="rut" gp-rut-validator>');
scope = $rootScope.$new();
$compile(element)(scope);
scope.$digest();
}
////////////////// HELPERS ///////////////////////////////////
function pressKey(keyCode) {
try {
// Chrome, Safari, Firefox
evt = new KeyboardEvent('keypress');
delete evt.keyCode;
Object.defineProperty(evt, 'keyCode', {'value': keyCode});
}
catch (e) {
// PhantomJS
evt = document.createEvent('Events');
evt.initEvent('keypress', true, true);
evt.keyCode = keyCode;
}
element[0].dispatchEvent(evt);
}
////////////////// SPECS //////////////////////////////////
it('1. Should be reject no valid characters', spec1);
function spec1(){
var ngModelCtrl = element.controller('ngModel'),
invalidCharacterKeys = [
'a'.charCodeAt(0),
'z'.charCodeAt(0),
'b'.charCodeAt(0),
'#'.charCodeAt(0)
];
invalidCharacterKeys.forEach(function(keyCode){
pressKey(keyCode);
scope.$digest();
expect(scope.rut).toBe('');
});
}
}
But I get the error Expected undefined to be ''.
What am I doing wrong?
Example in Codepen => http://codepen.io/gpincheiraa/pen/ozWyvA
How about replacing the Event.prototye.preventDefault:
var original = Event.prototype.preventDefault;
Event.prototype.preventDefault = function(){
original.bind(this);
handlers.filter((handler) => handler.keyCode == this.keyCode).forEach((handler)=>handler.handle(this));
handlers = handlers.filter((handler)=> handler.keyCode != this.keyCode);
}
and make him call a predefined Callback:
function pressKey(keyCode, cb) {
try {
// Chrome, Safari, Firefox
handlers.push({keyCode : keyCode, handle: cb});
evt = new KeyboardEvent('keypress');
delete evt.keyCode;
Object.defineProperty(evt, 'keyCode', {'value': keyCode});
element[0].dispatchEvent(evt);
}
catch (e) {
// PhantomJS
evt = document.createEvent('Events');
evt.initEvent('keypress', true, true);
evt.keyCode = keyCode;
element[0].dispatchEvent(evt);
}
}
and then call pressKey like this:
pressKey(keyCode, (event)=>{expect(event.keyCode).toBe(keyCode)}));
I am not 100% sure if this is what you've asked for...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With