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

Commit 96266b9

Browse files
committed
fix(ngMock#$controller): properly assign bindings to all types of controllers (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
1 parent 48c8b23 commit 96266b9

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

src/ngMock/angular-mocks.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -2205,9 +2205,15 @@ angular.mock.$RootElementProvider = function() {
22052205
angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
22062206
return function(expression, locals, later, ident) {
22072207
if (later && typeof later === 'object') {
2208-
var create = $delegate(expression, locals, true, ident);
2209-
angular.extend(create.instance, later);
2210-
return create();
2208+
var instantiate = $delegate(expression, locals, true, ident);
2209+
angular.extend(instantiate.instance, later);
2210+
2211+
var instance = instantiate();
2212+
if (instance !== instantiate.instance) {
2213+
angular.extend(instance, later);
2214+
}
2215+
2216+
return instance;
22112217
}
22122218
return $delegate(expression, locals, later, ident);
22132219
};

test/ngMock/angular-mocksSpec.js

+48
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
/* globals support: false */
4+
35
describe('ngMock', function() {
46
var noop = angular.noop;
57

@@ -1919,6 +1921,52 @@ describe('ngMock', function() {
19191921
expect(called).toBe(true);
19201922
});
19211923
});
1924+
1925+
it('should support assigning bindings when a value is returned from the constructor',
1926+
function() {
1927+
var called = false;
1928+
var data = [
1929+
{ name: 'derp1', id: 0 },
1930+
{ name: 'testname', id: 1 },
1931+
{ name: 'flurp', id: 2 }
1932+
];
1933+
module(function($controllerProvider) {
1934+
$controllerProvider.register('testCtrl', function() {
1935+
called = true;
1936+
expect(this.data).toBe(data);
1937+
1938+
return {};
1939+
});
1940+
});
1941+
inject(function($controller, $rootScope) {
1942+
var ctrl = $controller('testCtrl', { scope: $rootScope }, { data: data });
1943+
expect(ctrl.data).toBe(data);
1944+
expect(called).toBe(true);
1945+
});
1946+
}
1947+
);
1948+
1949+
if (/chrome/.test(navigator.userAgent)) {
1950+
it('should support assigning bindings to class-based controller', function() {
1951+
var called = false;
1952+
var data = [
1953+
{ name: 'derp1', id: 0 },
1954+
{ name: 'testname', id: 1 },
1955+
{ name: 'flurp', id: 2 }
1956+
];
1957+
module(function($controllerProvider) {
1958+
//jshint evil: true
1959+
var TestCtrl = eval('(class { constructor() { called = true; } })');
1960+
//jshint evil: false
1961+
$controllerProvider.register('testCtrl', TestCtrl);
1962+
});
1963+
inject(function($controller, $rootScope) {
1964+
var ctrl = $controller('testCtrl', { scope: $rootScope }, { data: data });
1965+
expect(ctrl.data).toBe(data);
1966+
expect(called).toBe(true);
1967+
});
1968+
});
1969+
}
19221970
});
19231971

19241972

0 commit comments

Comments
 (0)