I wanted to test a component using the UI elements to avoid testing to much implementation details.
When doing that, I faced was faced with an input and did not find easily how to trigger its change events to trigger the ng-model
change and the ng-change
event.
Here is how I did it. (This come late given that AngularJS is deprecated. But I guess I will not be the only one lucky enough to still work with it sometime.)
The test base
For these tests, we will use the angular-mocks
library.
We will use le $compile
to instanciate the component. And then interact with the component by using the compiled elements.
We will compile the input
directly to make the tests easier. We could compile a component that have inputs and retrieve them by calling the JQuery .find(<selector>)
on the compiled element.
We will use the Jest syntax for the test declaration and assertions.
require('angular');
require('angular-mocks');
describe('test', () => {
let $rootScope;
let $compile;
let $timeout;
beforeEach(inject((_$rootScope_, _$compile_, _$timeout_) => {
$rootScope = _$rootScope_;
$compile = _$compile_;
$timeout = _$timeout_;
}));
// ...
});
Simple ng-model test
In this test, we will use a simple input
without ng-model-options
.
To update the ng-model
update and ng-change
update we will use the following JQuery operations:
- .val(<value>)
to update the value
- .triggerHandler('change')
to send the change
event of the input
it('Should trigger change ng-model value and trigger ng-change', () => {
const scope = $rootScope.$new();
scope.value = '';
scope.onChange = jest.fn();
const element = $compile('<input ng-model="value" ng-change="onChange()">')(scope);
scope.$digest();
element.val('test').triggerHandler('change');
expect(scope.value).toBe('test');
expect(scope.onChange).toHaveBeenCalled();
});
ng-model with update on blur
In this test, we will use a simple input
with ng-model-options
to update only when the input blur
event is triggered.
The blur
event is triggered when the field looses focus.
This may be used to avoid updating every time the value changes if we know that we will only use the value when the input will be filled.
To update the ng-model
update and ng-change
update we will use the following JQuery operations:
- .val(<value>)
to update the value
- .triggerHandler('change')
to send the change
event of the input
- .triggerHandler('blur')
to send the blur
event of the input
it('Should trigger change ng-model value and trigger ng-change (update on blur)', () => {
const scope = $rootScope.$new();
scope.value = '';
scope.onChange = jest.fn();
const element = $compile('<input ng-model="value" ng-model-options="{ updateOn: \'blur\' }" ng-change="onChange()">')(scope);
scope.$digest();
element.val('test').triggerHandler('change').triggerHandler('blur');
expect(scope.value).toBe('test');
expect(scope.onChange).toHaveBeenCalled();
});
ng-model with debounce
In this test, we will use a simple input
without ng-model-options
.
The debounce option can be used to update the value only when the if it does not change for a given time.
This make it possible to keep up to date even if the input does not loose focus while avoiding getting too much events.
It can be useful for elements like search inputs where we want to show suggestions while the user types. But we do not want to do the computation on every change because it can be quite heavy.
To update the ng-model
update and ng-change
update we will use the following JQuery operations:
- .val(<value>)
to update the value
- .triggerHandler('change')
to send the change
event of the input
Then we will use $timeout.flush()
for the code to act like if the debounce time has passed.
it('Should trigger change ng-model value and trigger ng-change (debounce)', () => {
const scope = $rootScope.$new();
scope.value = '';
scope.onChange = jest.fn();
const element = $compile('<input ng-model="value" ng-model-options="{ debounce: 200 }" ng-change="onChange()">')(scope);
scope.$digest();
element.val('test').triggerHandler('change');
$timeout.flush();
expect(scope.value).toBe('test');
expect(scope.onChange).toHaveBeenCalled();
});
Top comments (1)
Nice Post!
khanzadapc.com/waves-tune-real-tim...