Deploy Angular 2 CLI app to Heroku

Angular2 CLI generated apps can’t be directly deployed in Heroku. But it is easy to configure them to do that using scripts to build and serve the app.

I used angular-cli 1.0.0-beta.20-4 to generate and Angular2/Webpack app.
npm install -g angular-cli
ng new ng2-demo-app

And configured the package.json file using heroku-prebuild, heroku-postbuild and start scripts to build the app and serve it using http-server.

"scripts": {
  "heroku-prebuild": "npm install -g http-server",
  "heroku-postbuild": "ng build --prod",
  "start": "http-server dist/",

Heroku-prebuild and heroku-postbuild are Heroku-specific build steps, they are equivalent to the generic preinstall or postinstall but using them we avoid running those scripts locally.

In Heroku dev-dependencies are not installed by default, that means that to make the ng build script to work we need to move dev-dependency to the dependencies block.

"dependencies": {
  "@angular/common": "~2.1.0",
  "@angular/compiler": "~2.1.0",
  "@angular/core": "~2.1.0",
  "@angular/forms": "~2.1.0",
  "@angular/http": "~2.1.0",
  "@angular/platform-browser": "~2.1.0",
  "@angular/platform-browser-dynamic": "~2.1.0",
  "@angular/router": "~3.1.0",
  "core-js": "~2.4.1",
  "rxjs": "5.0.0-beta.12",
  "ts-helpers": "~1.1.1",
  "zone.js": "~0.6.23",

  // moved here these devDependencies
  "angular-cli": "1.0.0-beta.20-4",
  "@angular/compiler-cli": "~2.1.0",
  "@types/jasmine": "~2.2.30",
  "@types/node": "~6.0.42",
  "typescript": "~2.0.3"
},
"devDependencies": {
  "codelyzer": "~1.0.0-beta.3",
  "jasmine-core": "2.4.1",
  "jasmine-spec-reporter": "2.5.0",
  "karma": "1.2.0",
  "karma-chrome-launcher": "~2.0.0",
  "karma-cli": "~1.0.1",
  "karma-jasmine": "~1.0.2",
  "karma-remap-istanbul": "~0.2.1",
  "protractor": "4.0.9",
  "ts-node": "1.2.1",
  "tslint": "3.13.0",
  "webdriver-manager": "10.2.5"
}

Notice that it’s preferable to move only the dependencies you actually need for production builds. For that reason I moved only the dependencies required for the build but not the testing or linting dependencies.

If you don’t want to be moving dependencies it is possible to disable the production mode in the Heroku instance with
heroku config:set NPM_CONFIG_PRODUCTION=false
With this Heroku will install all dependencies, included the dev ones.

Another alternative to the http-server solution explained here is to use the NGINX and Heroku-buildpack-static.

Docs:
https://www.angularonrails.com/deploy-angular-cli-webpack-project-heroku/
https://github.com/angular/angular-cli/issues/2517
https://m.alphasights.com/using-nginx-on-heroku-to-serve-single-page-apps-and-avoid-cors-5d013b171a45#.1zpyh4lao
https://github.com/heroku/heroku-buildpack-static

Advertisements

Jasmine-Matchers – Adding more common matchers to Jasmine.

Jasmine-Matchers is a library of test assertion matchers for a range of common use-cases, to improve the readability of tests written using the Jasmine testing framework.

Installation

Install the package

npm install karma-jasmine-matchers --save-dev

And configure it in karma.conf in the frameworks section

frameworks: ['jasmine', 'jasmine-matchers’],

To use the additional matchers also in protractor e2e, protractor should be configured to import the ‘jasmine-expect’ module before the tests run. That can be done in the protractor.conf.js like this:

onPrepare: function () {
// Import additional jasmine matchers
require('jasmine-expect’);
}

Usage

The list of additional matchers is available here https://github.com/JamieMason/Jasmine-Matchers#matchers

Examples

Examples of unit test refactors using new matchers

toBeArrayOfSize
– expect(clients.length).toBe(2);
+ expect(clients).toBeArrayOfSize(2);

and instead of failing like this
Expected 1 to be 2.
when it fails, the new matcher look like this:
Expected [ Object({ id: ‘client-id’, name: ‘A Client’ }) ] to be array of size 2.

toBeEmptyString
– expect(vm.getCategory({})).toBe(‘’);
Expected ‘Test’ to be ‘’
+ expect(vm.getCategory({})).toBeEmptyString();
Expected ‘Test’ to be empty string.

– expect(vm.projectsFilter.name).toEqual(‘’);
Expected ‘Test’ to be ‘’
+ expect(vm.projectsFilter.name).toBeEmptyString();;
Expected ‘Test’ to be empty string.

toBeEmptyObject
– expect(data).toEqual({});
Expected Object({ location: ‘ftp.mysite.com’, username: ‘username’, password: ‘password’, directory: ‘test’ }) to equal Object({ }).
+ expect(data).toBeEmptyObject();
Expected Object({ location: ‘ftp.mysite.com’, username: ‘username’, password: ‘password’, directory: ‘test’ }) to be empty object.

toBeTrue
– expect(vm.showHelp).toBe(true);
Expected false to be true.
+ expect(vm.showHelp).toBeTrue();
Expected false to be true.

Documentation

https://github.com/JamieMason/Jasmine-Matchers
https://www.npmjs.com/package/karma-jasmine-matchers
https://blog.pivotal.io/labs/labs/writing-beautiful-specs-jasmine-custom-matchers
https://github.com/JamieMason/Jasmine-Matchers/issues/60

Adding a Swagger Validator Badge to you project README

The Swagger Validator project can be used to show a “valid swagger” badge on your site or github README file.

captura-de-pantalla-2016-11-06-a-las-7-23-54

To generate a badge image for the validation of your swagger json or yaml file against OpenAPI 2.0 spec use

<img src="http://online.swagger.io/validator?url={YOUR_URL}">

Or using markdown

[![swagger-api validator-badge]({YOUR_URL/api_spec.yaml}task-list-api-swagger-definition.yaml)](./api_spec.yaml)

Links:
https://github.com/swagger-api/validator-badge
https://github.com/swagger-api/validator-badge/issues/77

Decorating Angular $httpBackend service.

An example of how to ​decorate the angular $httpBackend mock server with custom logic. In this example, I log to console the request method and URL.

// Configure the Mock HTTP Backend
angular
    .module('my-app')
    .config(['$provide', function ($provide) {
        $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
    }]);

// Decorate Mock HTTP Backend to log requests
angular
    .module('my-app')
    .config(function ($provide) {
        $provide.decorator('$httpBackend', function ($delegate) {
            let decoratedHttpBackend = function (method, url, data, callback, headers, timeout, withCredentials, responseType) {
                console.log(method + ' ' + url);

                return $delegate.call(this, method, url, data, callback, headers, timeout, withCredentials, responseType);
            };

            for (var key in $delegate) {
                if ($delegate.hasOwnProperty(key)) {
                    decoratedHttpBackend[key] = $delegate[key];
                }
            }

            return decoratedHttpBackend;
        });
    });

Solve CORS Cross-origin issue in Development Environment

Developing a front-end application, let’s say an Angular app, you could run into CORS Cross-origin issues performing requests to back-end services.

XMLHttpRequest cannot load http://my-service/api/my-resource. Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:8000&#8217; is therefore not allowed access.

In production is something that should be configured in the server adding the following header to its response:

Access-Control-Allow-Origin: *

And the same can be done in your local dev machine if you are serving the fron-end and also the back-end. But what happens if your service is in another machine or port?

We can solve this problem with a local reverse proxy, or using apps like Burp Suite. But a really quick workaround is to use the Google Chrome Allow-Control-Allow-Origin plugin.

Don’t forget to configure properly the filters to intercept only the URLs to the services that you use:

http://my-service/api/my-resource/*

CORS_chrome_plugin

Another hacky and quick way to solve this is opening chrome with the web security disabled:

open /Applications/Google\ Chrome.app/ --args --disable-web-security

but It could be really dangerous to use that all the time.

To know more about CORS read http://www.html5rocks.com/en/tutorials/cors/.

Design Patterns – Facade

The Facade Pattern is used to provide a simplified interface to a complicated subsystem.

The idea is to define a higher-level interface that abstracts clients from using directly a set of lower level interfaces in the subsystem. For some clients accessing directly the subsystem could make perfect sense because they benefit from the different options and flexibility of a rich API. However, most of the clients only need basic functionality, accessing a large set of interfaces only bring them complexity.

This pattern is commonly used during refactoring to simplify the use of a legacy code subsystem.

One important difference between this structural pattern and the Decorator pattern is that the goal in Facade is not to add new functionality.

Real examples

* JQuery
JQuery is a good example of Facade Pattern, providing a simple and clean interface to interacting with the complex DOM of the browser.

* Java URL class

URL url = new URL(&quot;http&quot;, &quot;www.google.ie&quot;, 80, &quot;/&quot;;);
url.openStream()

https://docs.oracle.com/javase/8/docs/api/java/net/URL.html

Code example

class FlightsService {
  findFlightsFor(city, date) {
    console.log(`Searching for flight to ${city} on ${date}`);
  }

  book(flightNumber, airline, date) {
    console.log(`Booking flight ${flightNumber} - ${airline} on ${date}`);
  }
}

class HotelsService {
  findHotelsFor(city, checkinDate, checkoutDate) {
    console.log(`Searching for hotels on ${city} from ${checkinDate} to ${checkoutDate}`);
  }

  book(roomNumber, hotel, checkinDate, checkoutDate) {
    console.log(`Booking room ${roomNumber} - ${hotel} from ${checkinDate} to ${checkoutDate}`);
  }
}

class TravelFacade {
  constructor() {
    this.flightsService = new FlightsService();
    this.hotelsService = new HotelsService();
  }

  findFlightsAndHotels(city, travelDate, returnDate) {
    this.flightsService.findFlightsFor(city, travelDate);
    this.flightsService.findFlightsFor(city, returnDate);
    this.hotelsService.findHotelsFor(city, travelDate, returnDate);
  }
}

Documentation

https://en.wikipedia.org/wiki/Facade_pattern
http://www.joezimjs.com/javascript/javascript-design-patterns-facade/
https://dzone.com/articles/design-patterns-uncovered-1
http://www.dofactory.com/javascript/facade-design-pattern

Useful Faker.js API and demo page

In my angular projects,​ I use the faker.js library to generate fake data for the test fixture factories used by my unit tests and the dev application running with a stubbed back-end. It is a convenient and consistent way to generate data that looks real and makes the code of our fixtures really simple. The Faker.js API documentation is really basic and sometimes it not obvious what kind of values it can generate.
To help with that you can use the next demo page https://cdn.rawgit.com/Marak/faker.js/master/examples/browser/index.html that shows examples of generated data for each of the faker.js API methods.

faker_demo

I encourage to use it and get familiar with the faker API to improve the quality of our test data.