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

Commit

Permalink
fix(ngMock#$controller): properly assign bindings to all types of con…
Browse files Browse the repository at this point in the history
…trollers (e.g. class-based)

The decorated version of `$controller` is able to assign bindings to a controller instance prior to
instantiation, emulating the behavior of `$compile` with directive controllers.

There are cases, that the actual controller instance is different than the pre-populated one (e.g.
when the controller constructor function returns a value or when the controller is an ES2015 Class).
While `$compile` accounts for such situation, by re-asigning the bindings after the controller has
been instantiated, `ngMock`'s `$controller` didn't.

This commit fixes it, by re-applying the bindings if the actual controller instance is different
than the original one (similar to how `$compile` would do it).

Fixes #14437

Closes #14439
  • Loading branch information
gkalpak committed Jun 7, 2016
1 parent 48c8b23 commit 96266b9
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 3 deletions.
12 changes: 9 additions & 3 deletions src/ngMock/angular-mocks.js
Expand Up @@ -2205,9 +2205,15 @@ angular.mock.$RootElementProvider = function() {
angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
return function(expression, locals, later, ident) {
if (later && typeof later === 'object') {
var create = $delegate(expression, locals, true, ident);
angular.extend(create.instance, later);
return create();
var instantiate = $delegate(expression, locals, true, ident);
angular.extend(instantiate.instance, later);

var instance = instantiate();
if (instance !== instantiate.instance) {
angular.extend(instance, later);
}

return instance;
}
return $delegate(expression, locals, later, ident);
};
Expand Down
48 changes: 48 additions & 0 deletions test/ngMock/angular-mocksSpec.js
@@ -1,5 +1,7 @@
'use strict';

/* globals support: false */

describe('ngMock', function() {
var noop = angular.noop;

Expand Down Expand Up @@ -1919,6 +1921,52 @@ describe('ngMock', function() {
expect(called).toBe(true);
});
});

it('should support assigning bindings when a value is returned from the constructor',
function() {
var called = false;
var data = [
{ name: 'derp1', id: 0 },
{ name: 'testname', id: 1 },
{ name: 'flurp', id: 2 }
];
module(function($controllerProvider) {
$controllerProvider.register('testCtrl', function() {
called = true;
expect(this.data).toBe(data);

return {};
});
});
inject(function($controller, $rootScope) {
var ctrl = $controller('testCtrl', { scope: $rootScope }, { data: data });
expect(ctrl.data).toBe(data);
expect(called).toBe(true);
});
}
);

if (/chrome/.test(navigator.userAgent)) {
it('should support assigning bindings to class-based controller', function() {
var called = false;
var data = [
{ name: 'derp1', id: 0 },
{ name: 'testname', id: 1 },
{ name: 'flurp', id: 2 }
];
module(function($controllerProvider) {
//jshint evil: true
var TestCtrl = eval('(class { constructor() { called = true; } })');
//jshint evil: false
$controllerProvider.register('testCtrl', TestCtrl);
});
inject(function($controller, $rootScope) {
var ctrl = $controller('testCtrl', { scope: $rootScope }, { data: data });
expect(ctrl.data).toBe(data);
expect(called).toBe(true);
});
});
}
});


Expand Down

0 comments on commit 96266b9

Please sign in to comment.