Tuesday, April 21, 2015

How to test private function in Angularjs

These days, I am working on unit tests of an AngularJS application. But it drives me crazy when I encountered private functions.
I  read the two articles by Philip Walton: 
My idea was inspired from these two articles.
It seems like whether and how to test the private function in Javascript is still a controversial topic.
For me, I choose to do it. There are two reasons:
First of all, some of the code are not written by me. I'd like to play around with my test code rather than changing others' work. And we haven't decided whether it's OK to make those code public.
Second of all, there are many private functions, I don't think it's good to skip all of them.

A brief instruction of the app I am working on

The app is built with gulp. We set the task

gulp test

for unit test.

In the app code, we have the following structure :
angular.module('MainModule').controller('MainCtrl',MainController);

mainController.$injct = ['dep1','dep2']

function MainController(dep1,dep2){
  var vm = this;
  var name = '';
  var isMember = false;

  vm.somePubFuncs = function(){
    // call those private functions from public function
  }

  function updateMemberBenefitTable(){
     // dosomething here
  }

  function loadMemberBenefitTable(){
    // dosomething here
  }
}

I will test the updateMemberBenefitTable() and loadMemberBenefitTalbe().

My basic idea of testing the private functions

Adding some public interfaces for the private function at the beginning of test, and strip them at the end of the test.
I use gulp-insert-lines for adding and gulp-strip-code for stripping.

I added the comments pair
/*test-code-insert-here*/  /*end-test-code-insert-here*/
i.e.

angular.module('MainModule').controller('MainCtrl',MainController);

mainController.$injct = ['dep1','dep2']

function MainController(dep1,dep2){
  var vm = this;
  var name = '';
  var isMember = false;

  vm.somePubFuncs = function(){
    // call those private functions from public function
  }

  /*test-code-insert-here*/
  /*end-test-code-insert-here*/

  function updateMember--BenefitTable(){
     // dosomething here
  }

  function loadMemberBenefitTable(){
    // dosomething here
  }
}

The interfaces will be inserted into the pair of comments.

The gulp task for unit test is:
var insertLines = require('gulp-insert-lines');
var stripCode = require('gulp-strip-code');

gulp.task('test',function(){

  // This section is to add the interfaces of the private function into the source file
  var str = '/*--test-only*/'+'\n'+
            'vm._updateMemberBenefitTable = updateMemberBenefitTable;'+'\n'+
            'vm._loadMemberBenefitTable= loadMemberBenefitTable;'+'\n'+
            '/*--end-test-only*/';
  gulp.src('path/of/MainCtrl')
    .pipe(insertLines({
      'after':/\/\*test-code-insert-here\*\/$/,
      'lineAfter':str
    }))
    .pipe(gulp.dest('dest'));
  //END This section is to add the interfaces of the private function into the source file
  
  return gulp.src('testfile.js')
    .pipe($.karma({
      configFile: 'karma.conf.js',
      action: 'run'  
    }))
    .on('end',function(){
      // This section is to strip off the interfaces of the private function 
      //at the end of the unit test
      gulp.src('path/of.MainCtrl')
        .pipe(stripCode({
          start_comment:'--test-only',
          end_comment:'--end-test-only'
        }))
        .pipe(gulp.dest('dest')); 
      //END This section is to strip off the interfaces of the private function 
      //at the end of the unit test
}) .on('error',function(err){ throw err; })


Please keep in mind that the /*--test-only*/  /*--end-test-only*/ comments pair is very important. Because later on, when gulp-strip-code is stripping the interfaces, the comments pair will be stripped as well. If you use /*test-code-insert-here*/ /*end-test-code-insert-here*/ pair for stripping, you will end up with being not able to find them at the next run of gulp test.

Tuesday, March 31, 2015

Useful Git Command

1. Squash
Say your bug fix branch is called bugfix and you want to merge it into master:
git checkout master
git merge --squash bugfix
git commit

2. Delete unexpected stash pop
git clean -f

3. Delete remote branch (the local one has been deleted)
git push origin --delete 

4. Reset commit
git reset --hard <HEAD>
git push -f

5. How to show or change Git username
http://alvinalexander.com/git/git-show-change-username-email-address

6. Generating SSH keys
https://help.github.com/articles/generating-ssh-keys/

7. Check who is the latest person updated the branch
git for-each-ref --format='%(refname) - %(authorname) (%(committerdate))' 'refs/remotes'

8. Prune the local list of remote branches
git remote prune origin

Sunday, March 29, 2015

Unexpected request GET error in Angular JS

I got the
Error: Unexpected request: GET components/template.html
No more request expected
at $httpBackend ... 

For me, the reason for this problem is:
The relative path of template.html in karma.conf.js preprocessors, beforeEach(module) and myDirective.js are different, i.e:
in the karma.conf.js, it was:
preprocessors: {
    'src/components/template.html': ['ng-html2js']
},

in the beforeEach(module), it was:

beforeEach(module('src/components/template.html'))

and in the myDirective,js, it was:

function myDirective(){
    return{
        restrict: 'EA',
        templateUrl: 'src/components/template.html'
    };
}

To solve the problem, I change all the relative path to
'src/components/template.html'

Wednesday, March 25, 2015

Good articles about AngularJS


Basic usage
1. AngularJS code style guide
- Jhon Papa: 10 AngularJS patterns
https://www.youtube.com/watch?v=UlvCbnKAH3g
https://github.com/johnpapa/ng-demos
- Todd Motto
https://github.com/toddmotto/angularjs-styleguide
- Angular Best Practices: Directory Structure
https://scotch.io/tutorials/angularjs-best-practices-directory-structure
- Scalable code organization in AngularJS
https://medium.com/opinionated-angularjs/scalable-code-organization-in-angularjs-9f01b594bf06
- Code Organization in large AngularJS and JavaScript Applications
http://cliffmeyers.com/blog/2013/4/21/code-organization-angularjs-javascript
2. Understanding $emit, $broadcast and $on in AngularJS
http://www.dotnet-tricks.com/Tutorial/angularjs/HM0L291214-Understanding-$emit,-$broadcast-and-$on-in-AngularJS.html
3. Recipes with Angular.js
http://fdietz.github.io/recipes-with-angular-js//controllers/testing-controllers.html
4. Angularjs directive
http://www.chroder.com/2014/02/01/using-ngmodelcontroller-with-custom-directives/
5. Controller in directive
http://www.bennadel.com/blog/2446-using-controllers-in-directives-in-angularjs.htm
6. Derictive Isolate Scope
http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope
7. Understanding Dependency Injection
https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection
8. Directive's lifecycle in AngularJS
http://filimanjaro.com/2014/angular-directive-lifecycle-vs-link-compile-controller/
9. Developer Guide Recipe: Provider, Factory, Service, Constant
https://docs.angularjs.org/guide/providers
http://www.learn-angular.org/#!/lessons/the-provider-recipe


AngularJS Unit Test:
1. Introduction to Unit Testing in AngularJS App
http://www.smashingmagazine.com/2014/10/07/introduction-to-unit-testing-in-angularjs/
2. Mocking Dependencies in AngularJS Tests
http://www.sitepoint.com/mocking-dependencies-angularjs-tests/
3. spyOn and createSpy
http://www.htmlgoodies.com/html5/javascript/spy-on-javascript-methods-using-the-jasmine-testing-framework.html#fbid=e4VtfL1YKyJ
4. Unit Testing w/ AngularJS
http://moduscreate.com/unit-testing-w-angularjs/
5. How to Unit Test Controllers
http://nathanleclaire.com/blog/2013/12/13/how-to-unit-test-controllers-in-angularjs-without-setting-your-hair-on-fire/
6. AngularJS Unit Testing Best Practices
http://blog.codeship.com/angularjs-tdd/
7. Introduction to Unit Test: Directives
http://angular-tips.com/blog/2014/06/introduction-to-unit-test-directives/
8. Video: Testing Directives
https://www.youtube.com/watch?v=rB5b67Cg6bc
9. Video: Unit Testing a Directive  ---- Egghead
https://www.youtube.com/watch?v=NV5Zkthh7nw
10. Testing AngularJS directive: handling external templates
http://www.portlandwebworks.com/blog/testing-angularjs-directives-handling-external-templates
11. Unit Testing AngularJS Directives With External Templates
http://www.bluesphereinc.com/blog/unit-testing-angularjs-directives
12. Testing AngularJS directives with External Templates --- using templatecache
http://www.portlandwebworks.com/blog/testing-angularjs-directives-handling-external-templates
13. Testing AngularJS directive templates with Jasmine and Karma
http://www.portlandwebworks.com/blog/testing-angularjs-directives-handling-external-templates
14. Testing directive that appends template to element ---- stackoverflow
http://stackoverflow.com/questions/28363679/testing-directive-that-appends-template-to-element
15. When template path in templateUrl of directive.js, module(<template path>) of directive.spec.js and preprocessor of karma.conf.js are different:
https://github.com/vojtajina/ng-directive-testing/issues/3#issuecomment-87720458
http://tylerhenkel.com/how-to-test-directives-that-use-templateurl/
16. Testing AngularJS Directive with Jasmine ---- From simple to complex
http://busypeoples.github.io/post/testing-angularjs-directives/
http://busypeoples.github.io/post/testing-angularjs-hierarchical-directives/
17. Video and sample code: What, How, When to test ---- e2e, unit test, TFD
https://www.youtube.com/watch?v=9-kumGACGYk
https://github.com/auser/testing-example
18. Angular Testing Cheat Sheet
https://github.com/sydcanem/angularjs-testing-cheat-sheet
19. Change constant value that gets passed to Config for Unit Test
http://stackoverflow.com/questions/25295445/angularjs-change-constant-value-that-gets-passed-to-config-for-unit-test
20. Unit Test custom provider
http://stackoverflow.com/questions/14771810/how-to-test-angularjs-custom-provider
https://github.com/angular/angular.js/issues/2274
21. Example of testing isolate scope
http://plnkr.co/edit/QXprEUof2Ps0Vivg4L34?p=preview
http://stackoverflow.com/questions/27697747/angular-testing-directive-with-templateurl-isolate-scope
22. Introduction to Unit Test: Services
http://angular-tips.com/blog/2014/06/introduction-to-unit-test-services/
23. Writing Unit Tests for an AngularJS Service
https://busypeoples.github.io/post/writing-unit-tests-for-service-in-angular-js/
24. Supplying Mocks for Services via $provide
http://tech.pro/tutorial/1517/supplying-mocks-for-services-via-provide
25. AngularJS Unit Testing Best Practices
http://blog.codeship.com/angularjs-tdd/
26. Understanding Dependency Injection

Friday, March 20, 2015

close in ModalService --- AngularJS

The close of Modal is in ModalService.

beforeEach(inject(function(_ModalService_){
    close = ModalService.close;
}))

Monday, March 16, 2015

Notes of SCOPE & CLOSURE JS

1. If an RHS look-up fails to ever find a variable, anywhere in the nested scopes, this results in a ReferenceError being thrown by the engine. I's important to note that the error is of the type ReferenceError.
    If the engine is performing an LHS look-up and it arrives at the top floor (global scope) without finding it, if the program is not running in "strict mode", then the global scope will create a new variable of that name in the global scope, and hand it back to Engine.

2. Cheating Lexical
    1) eval
    2) with: Even though a with block treats an object like a lexical scope, a normal var declaration inside that with block will not be scoped to that with block, but instead the containing function scope.