Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

feat($componentController): provide isolated scope if none is passed #14425

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -2196,8 +2196,8 @@ angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
* A service that can be used to create instances of component controllers.
* <div class="alert alert-info">
* Be aware that the controller will be instantiated and attached to the scope as specified in
* the component definition object. That means that you must always provide a `$scope` object
* in the `locals` param.
* the component definition object. If you do not provide a `$scope` object in the `locals` param
* then the helper will create a new isolated scope as a child of `$rootScope`.
* </div>
* @param {string} componentName the name of the component whose controller we want to instantiate
* @param {Object} locals Injection locals for Controller.
Expand All @@ -2207,7 +2207,7 @@ angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
* @return {Object} Instance of requested controller.
*/
angular.mock.$ComponentControllerProvider = ['$compileProvider', function($compileProvider) {
this.$get = ['$controller','$injector', function($controller,$injector) {
this.$get = ['$controller','$injector', '$rootScope', function($controller, $injector, $rootScope) {
return function $componentController(componentName, locals, bindings, ident) {
// get all directives associated to the component name
var directives = $injector.get(componentName + 'Directive');
Expand All @@ -2225,6 +2225,13 @@ angular.mock.$ComponentControllerProvider = ['$compileProvider', function($compi
}
// get the info of the component
var directiveInfo = candidateDirectives[0];
// create a scope if needed
if (!locals) {
locals = {};
}
if (!locals.$scope) {
locals.$scope = locals.$scope || $rootScope.$new(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't locals.$scope || redundant here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops yes. Good spot

}
return $controller(directiveInfo.controller, locals, bindings, ident || directiveInfo.controllerAs);
};
}];
Expand Down
20 changes: 20 additions & 0 deletions test/ngMock/angular-mocksSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,26 @@ describe('ngMock', function() {
}).toThrowError('Too many components found');
});
});

it('should create an isolated child of $rootScope, if no `$scope` local is provided', function() {
function TestController($scope) {
this.$scope = $scope;
}
module(function($compileProvider) {
$compileProvider.component('test', {
controller: TestController
});
});
inject(function($componentController, $rootScope) {
var $ctrl = $componentController('test');
expect($ctrl.$scope).toBeDefined();
expect($ctrl.$scope.$parent).toBe($rootScope);
// check it is isolated
$rootScope.a = 17;
$ctrl.$scope.a = 42;
expect($rootScope.a).toEqual(17);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this work with non-isolate scope as well ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah. I mean to check that $scope.a was undefined too.

});
});
});
});

Expand Down