6/15/15

Interesting thing about $watch

I guess everybody knows how to make angular to respond on the changes made to scope variables- to add some callback to "$watch" , something like this:

scope.$watch('name', function(newValue, oldValue) {
  scope.counter = scope.counter + 1;
});

But the cool thing that $watch can listen and respond to changes of functions which return something too. For example:

 $scope.tabs=[{active:true, name:'first'},{active:false, name:'second'},{active:false, name:'third'}}];
 $scope.$watch(function(){ return $scope.tabs.filter(function(t){ return t.active; })[0]; },function(tab){
   $scope.$broadcast('tab-selected',{name:tab.name})
 },true)

6/8/15

Building & testing user-menu directive part 2

testing

first test

after we have build user menu directive in previous post we may want to test it...
It is a good practice to test things you did. (Actually better practice is to test things before you did them, but lets leave TDD and focus on only T...) So lets start doing some testing:
1. lets test firstly that our directive loading a template correctly:


describe('Testing user menu directive', function() {
  var $scope = null;
  var $compile;

  //you need to indicate your module in a test
  beforeEach(module('plunker'));
  beforeEach(inject(function($templateCache, _$compile_) {
    $compile = _$compile_;
    var directiveTemplate = null;
    var req = new XMLHttpRequest();
    req.onload = function() {
        directiveTemplate = this.responseText;
    };
 
    // Using `false` as the third parameter to open() makes the operation synchronous.
    req.open("get", "userMenuTpl.html", false);
    req.send();
    $templateCache.put("userMenuTpl.html", directiveTemplate);
  }));
  
  beforeEach(inject(function($rootScope) {
    $scope = $rootScope.$new();

  }));

  it('should display login menu', function() {
    element = $compile('<user-menu></user-menu>')($scope);
    $scope.$digest()              
    expect($(element).find('a:eq(0)').text()).toContain('Sign in');
  });  
});

So far so good...

Slight Modifications

Now to more complicate things - lets add "signout" functionality which will cause our directive to change its view dynamically:


var app = angular.module('plunker', [])
.directive('userMenu', function ($templateCache) {
    return {
        restrict: 'E', 
        templateUrl:'userMenuTpl.html',
        controller: function ($scope, userSvc) {
            if (userSvc.isAuthenticated()) {
                $scope.profile = userSvc.getProfile(); 
            }
            $scope.getprofile = function(){
              return  userSvc.getProfile()
            }
            $scope.signout = function(){
              userSvc.logout();
            }
        }
    }
})
.factory('userSvc', function () {
      
    var _isAuthenticated = false, _profile= null;
    return {
      isAuthenticated: function() {
        return _isAuthenticated;
      },
      getProfile: function() {
        return _profile
      },
      login: function(){
        _isAuthenticated = true;
        _profile = {username:'Shlomo'}
      },
      logout:function(){
        _profile = _isAuthenticated = false;
      }
    }
})

lets modify the template also


<ul class="nav navbar-nav navbar-right" ng-if="getprofile()">
  <li>
    <a href="/profile"><i class="glyphicon glyphicon-user">
      </i> {{profile.username}}
    </a>
  </li>  
  <li style="border-left:1px solid #fff">
     <a href ng-click="signout()">Sign out</a>  
  </li>
</ul>

<ul class="nav navbar-nav navbar-right" ng-if="!getprofile()">
  <li>
    <a href  ng-click="open()">Sign in</a>  
  </li>  
  <li>
    <a style="border-left:1px solid #fff" href="/link-to-login">Sign Up</a>  
  </li>
</ul>

more tests

So now our directive able to change it view after user clicking on some link. lets test those behaviors:


  //...
  it('when logged in should show "sign out" link and user name', function() {
    userSvc.login();
    element = $compile('<user-menu></user-menu>')($scope);
    $scope.$digest()              
    expect($(element).find('a:eq(1)').text()).toContain('Sign out');
    expect($(element).find('a:eq(0)').text()).toContain('Shlomo');
  });
  
  it('after loggin out- should show "Sign in" link again', function() {
    userSvc.login();
    element = $compile('<user-menu></user-menu>')($scope);
    $scope.$digest();              
    expect($(element).find('a:eq(0)').text()).toContain('Shlomo');
    expect($(element).find('a:eq(1)').text()).toBe('Sign out');
    element.find('a').triggerHandler('click');
    expect($(element).find('a:eq(0)').text()).toBe('Sign in');
  }); 
 //...

View it on plunker

Hope you have good time reading

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...