Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manually trigger Angular data binding for an input field (for unit testing purposes only)

I'm writing some tests for an Angular directive and I need to simulate user input into an input field. I tried to do this:

element.find('input').val('some value').trigger('input');

but it didn't work. Triggering change didn't work either. I know I can access the element scope directly with element.scope() and change it, but it seems more natural to change the input's value and let Angular do the data binding.

For what it's worth, I've checked out input(name).enter(value) from Angular ngScenario, and it seems to do the same as I did:

...
input.val(value);
input.trigger(event || (supportInputEvent ? 'input' : 'change'));
...

What am I missing? Is there a better way to test user input in this case?

(I made a jsFiddler script to illustrate the question)

UPDATE

I think some clarification is needed. I'm not trying to change the DOM nor the scope outside Angular realm per se. I have a directive that renders an input box bound to a property of the directive's scope. I'm writing automated tests to ensure the directive does what it's supposed to do, and what one test should do is to simulate some input so that the directive scope gets updated and I can assert that some behavior is performed on that input. As I mentioned earlier, I can change the directive's scope from the test code by using element.scope(), but I'd rather change the input's value and let Angular do its thing.

like image 987
Michael Benford Avatar asked Jul 30 '13 06:07

Michael Benford


1 Answers

After spending some more time researching and testing, I've figured out what was wrong: jqLite registers event handlers using addEventHandler and they don't get triggered by jQuery trigger function. My jsFiddle script wasn't working because Angular's script was being loaded before jQuery's (and therefore was using jqLite). I updated the script to load everything in the correct order so that Angular uses jQuery on function to register event handlers, and now it simulates changes on the input box and tells Angular to do the data binding.

My test code wasn't working for the very same reason. I fixed it by changing the scripts order as well. If I didn't happen to be using jQuery, I would have to trigger the event by calling dispatchEvent instead of trigger.

like image 185
Michael Benford Avatar answered Sep 30 '22 18:09

Michael Benford