Skip to content

Commit

Permalink
Merge pull request #165 from glorious-codes/ng_lifecycle_hooks_support
Browse files Browse the repository at this point in the history
Add support for angular components lifecycle hooks
  • Loading branch information
rafaelcamargo committed Jul 24, 2020
2 parents 3e36a7f + 7f6447e commit ddfa069
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 5 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@glorious/pitsby",
"version": "1.27.8",
"version": "1.28.0",
"description": "Docs generator for AngularJS, React, Vue and Vanilla components",
"author": "Rafael Camargo <hello@rafaelcamargo.com>",
"repository": {
Expand Down
27 changes: 25 additions & 2 deletions src/webapp/scripts/services/angular-component-builder.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import angular from 'angular';

function angularComponentBuilder($compile, $controller, $injector){
function angularComponentBuilder($compile, $controller, $injector, $timeout){
const _public = {};

_public.build = ({ template, controller, dependencies }, $scope) => {
const element = buildElement(template);
const scope = buildScope($scope, controller, dependencies);
$compile(element)(scope);
handleHooks(scope, !usesOnInitHookManually(controller));
return element;
};

Expand All @@ -30,9 +31,31 @@ function angularComponentBuilder($compile, $controller, $injector){
});
}

function handleHooks(scope, shouldCallOnInitHookAutomatically){
if(shouldCallOnInitHookAutomatically)
$timeout(() => callHook(scope.$ctrl.$onInit));
scope.$on('$destroy', () => callHook(scope.$ctrl.$onDestroy));
}

function usesOnInitHookManually(controller){
const stringifiedController = stringifyController(controller);
if(stringifiedController)
return stringifiedController.includes('$onInit(') ||
stringifiedController.includes('$timeout($ctrl.$onInit');
}

function stringifyController(controller){
if(typeof controller == 'function')
return controller.toString();
}

function callHook(hook){
return hook && hook();
}

return _public;
}

angularComponentBuilder.$inject = ['$compile', '$controller', '$injector'];
angularComponentBuilder.$inject = ['$compile', '$controller', '$injector', '$timeout'];

export default angularComponentBuilder;
63 changes: 62 additions & 1 deletion src/webapp/scripts/services/angular-component-builder.test.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
describe('Angular Component Builder', () => {
let service, $scope, $window;
let service, $scope, $window, $timeout;

function compileComponent(component, scope){
const element = service.build(component, scope);
scope.$digest();
return element;
}

function buildComponent(controller, dependencies){
return { controller, template: '<div></div>', dependencies };
}

beforeEach(() => {
angular.mock.module('pitsby-app');
inject(($rootScope, $injector) => {
$scope = $rootScope.$new(true);
$window = $injector.get('$window');
$timeout = $injector.get('$timeout');
service = $injector.get('angularComponentBuilder');
});
});
Expand Down Expand Up @@ -54,4 +59,60 @@ describe('Angular Component Builder', () => {
expect(element.triggerHandler('click'));
expect($window.alert).toHaveBeenCalledWith('Rafael');
});

it('should execute initialization hook if controller uses it', () => {
window.alert = jest.fn();
const component = buildComponent(function(){
const $ctrl = this;
$ctrl.$onInit = () => window.alert();
});
compileComponent(component, $scope);
$timeout.flush();
expect(window.alert.mock.calls.length).toEqual(1);
});

it('should not execute initialization hook if controller does not use it', () => {
window.alert = jest.fn();
const component = buildComponent(function(){
const $ctrl = this;
$ctrl.onInit = () => window.alert();
});
compileComponent(component, $scope);
$timeout.flush();
expect(window.alert.mock.calls.length).toEqual(0);
});

it('should not execute initialization automatically hook if controller calls it manually', () => {
window.alert = jest.fn();
const component = buildComponent(function(){
const $ctrl = this;
$ctrl.$onInit = () => window.alert();
$ctrl.$onInit();
});
compileComponent(component, $scope);
expect(window.alert.mock.calls.length).toEqual(1);
});

it('should not execute initialization automatically hook if controller calls it manually inside $timeout', () => {
window.alert = jest.fn();
const component = buildComponent(function($timeout){
const $ctrl = this;
$ctrl.$onInit = () => window.alert();
$timeout($ctrl.$onInit);
}, ['$timeout']);
compileComponent(component, $scope);
$timeout.flush();
expect(window.alert.mock.calls.length).toEqual(1);
});

it('should execute destruction hook if controller uses it', () => {
window.alert = jest.fn();
const component = buildComponent(function(){
const $ctrl = this;
$ctrl.$onDestroy = () => window.alert();
});
compileComponent(component, $scope);
$scope.$destroy();
expect(window.alert.mock.calls.length).toEqual(1);
});
});

0 comments on commit ddfa069

Please sign in to comment.