Angular 1.5.0
The component test examples set at https://docs.angularjs.org/guide/component implies that $onInit() is supposed to be automatically triggered when instanciating a controller through $componentController , as seen below
it('should set the default values of the hero', function() {
component = $componentController('heroDetail', {$scope: scope});
expect(component.hero).toEqual({
name: undefined,
location: 'unknown'
});
});
Issue : The $onInit() method is never called even if the component has a this.$onInit() method defined in its controller. Either a bug or documentation mistake.
If $onInit() is called manually, such a test works.
it('should set the default values of the hero', function() {
component = $componentController('heroDetail', {$scope: scope});
component.$onInit();
expect(component.hero).toEqual({
name: undefined,
location: 'unknown'
});
});
A test which actually compile the component, not using $componentController , doesn't encounter this kind of issue.
it('should set the default values of the hero', function() {
var element = "<hero-detail></hero-detail>";
element = $compile(element )(scope);
scope.$digest();
var controller = element.controller('heroDetail');
expect(controller.hero).toEqual({
name: undefined,
location: 'unknown'
});
})
It would depend on the implementation of the controller. There is nothing implying that there is an $onInit()
method. (Or did I miss something ?)
But it does seem like the tests are out-of-sync with the actual implementation of the HeroDetailController
... (e.g. there is no initialization in the actual controller).
@arch-lm, would you like to submit a PR for that ?
There are three options:
$onInit
there is a risk that given component uses require
controllers and there is not enough information available (it is just constructing one isolated controller, there are no parents or other requirement structure)$onInit
assuming that there will be no require
controllers, and throw an exception if there are in fact require
controllers$componentController
with require
controllers instances (mocks, ...) and then call $onInit
.We already have the bindings parameter and it is likely that we can add the require
controllers instances, but by doing that we cannot test the two stages in the initialization: one with bindings (constructor), another with requires($onInit). So it should be an extra argument, the fifth... too many arguments.I do not have yet in my mind which of one is best for now.
I'm thinking that $componentController
should have tests for ES6 classes, because it seems to deal different with bindings (as I understand from documentation it says that they follow the same cycle of life than require
controller instances). May be should be better to assume that everything follows ES6 classes cycle of life in the $componentController
so bindings can have require
controllers, so no fifth argument.
Uhmmm after think a little bit I arrived to the following:
$componentController
to execute $onInit
will be a breaking change (in tests so all breaks should be likely to be detected, and it can be considered to have low affectation)$onInit
, I explain it: $componentController
is to instance controllers a kind of replacement for $controller
, but instead of creating instances of controllers registered by the controllerProvider
it creates instances of controllers _registered_ through directives (the ones that satisfies a component definition). So, once you have the instance of the controller, you can call manually $onInit
, and all the lifecycle of your controller, the idea is that you are testing a controller, not a directive (and its relationships). Good thinking :smiley: $onInit
(and the lifecycle hooks in general) are related to directives. They are not specific to components (in contrast to $componentController
) and not specific to controllers outside of the context of a directive.
$componentController
does also support locals, so one could set required controllers and manually invoke $onInit
if they need to. IMO, the current behavior is fine.
--
Still, if someone wanted to submt a PR for https://github.com/angular/angular.js/issues/14129#issuecomment-188702281, that would be awesome :smiley:
@gkalpak is there any example with the Jasmine ready to fiddle in that could be added to the ngdocs?
I cannot found any and I do not like the idea of build a mini-app to verify the test and then throw it away.
@drpicox, I use this pen as a base for testing with Jasmine.
I'm not too keen on adding something like this to the docs, because such kinds of stuff tends to get outdated pretty quickly and its usefulness is quite limilted for people visiting the docs anyway.
I think this can be closed now, as the potentially confusing bit related to $onInit seems to have been removed.
:+1: Closing