What are you looking for?

Two Fucking Developers

Testing Angular 2 with Karma and Jasmine

Update: Removed @Injectable from Services and Pipes. Thanks Pascal!

Happy new year ladies and gentlemen!

Angular 2 Beta is out and it’s time to start creating your own library, a side project or update your current product to the newest version.

To follow this tutorial is needed a small knowledge of NPM, TypeScript, Angular 2, Karma and Jasmine.

In this tutorial we will see the next:

  • Installing dependencies
  • Preparing your package.json
  • Setting up TypeScript
  • Setting up Karma
  • Creating our application
  • Testing Angular 2 Components with Jasmine
  • Testing Angular 2 Services with Jasmine
  • Testing Angular 2 Pipes with Jasmine
  • Creating a coverage report with Istanbul

Skip the tutorial and show me the code!

Installing dependencies

First things first, we need to create a package.json so we will initialize our project.

Create a folder and cd into it.

Initialize your package.json with some default values, we will update our package file later.

Install the Angular 2 library and RxJS as client dependencies:

Now we can install all development dependencies. Here’s a list of dependencies and their use in this example:

  • http-server: To run a simple server and see our coverage reports.
  • jasmine-core: Our testing framework.
  • karma: Our test runner.
  • karma-chrome-launcher: To launch Google Chrome from Karma.
  • karma-coverage: To create Coverage reports.
  • karma-jasmine: Karma adapter for Jasmine framework.
  • remap-istanbul: To map our coverage in JS files to TypeScript files.
  • systemjs: Module loader.
  • typescript: TypeScript compiler.

Install all dependencies as development:

Now that we have all our dependencies installed let’s going to prepare our NPM commands.

Preparing your package.json

For our build system we’re going to use NPM only, no Grunt, Gulp or Webpack here. Of course you can modify as you want your build system, but for simplicity we just used NPM commands (which a lot of times is enough).

Modify your “scripts” property in your package.json as follows:

Here’s a small explanation of each command:

  • build: Removes the compiled files by TypeScript.
  • pretest: Runs the build “command” before the “test” command.
  • test: Execute tests with Karma.
  • posttest: Updates the coverage report remapping the result to TypeScript files.
  • coverage: Shows the coverage report.

Setting up TypeScript

To configure TypeScript properly we need to create first a “/src” folder and enter into it:

Now create a tsconfig.json file with this content:

The important thing here is the “outDir” which is telling us where the compiled files will be deployed. That’s the folder that we remove every time we execute the “build” NPM command.

Setting up Karma

Now it’s time to set up Karma. Basically it’s pretty similar to Angular 1.X configuration but we need to add also a karma-test-shim to use Karma with SystemJS.

But one thing at a time. First we will create a karma.conf.js in our root directory:

Important and weird things here are:

  • files: array which contains all the files needed to start our app with Karma.
  • proxies: a proxied path to execute the Angular app in the same path as when we execute locally.
  • preprocessors: regular expression to get to which files we should create the coverage report. Basically all the TypeScript files that doesn’t have a spec inside.

To the rest we’ve added a few comments so I think that everything is pretty clear.

Now we need to create a karma-test-shim. For this use case I’ve get borrowed one from Julie Ralph repo ng2-test-seed and modified to my needs.

To make it work with your environment you just need to modify all the functions to get exactly what you need. In my case I needed to modify a few regular expressions and some paths and we’re done!

We can just start writing tests!

Creating our application

Now comes the fun!

To make a test first we need a Class to test, so first we will write a simple list that gets a few dog breeds from a service. Those dogs are going to be capitalized with a custom pipe, so we can test the main three types of objects in Angular 2: Components, Services and Pipes.

Let’s start with our service. To make it as easier as possible we’re not using an online service and we will have just a hardcoded array with some dogs.

Here is important to notice that that we have a coverage branch in our getDogs() method. We will need to be sure to cover all branches when we test our code.

Now our Pipe, which will get a string and will capitalize all words:

In our Pipe we override the “transform” method provided by PipeTransform interface.

And finally our component which will have a list using our Service and our Pipe.

Now that we have our Classes finished we can start by testing them.

Testing Angular 2 Components with Jasmine

If you’re used to testing in Angular 1.X you will see that it looks very similar but even easier and clearer.

As a recommendation we prefer to have our tests with our code to be faster to find and keep all the code together.

If you remember our Karma Shim we need that all tests finish with .spec.ts, this is how we made to tell Karma which files should be executed as tests.

As you can see the tests are pretty easy to do. Just create a new instance of your Component dependencies, then create a new Component instance with the dependencies required and then you can just start executing functions and expecting results.

This is much clearer than Angular 1.X tests!

Testing Angular 2 Services with Jasmine

Services are pretty much the same as Components. In this case we need to test a branch, so we made two tests to see if everything works as expected.

Testing Angular 2 Pipes with Jasmine

And yes, Pipes are easy as pie too. In fact, if you take a look to your other tests and compare each other it is indeed very hard to figure out which one is a Component, a Service or a Pipe. That means that tests haves a great separation of concerns.

Let’s see our Pipe test.

Now we can try our NPM commands!

Creating a coverage report with Istanbul

We can start by creating our build and let’s see our terminal output.

It should create a “dist” folder in your root.

Now let’s see if our tests are working.

Yeah! It works! Everything looks great and it seems that a Coverage report has been created. Let’s take a look to it.

The Coverage report looks very cool too and we have a 100% coverage!

Istanbuil Coverage Report

This is great. Now that we’re sure that our application is passing all tests we can run it to be sure that is true.

Conclusion

Testing Angular 2 is for easier than testing Angular 1.X apps. The only backward is to have a more complex configuration on Karma but that’s a worthwhile price to have a better testing framework.

The configuration to remap the .js.map files to TypeScript files is pretty easy so we can still have great reports with Istanbul.

If you want to take a look to the code or fork it to improve it you can do it. Pull requests are welcome!!

https://github.com/Elecash/angular2-testing

Thanks for reading!

Angular 2 singleton service

Posted on April 4, 2015

WARNING! This post is very old and experimental, Angular 2 has been changed a lot since March 2015 and nothing here is a valid resource anymore!

Angular 2 is out and everybody is creating some tutorials about how to start playing with it and I must say this… it’s terribly funny!

In fact, ES6 and Angular 2 takes me back to 2005 when I read Essential ActionScript 2.0 book by Colin Moock. I still have that book in my home and some of the patterns that you can learn in that book are still valid for ES6.

Creating your Angular 2 Application

First, I want to recommend you to read the amazing tutorial created by the Thoughtram team about Developing a zippy component in Angular 2. Basically I started with the same repo from Pawel Kozlowski (thanks Pawel, awesome resource).

I’ve read a few other tutorials about Angular 2 and ES6 and at the end I made a custom implementation that you can fork in this Github repo: 2fdevs/angular2-singleton on Github.

First check the same repo, we have a good start with this code:

Since I want to create an application, I’ve started by creating an Application class:

And in the application template we will put TWO “hello” components:

Now we need to change our bootstrap in the index.html file. This is our new body tag and bootstrap logic:

And that’s all, we have now an application that is using our “hello” component inside of it.

Angular 2 Singleton Service

One common pattern in OOP is the Singleton Pattern which allows us to have one instance and only one of certain class in our entire application.

Let’s going to write our first Singleton class:

There are several ways to create a Singleton, this is one of them. I want to explain step by step what does this service:

The first thing is pretty interesting, if you try to call “var inst = new SingletonService();” it will throw an error! Wow, that’s pretty extreme, but this is the intended behaviour. We don’t want to create in that way the service, we want to have only one instance for that we will have a way to retrieve that instance:

This is our way to retrieve the Singleton instance. Since it’s an static function (and static variables) you will retrieve the instance with SingletonService.getInstance() and we will take care that the instance is only created if SingletonService.instance never was created before.

Now that you have your static functions and properties created we can work with our service as any other service. We will add a couple of methods to set and get a message.

The rest of methods are not static and you will access them like this:

From now, you can call setMessage() once and on any point of your application if you make inst.getMessage() you will get always the same message because there’s only one instance in the entire application.

This is the complete SingletonService class:

Putting it all together

Now, we can update our message in the Application class and show the same message in all the “hello” components.

This is how we will set the common message:

And now, we can retrieve the same message everywhere:

Nice!

This is so clean. We can have a Singleton service and we need to just import the class and call the getInstance() method to retrieve the same instance everywhere.

The dangers of using Singletons

Be carefoul when using Singletons. People tend to use them for everything and for some cases Singletons could be more a problem than a solution so every time you want to use a Singleton ask to yourself if only need one (and only one) of this class.

In case that you need more instances of a Singleton in the future you will face how to transform a Singleton into a Multiton and I can tell you that it’s not a funny process.

Thanks for reading!

TypeScript and Angular 2

Posted on March 14, 2015

Last week, at ng-conf we get some interesting news about the state of Angular 2 and the relationship between this nice framework with the cool superset of JavaScript: TypeScript. We heard some announces talking about TypeScript and Angular 2 some time ago, but there were more elements in the equation, like AtScript.

For not boring you I’ll put some links to get more info about this announce, but we can resume it saying that Angular 2 is built on TypeScript, and AtScript is now TypeScript.

A really good work from Google and Microsoft teams, collaborating together.

So if you want to be updated with more info from Angular and TypeScript teams, you can read the following posts:

Also you can check the demo that was showed by Jonathan Turner at ng-conf, or watch the video showcasing this demo.

There are some articles on other websites talking about this announce, for example at techcrunch, but if you want to learn it, you need to visit angular.io website, the official one form Angular 2.

As you know (if you visit to our website from time to time), our main two topics at this blog are AngularJS and TypeScript… so you can imagine how amazing is for us the news that went live last week. At this point, we can say that we bet right for them… good times for this two fucking developers 😉

AngularJS virtual list directive tutorial

I’ve been working at a customer for almost a year and we’re creating a webapp that needs to display huge amounts of data, usually in forms. One of the requirements is to have custom lists and selects that can display thousands of elements with icons, checkboxes and other components inside the options.

In this tutorial we’re showing how to create an AngularJS virtual list that can support up to 1MM (yup, one million) records. Technically, it could be even more but if you want to show more than 1MM records in a list maybe you need to do something different.

Virtualization

It is called virtualization when in a list you only create the records that you’re going to display in certain area. This is obviously done in all high performance components created ever to not create thousands of cells that could destroy the application performance.

To create a virtualized list en AngularJS is extremely easy, and you can have something pretty useful in less than 100 lines of code.

So let’s start!

Continue Reading

AngularJS Best Practices #003: $routeProvider

Posted on July 28, 2014

This series of AngularJS best practices articles are defined by three rules: it’s easier to debug, it’s easier to test and it’s easier to maintain. So maybe this could be worst for other things (like performance).

$routeProvider

AngularJS $routeProvider is probably one of the most popular and widely used providers. With $routeProvider we manage all our application routes and is responsible for updating our views and pairing these views with its controllers.

If you have been worked with AngularJS for a while is probably that you are familiar with $routeProvider and this could be an approach of how you’re using it currently:

This is a classic example of AngularJS $routeProvider usage. You have your view in a separated html and your controller takes your data from a resolve function that is loading an external json. Everything looks fine, but as you will see, this could be improved to have something better to scale, maintain and test.

Using $routeProvider

The biggest mistake in the previous approach is that our data source is completely attached to our $routeProvider and thats wrong because we can’t reuse it. Also there’s another problem, it is going to be harder to test and also we don’t have a centralized service to scale our data provider. So our first improvement would be to create a service to load our data.

That’s much better! Now we have an injectable service called “httpDataLoader” that we can use along our application and also we can scale it. If you’re working with a REST service you can even use Restangular, an awesome module created by Martin Gontovnikas. This is how your service should looks like with Restangular:

Obviously to have a provider for our data will allow us to test it better by mocking our service, so as we’ve seen this is a highly recommendable technique and your data should always come from a service.

Now that we have been solved our biggest problem let’s see what else we can do.

Simplifying scope with “Controller as”

Working with scopes in JavaScript sucks. I suffered scopes back in the old times with Flash 5/ActionScript 1.0 and I can’t believe that today we’re still seeing things like “this._self”.

Anyway, AngularJS manages quite good scopes for us, however there is still a common problem with “scopes” and “this”. Let’s see our controller again:

Ok, now we’ve been added a new variable called “defaultMaxItems” that is overriden by our data provider. However we have a problem here because we’ve been defined “defaultMaxItems” as a “private” variable and now it is not available in scope and it is not testable or accesible for our html template. So let’s fix this with a common workaround:

Ok, that’s better. Now we have all defined in “this” and it is accesible through scope to test and bind with the template. Basically, the AngularJS team arrived to this conclusion and since AngularJS 1.1.5 provide a way to do this automatically with “Controller as”. If you want to know more you can read this post where Alex Ford explains perfectly how “Controller as” works.

The first thing that you will notice is that with “Controller as” you no longer need to inject $scope, “Controller as” will do that for you and will create also a variable called “controller” inside “$scope” that will be “this” ($scope.controller = this;). This is so much clean and easy to use than injecting $scope and matching to this, etc.

With this example I’ve created a Plunk just in case you want to play with the code.

Happy fuckingn coding!

Solving spyOn problems in Jasmine

Posted on July 21, 2014

If you’re developing a large application I think that testing is a must. In the last months I’ve catched a lot of bugs in my code thanks to the unit and E2E testing I’ve made with Karma and Protractor. Obviously the drawback is the maintanability of your testing code, but at the end of the day you really appreciate this parachute.

Because I’m developing with Karma I usually test my code in three main browsers, Chrome, Firefox and PhantomJS. Yes, I’m not testing in Internet Explorer, luckily is not a requirement in this customer because we have control of the environment, so yes, I’m a lucky bastard.

The awesomeness of spyOn

If you’ve been made a few tests with Karma and AngularJS you already know how awesome is spyOn which basically allows you to watch when a function have been called and what parameters have been passed.

Let’s see an example:

In this test I’m watching if storage.set() have been called by restAPI.removeHeader() just to be sure that my localStorage it’s saving the correct info.

The problem in this test is that it will work in Chrome and PhantomJS (probably in IE too) but not in Firefox where it throws this error.

This is happening because Jasmine is trying to define a property that is nonconfigurable by the browser and then it can’t override the functions to spy on them.

Mocking with Object.defineProperty() to the rescue

Thanks to Object.defineProperty() we can write a mock of window.localStorage with configurable, enumerable and writable with true values to allow Jasmine to change those methods.

Now, you can use spyOn without any problem and yes, you can use this solution to solve spyOn problems in Jasmine for any object.

By the way, this is highly inspired by this solution I’ve found in this thread at Jasmine Github Issues.

AngularJS Best Practices #002: Scope functions

Posted on July 5, 2014

This series of AngularJS best practices articles are defined by three rules: it’s easier to debug, it’s easier to test and it’s easier to maintain. So maybe this could be worst for other things (like performance).

Scope functions

In this article I want to talk about scope functions and how could help us to write our code. Probably this would be pretty simple, but there are a lot of docs and tutorials where scope functions are barely used.

For example, this is a very common situation where you want to add an item to a shopping cart in an html template.

Due to its simplicity it seems normal to just code “itemCount = itemCount + 1” in the ng-click directive but we can face some problems with this technique.

Using scope functions

The first problem is debugging. Let’s suppose that we’re initializing or changing itemCount in any other place and by some mistake in our code (yes, everybody makes mistakes) and when we click to “Add item” we see that it is not changing our value correctly.

If we had a scope function we just can stop code execution with our browser (Chrome) dev tools and see what’s happening easier. So for me, this is a better approach:

That’s so much better, now we can use Chrome dev tools to stop code execution before we update the variable and see if the problem is in this function or not.

But also is better for maintanability, we can add more statements to the functions easily without modifying our html templates that are already cached in the user’s browsers:

And yes, this is also better for testability. Scope functions are very easy to test something that you can’t with html expressions.

Scope functions and listeners

Another common mistake that I’ve done before is to create private functions for listeners. For example:

I thought that this was a good practice because onTriggerElem function is private and it is not necessary to be public but nothing far from the truth. Setting onTriggerElem as a private function would make the function harder to test.

Maybe this could be hard to $digest() (bad joke, sorry) but JavaScript seems to me too much dynamic and open to make private functions. Of course, there are situations where you must do that like when you’re building an API for third-party developers (like I do in my Videogular project), but the truth is that using private functions will make your code harder to test and it feels to me like something that shouldn’t be done.

So, if you’re new (or not) to AngularJS and you’re not using a lot scope functions my recommendation is to use them always, even with the simpler functions, because sooner or later you will need them.

AngularJS Best Practices #001: Constants

Posted on June 21, 2014

I’m working with AngularJS for almost two years and I’ve decided to post a series of AngularJS best practices to share my experience and get feedback from the community. If you consider that something is wrong or could be improved, just leave a message in this post and I will update this entry.

On the other hand, this series of AngularJS best practices articles are defined by three rules: it’s easier to debug, it’s easier to test and it’s easier to maintain. So maybe this could be worst for other things (like performance).

Constants

AngularJS offers a provider for constants that despite is not very popular it could save you hours of debugging.

Let’s see an example about how Constants work.

This is a classic example, you want a config that could be injectable at any part of your application and it works but maybe is not the best use of a constant.

There are better ways to inject a config in your application, probably the best you can do is to create a service and load with $http a JSON file. This is better for many reasons, but probably the most important is that you can update your config file without modifying your code, so if you have the same project in different servers you can have one source code base. That’s better for testing and maintainability.

Using Constants

Let’s see now another example, what problems could we have and how we can solve them with constants.

Another classic. We have a custom directive and we’ve been added a ‘click’ listener. Are you sure? Take a look again, we have a typo, we’ve been written ‘cilck’ instead of ‘click’ and now we’re driving us nuts wondering why the heck our click is not working.

And this is something that could happen to you very easy and with other situations, like when you’re dispatching or listening to an event:

So here is where constants are really useful. Just create a constant for all your events and string literals and inject them as a dependency.

Now you can forget to stop writting typos. You can even have your events organized by MY_EVENTS.JS.CLICK, MY_EVENTS.ANGULAR.DESTROY and MY_EVENTS.MY_APP.GET_NOTIFICATION, adding you verbosity and helping you having a centralized file for all your events. And you not only will not need to remember any string ever, what’s more important is that even you have a typo in your custom events (like GET_NOTIFICATION) they will work with a typo across your application because you will be listening and dispatching the same string literal!!

Obviously you can use constants for a lot of things but try to use them wisely. Think that a constant should be something that you can’t modify even with a decorator, so use constants where it should be used.

AngularJS video source directive

Posted on April 8, 2014

This is a quick post and a very simple directive to change the video source with AngularJS. This seems to be something simple because you think that ng-src should work perfectly but it doesn’t, so maybe this directive will help you.

To use this directive you just need to create a scope variable in your controller with an object like this:

Then in your controller create a scope function to change the source and that’s it:

Your final code should looks like this:

This solution is what we are currently using in our Videogular project and I think that it is also useful if you don’t want to use Videogular and you want only to change a video source.

To use this directive in your HTML just set a video tag like this:

You can try this AngularJS video source directive in this demo.

To browse the code check the repo at Github.

If you want something more powerful you can take a look to Videogular, maybe is what you’re looking for :)

Happy fucking coding!

Older Posts