exclude file from karma coverage report

We have some files that is not so testable (like animation related, or things like polyfills) to be excluded from the karma coverage report. With angular-cli looks like it is straightforward that we can include the below config:

 "test": {
    "codeCoverage": {
      "exclude": [
        "src/polyfills.ts",
        "**/test.ts"
      ]
    },
    "karma": {
      "config": "./karma.conf.js"
    }
  }

However since we are not using cli , we need to tweak ourselves. Found the PR that implements the above feature. Looks like we just need to push the files to be excluded to the webpack config’s module rules for istanbul-instrumenter-loader`. Something like:

module:{
 rule: [
  ...
        {
        enforce: 'post',
        test: /\.(js|ts)$/,
        loader: 'istanbul-instrumenter-loader',
        include: helpers.root('src'),
        exclude: [
          /\.(e2e|spec)\.ts$/,
          /node_modules/,
          // add files needs to be excluded from coverage report below
          `${helpers.root('src')}/services/svg-animations.service.ts`
        ]
      },
  ...
 ]
}

The helpers.root is just a help function get get the proper path.

function root(args) {
  const path = require('path');
  args = Array.prototype.slice.call(arguments, 0);
  const ROOT = path.resolve(__dirname, '..');
  return path.join.apply(path, [ROOT].concat(args));
}

In the coverageReporter of karma.conf.js, we can set a lot of useful things like threshold, dir(normalized with subdir), etc…

Advertisements

angular change detection notes

Was reading some angular change detection related articles trying to understand it. some note.

Angular can detect when component data changes, and then automatically re-render the view to reflect that change.

NgZone

ngZone is an angular verison of zone.js, which patches the browser async calls like user event(click/keyup etc), settimeout/interval, XHR.  It is similar to the AOP we have in Spring that proxies are created by framework to do before/after custom logic around the original method call. The importance of this angular patch these brower-API to trigger the change-detection. Previously in ng1, we have all those special directives like ng-click, $timeout etc to make sure after all the custom logic is done, we all the angularjs $apply() to run the digest cycle to do the dirty check and update the view if necessary. Now in ng2+, all these special stuff are gone because of the usage of Zone which enables us to fire change detection after any of these browser event are done from the main stack. Here is a good article explaining zone in angular.

Basically, The short version is, that somewhere in Angular’s source code, there’s this thing called ApplicationRef, which listens to NgZones onStable event. Whenever this event is fired, it executes a tick() function which essentially performs change detection.

  tick() {
    this.changeDetectorRefs
      .forEach((ref) => ref.detectChanges());
  }

change detection flow

So now we know how CD is triggered, now time for how it is executed.

change detector classes are created on the fly by angular for each component.

From the top of the component(view) tree, we start the CD.

The main logic responsible for running change detection for a view resides in checkAndUpdateView function. Most of its functionality performs operations on child component views. This function is called recursivelyfor each component starting from the host component. It means that a child component becomes parent component on the next call as a recursive tree unfolds.

When this function triggered for a particular view it does the following operations in the specified order:

  1. sets ViewState.firstCheck to true if a view is checked for the first time and to false if it was already checked before
  2. checks and updates input properties on a child component/directive instance
  3. updates child view change detection state (part of change detection strategy implementation)
  4. runs change detection for the embedded views (repeats the steps in the list)
  5. calls OnChanges lifecycle hook on a child component if bindings changed
  6. calls OnInit and ngDoCheck on a child component (OnInit is called only during first check)
  7. updates ContentChildren query list on a child view component instance
  8. calls AfterContentInit and AfterContentChecked lifecycle hooks on child component instance (AfterContentInit is called only during first check)
  9. updates DOM interpolations for the current view if properties on current view component instance changed
  10. runs change detection for a child view (repeats the steps in this list)
  11. updates ViewChildren query list on the current view component instance
  12. calls AfterViewInit and AfterViewChecked lifecycle hooks on child component instance (AfterViewInit is called only during first check)
  13. disables checks for the current view (part of change detection strategy implementation)

Some lifecycle hooks are called before the DOM update (3,4,5) and some after (9). So if you have the following components hierarchy: A -> B -> C, here is the order of hooks calls and bindings updates:

A: AfterContentInit
A: AfterContentChecked
A: Update bindings
    B: AfterContentInit
    B: AfterContentChecked
    B: Update bindings
        C: AfterContentInit
        C: AfterContentChecked
        C: Update bindings
        C: AfterViewInit
        C: AfterViewChecked
    B: AfterViewInit
    B: AfterViewChecked
A: AfterViewInit
A: AfterViewChecked

check on reference

By default, Angular Change Detection works by checking if the value of template expressions have changed. This is done for all components. In other word, Angular does not do deep object comparison to detect changes, it only takes into account properties used by the template.

Performance

Ng2+ gets rid of the ng1 way of doing dirty check which would result in multiple rounds of check. Now we only have 1 round. If we change the fields in the life cycle hooks like ngAfterViewChecked, we will get xxx has changed after it was checked. This error message is only thrown if we are running Angular in development mode. In production mode, the error would not be thrown and the issue would remain undetected.

trigger CD manually

There could be special occasions where we do want to turn off change detection. Imagine a situation where a lot of data arrives from the backend via a websocket. We might want to update a certain part of the UI only once every 5 seconds. To do so, we start by injecting the change detector into the component:

constructor(private ref: ChangeDetectorRef) {
    ref.detach();
    setInterval(() => {
      this.ref.detectChanges();
    }, 5000);
  }

As we can see, we just detach the change detector, which effectively turns off change detection. Then we simply trigger it manually every 5 seconds by calling detectChanges().

 

Some references:

  1. How does Angular Change Detection Really Work ?
  2. ANGULAR CHANGE DETECTION EXPLAINED
  3. Everything you need to know about change detection in Angular

some other good article in angularInDepth:

Exploring Angular DOM manipulation techniques using ViewContainerRef

The mechanics of DOM updates in Angular

difference between detechChanges and markForCheck

Angular Rxjs Error Handling flow

In Angular 2+, http are all RX based. so the error flow is quite different from what we used to have in angular 1.x’s promise based way.

consider the code

this.http.get(‘someurl’)
.map((res: Response) => {
return res.json();
})
.catch((err) => {
console.log(error);
Observable.throw(‘my custom err msg’);
})
.subscribe((res)=>{
console.log(res);
}, (err) => {
console.log(err);
}, ()=> {
console.log(‘complete’);
})

So the basic flow is if anything exception happened, the error handler function in the catch block will be called first. That function should return an Observable since it is a chain. Then the (err) function will be invoked. In the context of an HTTP request in Angular2, a response with a status code different than 2xx is considered as an error.

Note, if we do not use Observable.throw() in catch but return some random result, it would probably result in funky result. In the ​subscribeToResult function, there are multiple type checks. For example, if we return an array, if would be treated valid and be passed to the first handler rather than the error handler. If we return a random object like the error object, we will get TypeError: unknown type returned, error and trigger the 2nd handler(error handler).

Another note is if angular will return some odd error object with status: 0 when invoking some non-exist cross origin endpoints. This is because Whenever you make an api call to a non existing route, the browser sends a preflight request (a) . If the backends error handle strategy is to return an http response with 404 code and the error details in the body, the browser returns a generic error with http status code 0 without the actual server’s payload. The second call is never made because there is no sense in doing it since the preflight went wrong. In the end the error thrown have 0 status without any information about the real cause of the error.

file upload with angularjs and nodejs

angular and node are really hot technologies recently.

The issue i am tackling today is uploading file from angular frontend to nodejs backend. The file i am working with is avatar(image), but it tech should be able to applied to any file.

There are a lot of options on both sides.

Frontend angularJs

angular-file-upload

https://github.com/danialfarid/angular-file-upload#php

This directive is easy to use and not as fancy as others. These are the reason i choose it.

ng-flow

flow js is another option that many ppl are using.

https://github.com/flowjs/ng-flow

I just found it has too many features and a little bit over-complicated. Thing like chunking file transfer is not something i really need here. What’s more the documentation and examples are not quite useful that I have to dig into the source code to understand how some directive attribute work. If you need some of its features like chunking / image preview, use it.

Backend Nodejs

Most of them are based on Busyboy

Formidable

https://github.com/felixge/node-formidable

Formidable has been there for a long time. I choose it because of its easy to use and good documentation. It does not have that much features as the other options but far enough for me since I just need to be able to parse the multi-part request, get the fields and files.

multiparty

https://github.com/andrewrk/node-multiparty/

Multiparty is another middleware to parse http requests wit multipart/form-data. The functionality and API are very similar to Formidable. But with some new features like you can chain multiple callbacks for Parse. It also has support for the AWS s3, which might be very useful to those who uses cloud.

Multer

https://github.com/expressjs/multer

multer is quite new and is actively maintained. I might switch to it later if I have more time. It is also recommended by the Express team as the middleware for replacing the old and ugly express-multipart, which is the integrated in Express 3 but no long bundled in Express 4.

Implementation

html snippet

Use the angular-file-upload directive. Each time a file is added, it triggers the upload(files) method in controller.

<div style="margin-left: 400px; margin-top: 100px;" >
                <label for="uploadWidget"> Upload Image</label>
                <div id="uploadWidget" class="btn btn-default" ng-file-select ng-file-change="upload($files)">Select File</div>
            </div>

Angular controller
The $upload is something we get from the directive and could be injected here. The upload function will upload the file with some metadata to the server’s ‘/api/uploadAvatar’ endpoint. progress() is optional. success() will accept the callback with the response stored in ‘data’.

contactControllers.controller('MemberEditController', ['$scope', '$routeParams', 'MemberResource', '$location', '$window', '$upload',
    function ($scope, $routeParams, MemberResource, $location, $window, $upload) {
        $scope.upload = function (files) {
            if (files && files.length) {
                $upload.upload({url: '/api/uploadAvatar', fields: {username: $scope.member.username}, file: files[0]}).progress(function (event) {
                    var progressPercentage = parseInt(100.0 * event.loaded / event.total);
                    console.log('progress: ' + progressPercentage + '% ' + event.config.file.name);
                }).success(function (data, status, headers, config) {
                    console.log('file ' + config.file.name + 'uploaded. Response: ' + JSON.stringify(data));
                    $scope.member.photo = data.path;
                });
            }
        };

NodeJs
in the server side, we first config the route for the ‘/api/uploadAvatar’ that we have above so that we could handle the request. restImpl is a file that i have for holding my rest implementations. Below is the code in the nodejs bootstrap app.js/server.js

var restImpl = require('./routes/restImpl');

app.post('/api/uploadAvatar', restImpl.uploadAvatar);

in the restImpl js, we do the real work.
The logger below is an instance of winston. Look at my another POST for configuring logging for nodejs.

In the uploadAvatar function, we get a formidable instance which is used to parse the incoming request so that we could get all the files and fields out of it. Then we could do all the processing in the callback. we 1st get the file, then the current path for the temp file and move the file from the temp location to the target path. Finally we return the new file’s path to the client so that we could handle it on the angularjs(the ‘data’ above in the success callback).

var formidable = require('formidable');
var path = require('path');
var fs = require('fs');
var logger = require('winston');
//handle avatar upload
exports.uploadAvatar = function (req, res) {
    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        var file = files.file;
        var username = fields.username;
        var tempPath = file.path;
        var targetPath = path.resolve('./public/photos/' + username + '/' + file.name);
        fs.rename(tempPath, targetPath, function (err) {
            if (err) {
                throw err
            }
            logger.debug(file.name + " upload complete for user: " + username);
            return res.json({path: 'photos/' + username + '/' + file.name})
        })
    });
};

How angular js works

1 bootstrap flow:

http://java.dzone.com/articles/how-angularjs-works-%E2%80%93

  • angularInit method which checks for ng-app module
  • bootstrap method which is invoked once an ng-app module is found. Following are key invocations from within bootstrap method:
    • createInjector method which returns dependency injector. On dependency injector instance, invoke method is called.
      For example if myModule has ‘greeter’ dependency. we get it like this

      var injector = angular.injector(['myModule', 'ng']);
      var greeter = injector.get('greeter');

      the greeter is usually provided by some factory/service/provider

      myModule.factory('greeter', function($window) {
        return {
          greet: function(text) {
            $window.alert(text);
          }
        };
      });
    • compile method which collects directives
    • Composite linking method which is returned from compile method. Scope object is passed to this composite linking method
    • $apply method invoked on scope object finally does the magic and renders the view.

Another article on how module bootstraps

2 $watch How the $apply Runs a $digest

http://angular-tips.com/blog/2013/08/watch-how-the-apply-runs-a-digest/

$watch will be created for the needed dom element. It takes a watchFn(which is usually the scope variable name) to return its own latest value and a listnerFn for the change callback.

$digest will go into the angular context(watched elements) and run the digest loop which compares the changes(new value are return by all watches) until all the elements are up to date(up to 10 loops if infinite loop). We do not usually call digest directly but uses apply more unless there are some heavy filters used(look at the below difference link).

$apply will call digest from the rootscope and go thru all its children scopes. Most of the time(angular’s own directives) this is called automatically. When you use some third part library(jQuery) or update var of scope in your own directive(meaning the event is from DOM directly), you will need to call this explicitly to let the event go thru the angular context.The most important thing to keep in mind is whether or not Angular can detect your changes. If it cannot, then you must call $apply()manually. The better practise is to pass the needed changed as a function to the apply like:

scope.$apply(function(){scope.a = a; $parse(attrs.b).assign(scope, ‘b’);})

main different between digest and apply

3 detail on watch/digest

http://teropa.info/blog/2013/11/03/make-your-own-angular-part-1-scopes-and-digest.html

4 Injection(service/facotry/inject)

https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection

The DI is actually done rely on the fact that javascript could turn a function to String by calling .toString(). For example


var f = function(a, b, c){};

console.log(f); console.log(f.tostring());

This way, angularJs could get the arguments in String format and do analysis then corresponding injection.

Note the best practice to DI is to specify the name list first then put the objects into function so that even the js is minified, it would still work. Angular doc about this

Like

admin.controller(‘BillingSchedulerController’, [‘$scope’, ‘$filter’, ‘JobControlResource’, ‘$timeout’, function ($scope, $filter, JobControlResource, $timeout)
{…}

the reason we can do this is, when angular saw the second param of controller is array instead of a function, it starts to parse the first n-1 elements of the array and inject into the n element which is a function. and then call the elementN() with corresponding dependencies. this is a good video explaining this point. 

A side note, angular.$injector().annotate(yourFunction) will get all the argument of ‘yourFunction’ as an array.

My other post briefly describes the difference between service/factory/provider. Basically they are all for DI so that the objects($scope, $filter, JobControlResource, $timeout) above could be injected.

5 directives

a detail video on how directive works from the author of angular

Basically compile function compiles the html template. link function applies the scope to the template.

New scope in directive

The scope:true is useful so that whatever we do in the directive does not pollute the outside world. it will be an isolated scope which is not inheriting!

1. We also could import the outside value by scope:{email : @}. use @ to use the {{email}} style. this way it is passing an email string in.

2. use scope:{email : ‘=’} to use a expression passed in. this way is passing a reference of an object in.

Scope properties come in three different flavours

  • Two-way binding: Indicates that changes made on either the parent or child scope are reflected in the other. It’s denoted by an equals sign (=) when building the scope.
    Use ‘attribute=parentField’ to pass the parentField object to the directive to achieve two way binding. see this example
  • One-way binding: Data flows only from child to parent via a function. Denoted by an ampersand (&).
    Use ‘attribute=parentFunction(someVal)’ to pass the parentFunction to the child so that it could be called there. in the directive, it could be called by scope.parentFunction({someVal:’someString’}). Here someString could also be a field in the scope so that it could be dynamic. see this example
  • Text binding. Just a string value that contains no binding information. Denoted by an at symbol (@).
    To pass value from the parent, use ‘attribute={{parentField}}’ so the parentField could be a dynamic value. see this example
  • review

Transclude

the  transclude: true will pull the content of the ng-transclude out of the directive scope so that it could still received value from outside world. The inside content scope is a sibling scope with the directive scope. They are both child of the upper scope. The difference is the directive scope is not inheriting but the inside content scope inherits values from the parent.(this is explained from the above youtube video starts @45:00)

Angular’s $scope event system $emit, $broadcast and $on

Angular’s $emit, $broadcast and $on fall under the common “publish/subscribe” design pattern, or can do, in which you’d publish an event and subscribe/unsubscribe to it somewhere else. The Angular event system is brilliant, it makes things flawless and easy to do (as you’d expect!) but the concept behind it isn’t so simple to master and you can often be left wondering why things don’t work as you thought they might.

For those who are new to Angular and haven’t used or seen $emit, $broadcast or $on, let’s clarify what they do before we look at $scope and $rootScope event and scope relationships and how to utilise the event system correctly – as well as understand what’s really going on.

$scope.$emit up, $scope.$broadcast down

Using $scope.$emit will fire an event up the $scope. Using $scope.$broadcast will fire an event downthe $scope. Using $scope.$on is how we listen for these events. A quick example:

 

// firing an event upwards
$scope.$emit('myCustomEvent', 'Data to send');

// firing an event downwards
$scope.$broadcast('myCustomEvent', {
  someProp: 'Sending you an Object!' // send whatever you want
});

// listen for the event in the relevant $scope
$scope.$on('myCustomEvent', function (event, data) {
  console.log(data); // 'Data to send'
});

module.service vs module.factory angular

There is a great google group post about this from Pawel Kozlowski:

https://groups.google.com/forum/#!msg/angular/hVrkvaHGOfc/idEaEctreMYJ

Quoted from Powel:

in fact $provide.provider, $provide.factory and $provide.service are more or less the same thing in the sense that all of them are blueprints / instructions for creating object instances (those instances are then ready to be injected into collaborators).

$provide.provider is the most spohisticated method of registering blueprints, it allows you to have a complex creation function and configuration options.

$provide.factory is a simplified version of $provide.provider when you don’t need to support configuration options but still want to have a more sophisticated creation logic.

$provide.service is for cases where the whole creation logic boils down to invoking a constructor function.

So, depending on the complexity of your construction logic you would choose one of $provide.provider, $provide.factory and $provide.service but in the end what you are going to get is a new instance.

Here is the accompanying fiddle to demonstrate (from the thread):http://jsfiddle.net/pkozlowski_opensource/PxdSP/14/

And the code:

The $get function of provider is something will be called. The setName() is sort of API provided so that we could config provider thru the app.config(function(helloWorldProvider){helloWorldProvider.setName(‘something’)}) method.

var myApp = angular.module('myApp', []);

//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
    this.sayHello = function() {
        return "Hello, World!"
    };
});

//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
    return {
        sayHello: function() {
            return "Hello, World!"
        }
    };
});

//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {

    this.name = 'Default';

    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!"
            }
        }
    };

    this.setName = function(name) {
        this.name = name;
    };
});

To ease choosing between the 4 different ways I will shortly recap all of them:

  • Use either “value(name, value)” or “constant(name, value)” to register an existing value:
    • you typically would use “value” to register a service object or a function
    • whereas “constant” should only be used for configuration data
  • factory(name, providerFunction)“: registers a factory function responsible for creating the “singleton” service instance.
    Just like “value(name, value)” a factory function could return anything from primitive type, function or object instance.
  • service(name, constructor)“: registers the constructor function which will be constructed using a “new” keyword.
  • provider(name, providerType)“: the most advanced way to register a service.
    Most often there is no need for your service to be configurable through a “…Provider” service, unless you are writing a reusable JavaScript library containing AngularJS services.

From Another good article about singleton