web-dev-qa-db-fra.com

Comment déclencher implicitement $ onInit ou $ onChanges dans les tests unitaires Angular contrôleur de composant?

J'utilise Angular 1.5.5 et Jasmine comme framework de test. Actuellement, je dois faire quelque chose comme ça pour que le test réussisse:

function createController(bindings) {
    return $componentController('myController', null, bindings);
}

beforeEach(inject(function (_$componentController_) {
    $componentController = _$componentController_;
}));

describe('on pages updated', function () {

    beforeEach(function () {
        controller = createController({prop1: 0, prop2: 0});
        controller.$onInit(); // you see I have to explitcitly call this $onInit function
    });

    it('should update isSelected and currentPage', function () {
        expect(controller.prop1).toBe(0);
        expect(controller.prop2).toBe(0);

        controller.prop1= 1;
        controller.prop2= 2;
        controller.$onChanges(controller); // and $onChanges here as well

        expect(controller.prop1).toBe(1);
        expect(controller.prop2).toBe(2);
    });

});
15
Great Question

Il existe un problème dans github à ce sujet: https://github.com/angular/angular.js/issues/14129

Fondamentalement, il fonctionne comme prévu et n'appelle pas $onInit ou $onChanges automatiquement.

il n’a aucun sens (ou peu logique) d’exécuter $ onInit, je l’explique: $ composantController consiste à remplacer le contrôleur par $ directives (celles qui répondent à une définition de composant). Ainsi, une fois que vous avez l'instance du contrôleur, vous pouvez appeler manuellement $ onInit et tout le cycle de vie de votre contrôleur. L'idée est que vous testez un contrôleur, pas une directive (et ses relations).

7
Gustav

Je ne sais pas si cela aidera, mais pour tester les composants, je fais ce qui suit

beforeEach(module('templates'));

var element;        
var scope;

beforeEach(inject(function ($rootScope, $compile) {
    scope = $rootScope.$new();
    scope.draw = new ol.source.Vector({ wrapX: false });
    element = angular.element('<custom-element draw="draw"></custom-element>');
    element = $compile(element)(scope);
}));

var controller;
beforeEach(inject(function ($rootScope, $componentController) {
    scope = $rootScope.$new();
    scope.draw = new ol.source.Vector({ wrapX: false });
    controller = $componentController('customElement', {draw: new ol.source.Vector({ wrapX: false })}, { $scope: scope });
}));

et $ onInit () et $ onChanges () se déclenchent quand ils devraient être, par eux-mêmes

0
elasticrash

Vous auriez besoin de prendre la référence du contrôleur de la version compilée de l’élément. Comme indiqué ci-dessous:

describe('Component: Test Method', function () {

        beforeEach(inject(function (_$rootScope_) {
            scope = _$rootScope_.$new();
        }));


        it('should set value of selectedPackage to null after $onChanges event', inject(function ($compile) {
            // Trigger 1st $onChanges
            scope.selectedPackage = 'packageCode';

            var element = angular.element('<select-my-tv selected-package="selectedPackage"></select-my-tv>');
            element = $compile(element)(scope);
            scope.$digest();

            //Extract the Controller reference from compiled element
            var elementController = element.isolateScope().$ctrl;

            // Assert
            expect(elementController.selectedPackage).toBeNull();
        }));
    });
});
0
Maverick09