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

Commit

Permalink
feat(ngMock.$componentController): add helper to instantiate controll…
Browse files Browse the repository at this point in the history
…ers for components

Closes #13683
Closes #13711
  • Loading branch information
petebacondarwin committed Jan 10, 2016
1 parent 7e24590 commit dd14e0c
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 3 deletions.
9 changes: 7 additions & 2 deletions src/ng/compile.js
Expand Up @@ -928,6 +928,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return this;
};

this.$$componentControllers = createMap();
/**
* @ngdoc method
* @name $compileProvider#component
Expand Down Expand Up @@ -1052,6 +1053,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
* See also {@link ng.$compileProvider#directive $compileProvider.directive()}.
*/
this.component = function registerComponent(name, options) {
var controller = options.controller || function() {};
var ident = identifierForController(options.controller) || options.controllerAs || '$ctrl';
this.$$componentControllers[name] = { controller: controller, ident: ident};

function factory($injector) {
function makeInjectable(fn) {
if (isFunction(fn) || isArray(fn)) {
Expand All @@ -1065,8 +1070,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {

var template = (!options.template && !options.templateUrl ? '' : options.template);
return {
controller: options.controller || function() {},
controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
controller: controller,
controllerAs: ident,
template: makeInjectable(template),
templateUrl: makeInjectable(options.templateUrl),
transclude: options.transclude,
Expand Down
31 changes: 30 additions & 1 deletion src/ngMock/angular-mocks.js
Expand Up @@ -2161,6 +2161,34 @@ angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
};
}];

/**
* @ngdoc service
* @name $componentController
* @description
* 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.
* </div>
* @param {string} componentName the name of the component whose controller we want to instantiate
* @param {Object} locals Injection locals for Controller.
* @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used
* to simulate the `bindToController` feature and simplify certain kinds of tests.
* @param {string=} ident Override the property name to use when attaching the controller to the scope.
* @return {Object} Instance of requested controller.
*/
angular.mock.$ComponentControllerProvider = ['$compileProvider', function($compileProvider) {
return {
$get: ['$controller', function($controller) {
return function $componentController(componentName, locals, bindings, ident) {
var controllerInfo = $compileProvider.$$componentControllers[componentName];
return $controller(controllerInfo.controller, locals, bindings, ident || controllerInfo.ident);
};
}]
};
}];


/**
* @ngdoc module
Expand All @@ -2184,7 +2212,8 @@ angular.module('ngMock', ['ng']).provider({
$log: angular.mock.$LogProvider,
$interval: angular.mock.$IntervalProvider,
$httpBackend: angular.mock.$HttpBackendProvider,
$rootElement: angular.mock.$RootElementProvider
$rootElement: angular.mock.$RootElementProvider,
$componentController: angular.mock.$ComponentControllerProvider
}).config(['$provide', function($provide) {
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
$provide.decorator('$$rAF', angular.mock.$RAFDecorator);
Expand Down
82 changes: 82 additions & 0 deletions test/ngMock/angular-mocksSpec.js
Expand Up @@ -1857,6 +1857,88 @@ describe('ngMock', function() {
});
});
});


describe('$componentController', function() {
it('should instantiate a simple controller defined inline in a component', function() {
function TestController($scope, a, b) {
this.$scope = $scope;
this.a = a;
this.b = b;
}
module(function($compileProvider) {
$compileProvider.component('test', {
controller: TestController
});
});
inject(function($componentController, $rootScope) {
var $scope = {};
var ctrl = $componentController('test', { $scope: $scope, a: 'A', b: 'B' }, { x: 'X', y: 'Y' });
expect(ctrl).toEqual({ $scope: $scope, a: 'A', b: 'B', x: 'X', y: 'Y' });
expect($scope.$ctrl).toBe(ctrl);
});
});

it('should instantiate a controller with $$inject annotation defined inline in a component', function() {
function TestController(x, y, z) {
this.$scope = x;
this.a = y;
this.b = z;
}
TestController.$inject = ['$scope', 'a', 'b'];
module(function($compileProvider) {
$compileProvider.component('test', {
controller: TestController
});
});
inject(function($componentController, $rootScope) {
var $scope = {};
var ctrl = $componentController('test', { $scope: $scope, a: 'A', b: 'B' }, { x: 'X', y: 'Y' });
expect(ctrl).toEqual({ $scope: $scope, a: 'A', b: 'B', x: 'X', y: 'Y' });
expect($scope.$ctrl).toBe(ctrl);
});
});

it('should instantiate a named controller defined in a component', function() {
function TestController($scope, a, b) {
this.$scope = $scope;
this.a = a;
this.b = b;
}
module(function($controllerProvider, $compileProvider) {
$controllerProvider.register('TestController', TestController);
$compileProvider.component('test', {
controller: 'TestController'
});
});
inject(function($componentController, $rootScope) {
var $scope = {};
var ctrl = $componentController('test', { $scope: $scope, a: 'A', b: 'B' }, { x: 'X', y: 'Y' });
expect(ctrl).toEqual({ $scope: $scope, a: 'A', b: 'B', x: 'X', y: 'Y' });
expect($scope.$ctrl).toBe(ctrl);
});
});

it('should instantiate a named controller with `controller as` syntax defined in a component', function() {
function TestController($scope, a, b) {
this.$scope = $scope;
this.a = a;
this.b = b;
}
module(function($controllerProvider, $compileProvider) {
$controllerProvider.register('TestController', TestController);
$compileProvider.component('test', {
controller: 'TestController as testCtrl'
});
});
inject(function($componentController, $rootScope) {
var $scope = {};
var ctrl = $componentController('test', { $scope: $scope, a: 'A', b: 'B' }, { x: 'X', y: 'Y' });
expect(ctrl).toEqual({ $scope: $scope, a: 'A', b: 'B', x: 'X', y: 'Y' });
expect($scope.testCtrl).toBe(ctrl);
});
});
});
});


Expand Down

0 comments on commit dd14e0c

Please sign in to comment.