Angular: is it possible to test certain characters in a keypress event?

I am creating a directive that prevents the user from clicking on certain invalid characters, in this case, using the keypress event keypress on an input element that uses my directive. I tried to test this functionality, but I do not understand how to do it.

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

+6
source share
3 answers

How about replacing 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 it 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 press pressKey as follows:

 pressKey(keyCode, (event)=>{expect(event.keyCode).toBe(keyCode)})); 

I am not 100% sure if this is what you asked for ...

+1
source

Use this code it('1. Should be reject not valid characters') instead of it('1. Should be reject no valid characters', spec1);

0
source

How about extracting logic from infrastructure / low level code and more clear testing?

In other words, define a service that accepts the key as an input, and then returns true/false . The service does not listen for the event of the html element, it just accepts the input and gives the result. Thus, you can test this service (like any other service) using your jasmine unit tests. Then add this service to your directive and call it from the event handler (binding still occurs inside the directive). If the service returns false, also call e.preventDefault() , otherwise enable the key.

Obviously, this approach will not check how you are subscribing to the event of the html (bind) element, but I do not think your intention at all. This will check which keys are accepted / rejected just fine, following a cleaner separation of problems - this is MVC in the end, which is related to the separation of problems.

0
source

All Articles