Setting up TypeScript and AngularJs in Visual Studio 2013

Update : 6 Nov 2014

Update: Before you begin

In the 9 months or so since this blog post was published, WordPress has recorded over 10,000 page hits on this blog entry alone.  I wish it wasn’t so.  My experience with AngularJs (1.x) was frustrating to say the least.  Soon after posting this blog, I dropped AngularJs as a framework.  There were just too many things that should have been simple that I spent hours and hours trying to figure out – and still couldn’t get working.

As an example, when I tried to run an integration test to fetch json from my back-end database, I could not.  Every article I read said that I should mock out the http request and return mock data.  That is not the point of an integration test.  I need to ensure that the json returned from my service still works with my beautifully hand-crafted AngularJs application.  Angular’s unit testing framework would not allow me to do this.  So I gave up in favour of simpler, more object-oriented, more testable and eventually more explainable JavaScript framework.  But I did give it a good go.

A work colleague of mine sent me a link to a blog post today that just resonated with my own experiences.  Lars Eidnes has persisted with the AngularJs framework for a long time, and posted a blog entitled AngularJS: The Bad Parts.  It makes for a very interesting read.

In the end, choosing a framework is part personal choice, part experience, part guesswork.  My personal choice is not AngularJs.

Update: Angular 2.0

The recent announcement that the Microsoft and Angular teams have been working together on the Angular 2.0 framework is good news indeed.  The upcoming 1.5 version of the TypeScript compiler will include the first language structures to support Angular 2.0 syntax, and will include some elements of the AtScript language.  It will be a very interesting update,  with some very powerful new features.  Interesting times ahead, indeed.

Mastering TypeScript Book : available April 2015

Over the past couple of months I have been working very closely with the publishing team at PAKT Publishing on a new book called “Mastering TypeScript”.  It is scheduled for publication in April 2015.  The concepts and ideas of this blog post have all been updated and expanded within the book.  You can read all about it here : https://www.packtpub.com/web-development/mastering-typescript

B03967_MockupCover_Normal 

Original Post:

I have recently begun working through the AngularJs tutorials, and quickly found that they are geared towards development environments other than Visual Studio.  With the explosion of type definitions available via NuGet and DefinitelyTyped, I wanted to work through the process of getting up and running in AngularJs with a full Visual Studio 2013 development environment – complete with TypeScript debugging through F5.

As one of my passions is unit-testing, I was particularly interested in AngularJs’ methodology for writing and running Jasmine unit tests, as well as writing and running e2e tests. In addition, debugging unit tests and e2e tests was a must-have – thereby providing a complete Visual Studio development environment.

This blog therefore serves as a guide on how to setup TypeScript, AngularJs and Visual Studio 2013, including debugging Jasmine unit tests, debugging AngularJs e2e tests, and configuring a Continuous Integration build server ( TeamCity ).

Firstly, a few links:

AngularJs tutorial – this is the official AngularJs tutorial that I worked through in this blog.  Note that the source-code on git-hub currently covers step_00 through step_04.  Future blog entries will discuss step_05 and beyond.

The completed source-code for this project can be found on git-hub: blorkfish/TypeScriptAngularTutorial

I’ll follow the following steps :

  • Creating a TypeScript Project
  • Using NuGet to install AngularJs, boostrap, jasmine, and DefinitelyTyped definitions.
  • Writing TypeScript versions of the AngularJs controllers and unit tests.
  • Using node to setup karma
  • Debugging with Visual Studio 2013.
  • Debugging Unit tests with IE.
  • Debugging e2e tests with IE.
  • Notes on running tests on a CI build server.

Creating a TypeScript Project.

Let’s go ahead and create a TypeScript project in Visual Studio 2013.  Create a TypeScript Project.  For the purposes of this blog, I’ve called my project TypeScriptAngularTutorial.

image

Upgrade to .NET Framework 4.5

Note that to use the new Microsoft ASP.NET Web API 2.1, we’ll need to upgrade the project to use .NET 4.5.  Simply right-click on the project, select Properties, and modify the Target framework to .Net Framework 4.5:

image

Using NuGet to install dependencies.

Click on Tools | Library Package Manager | Manage NuGet packages for solution.  In the search box, simply type AngularJs:

I used the Angular Js package created by Fitzchak Yitzchaki, as it includes all of the angular js files in one hit:

image

Next, we need the angularjs.TypeScript.DefinitelyTyped package – as seen at the bottom of the list in the above screenshot.

Your project will now include a Scripts folder, with all of the relevant angular .js files, as well as a /Scripts/typings folder with all of the relevant .d.ts definition files for TypeScript:

image

Next, install NuGet packages bootstrap, jasmine, and jasmine.TypeScript.DefinitelyTyped.

image

image

Resolving issues with conflicting typings

At this stage, compiling the project will result in various errors relating to Duplicate Identifiers:

Duplicate identifier ‘describe’, ‘xdescribe’, ‘it’, ‘iit’, etc. etc.

This is due to multiple .d.ts files including definitions for the jasmine libraries.  To resolve this, edit the /Scripts/typings/angular-scenario.d.ts, and comment the definitions for describe etc. at the bottom of the file, and remove the /scripts/typings/jasmine/jasmine-1.3.d.ts file from the project.

image

Compiling the project now will produce 3 errors, all related to JasmineControler.cs.

image

This can be resolved by simply removing the JasmineController.cs file from the project.  It seems that the installation of Jasmine.js automatically adds a Jasmine MVC controller.  Since this is not an MVC project, the relevant MVC references have not been included.

Writing TypeScript versions of AngularJs Controllers and Unit Tests.

At this stage, we are ready to start writing AngularJs code.  Step_00 of the AngularJs Tutorial explains how to create app/index.html, and include the relevant angular.js files in order to see your first AngularJs application up and running.  The only difference between the Tutorial code and the Visual Studio version is the location of the AngularJs files.

Directory Structure

Using NuGet within Visual Studio will automatically create a /Scripts folder, and place JavaScript files in this folder.  NuGet will also place .css files in the /Content/ directory, and the TypeScript DefinitelyTyped definition files (.d.ts) will be downloaded in /Scripts/typings.

I have therefore kept the directory structure used in the tutorial the same as documented on the AngularJs site, and changed the references to /app/lib/ … to use the DifinitelyTyped structure of /Scripts/ …

Css files are split into two directories – those that are included with NuGetPackages are found in /Content, while those that you write yourself as part of the app I have put into the /app/css directory.

The script references for /app/default.html file for Step_00 are therefore as follows:

<head>
    <title>Tutorial app/index.html</title>
    <link rel="stylesheet" href="css/app.css"/>
    <link rel="stylesheet" href="../Content/bootstrap.css" />
    <script src="../Scripts/angular.js"></script>
</head>

Here is the resultant directory structure:

image

Debugging in Visual Studio

Note that setting /app/index.html as your project startup file, and debugging in Internet Explorer ( by hitting F5 ) may not currently have the desired effect.

If your page does not work correctly, i.e. shows Nothing here {{‘yet’ + ‘!}}, the problem is that IE is interpreting the page as an IE 7 standards page.

Include the <meta htp-equiv > tag line at the top of your /app/index.html page to force IE to use the latest version of the standards:

<!DOCTYPE html>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<html lang="en" ng-app="phonecatApp">
<head>

Writing the AngularJs Controller in TypeScript

In step_02 of the AngularJs Tutorial, you will begin writing an Angular Controller.  To do this in TypeScript, simply create a class, with a constructor that uses the $scope keyword.  Remember to include the angular.d.ts file for type definitions.

The full version of step_02 controller.ts is as follows:

/// <reference path="../../Scripts/typings/angularjs/angular.d.ts"/>

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

class PhoneListCtrl  {
    constructor($scope) {
        $scope.phones = [
            { 'name': 'Nexus S', 'snippet': 'Fast just got faster' },
            { 'name': 'Motorola', 'snippet': 'Next generation tablet' },
            { 'name': 'Motorola Xoom', 'snippet': 'Next, next generation tablet' }
        ];
    }
};

If you would like to see the generated JavaScript version of this file, simply click on your project, and then “Show all files”.

At this stage, you should be able to put a breakpoint on the constructor above, hit F5, and debug directly into your TypeScript code.

Using node to setup Karma.

Karma setup is very straight-forward – simply install node and then install karma as directed in the tutorial.  NodeJs is a windows installer, and once installed, simply type

npm install -g karma

You will also need the karma-ng-scenario module.  If you would like to run tests in both Chrome ( the default ) and IE, simply install the karma-ie-launcher.  I use TeamCity for a CI build server, so also need karma-teamcity-reporter:

npm install -g karma-teamcity-reporter
npm install -g karma-ie-launcher
npm install -g karma-ng-scenario
npm install -g karma-junit-reporter

Note that on build servers, you will need to run the above commands while logged in as the account that executes the build.  Simply running the above as an Administrator will not install karma for all logged in users.

Running unit tests with Karma

With a little tweaking to the /test/config/karma.conf.js file to take into account the modified directory structure, running unit tests using karma is pretty simple – just navigate to the /test/scripts directory, and run test.bat.

Note that on build servers, simply append the —single-run parameter to the karma command line, which will run the tests once, and then quit the batch file.

Debugging TypeScript Unit Tests in Visual Studio.

Unfortunately, debugging TypeScript unit tests requires a running instance of Internet Explorer.  Similar to the /app/index.html file, we will need an .html file that we can set as the project startup file, and then simply hit F5 to start debugging unit tests.

In the source provided with this article, I have created two SpecRunner.html files – one for standard Jasmine unit tests, and the other for e2e AngularJs tests.  Instead of using karma as a test runner in this instance, we will simply use Jasmine.

/test/SpecRunner.html is as follows:

<!DOCTYPE html>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<html>
<head>
    <title>Partner Settings Test Suite</title>
    <!-- include your script files (notice that the jasmine source files have been added to the project) -->
    <script type="text/javascript" src="../Scripts/jasmine/jasmine.js"></script>
    <script type="text/javascript" src="../Scripts/jasmine/jasmine-html.js"></script>
    <script type="text/javascript" src="../Scripts/angular.js"></script>
    <script type="text/javascript" src="../Scripts/angular-mocks.js"></script>
    <script type="text/javascript" src="../app/ts/controllers.js"></script>
    <script type="text/javascript" src="unit/controllersSpec.js"></script>
    <link rel="stylesheet" href="../Content/jasmine/jasmine.css" />
</head>
<body>
    <!-- use Jasmine to run and display test results -->
    <script type="text/javascript">
        var jasmineEnv = jasmine.getEnv();
        jasmineEnv.addReporter(new jasmine.HtmlReporter());
        jasmineEnv.execute();
    </script>
</body>
</html>

Note that we have included jasmine.js and jasmine-html.js ( as well as the jasmine.css ) into the page, along with the required angular and controller javascript files.

Running the project with /test/SpecRunner.html as your startup page will allow you to set breakpoints in any of the above included javascript or typescript files.

image

Debugging TypeScript e2e tests with Visual Studio

Setting /test/e2e/SpecRunner.html as your project startup file will also enable debugging of e2e tests, when hitting F5 in Visual Studio.

image

If you would like to run the /test/script/test_e2e.bat file, just keep in mind that this requires a running web-server.  In Visual Studio, you need to hit F5 to start up IISExpress before running the batch file.  Otherwise, you will get an error as follows:

image

Note that in the /test/config/karma.e2e.js file there is a reference to proxies.  This sets the web-server site and port for the e2e tests to a running web-server instance.  In the properties of the project file, I have set the IIS Express port to be 53722, and this is the value of the proxies setting:

image

module.exports = function (config) {
    config.set({
        basePath: '../../',

        files: [
          'test/e2e/**/*.js'
        ],
        
        urlRoot: '/_karma_/',

        autoWatch: false,
        
        singleRun: true,
        
        proxies : {
            '/' : 'http://localhost:53722'
        },

Running tests on a CI build server.

To conclude, just a few notes on running tests on a CI build server.

In order to run unit tests on a CI build server ( such as TeamCity ), bear in mind the following:

  • Use the –-single-run parameter on the karma command line to run unit tests once only.
  • Depending on which build server you have, you may need either karma-junit-reporter, or karma-teamcity-reporter to report on unit test results correctly.
  • To launch tests in multiple browsers, make sure that you have installed the relevant launcher on the build server ( karma-chrome-launcher, karma-firefox-launcher, karma-ie-launcher).
  • Make sure that you log in as the account that runs the build to install karma and relevant reporters and launchers.
  • For e2e tests, a full version of the running web-site is required.
  • We use the Visual Studio packaging mechanism and msdeploy for automatic deployment on build servers.
  • Point your proxies setting in karma.e2e.conf.js to the web-site as above.
  • For web-servers that are behind a firewall, have a look at using cntlm local proxies.  This allows you to use your normal login on a server that does not have internet access.  All authentication is via a hash-key – so no username / passwords are in plain text.
    Have fun,
    – blorkfish.
Advertisements