Unexpected behavior in unit-tests using $componentController and &-bindings to pass data #14426
Description
Do you want to request a feature or report a bug?
Bug with using $componentController
, &
-bindings, and passing arguments.
What is the current behavior?
Using $componentController
to instantiate the controller of a component that has an &
-binding used to pass data back to its user results in unexpected argument data being passed to the function.
_Example_
Given:
angular.module('heroApp', [])
.component('heroDetail', {
template: '<div></div>',
bindings: {
hero: '<',
onDelete: '&'
}
});
The current behavior using $componentController
is:
it('should call the onDelete binding when a hero is deleted', function() {
var deleteSpy = jasmine.createSpy('deleteSpy');
component = $componentController('heroDetail',
{$scope: scope},
{
hero: {name: 'Wolverine'},
onDelete: deleteSpy
}
);
component.onDelete({hero: component.hero});
// Spy is called with object map, instead of just the "hero" value
expect(deleteSpy).toHaveBeenCalledWith({hero: component.hero});
});
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar (template: http://plnkr.co/edit/tpl:yBpEi4).
Here is a minimal demo, comparing $componentController
and $compile
to unit-test the onDelete
binding: Demo
What is the expected behavior?
Given the same "heroDetail" component as above, one would expect the following test to succeed:
it('should call the onDelete binding when a hero is deleted', function() {
var deleteSpy = jasmine.createSpy('deleteSpy');
component = $componentController('heroDetail',
{$scope: scope},
{
hero: {name: 'Wolverine'},
onDelete: deleteSpy
}
);
component.onDelete({hero: component.hero});
// Spy is called with the object map, instead of just the "hero" value
expect(deleteSpy).toHaveBeenCalledWith(component.hero);
});
This would make $componentController
's behavior consistent with $compile
's behavior (and the real world).
What is the motivation / use case for changing the behavior?
Using components is the recommended design-pattern from AngularJS 1.5.0. Using $componentController
in unit-tests to instantiate component controllers greatly simplifies testing code. One would expect behavior to be consistent with the real world (and the former unit test implementation technique using $compile
).
Which versions of Angular, and which browser / OS are affected by this issue? Did this work in previous versions of Angular? Please also test with the latest stable and snapshot (https://code.angularjs.org/snapshot/) versions.
AngularJS >=1.5.0 using Chrome 49 and Safari 9.0.3