2015 in review

Standard

The WordPress.com stats helper monkeys prepared a 2015 annual report for this blog.

Here’s an excerpt:

A New York City subway train holds 1,200 people. This blog was viewed about 6,000 times in 2015. If it were a NYC subway train, it would take about 5 trips to carry that many people.

Click here to see the complete report.

Browser Sync in Visual Studio

Standard

One may use Browser Sync node plugin in order to keep multiple browsers & devices in sync when building websites.

Installation:

  • install NodeJS
  • install Browser Sync by typing below command in CMD
        npm install -g browser-sync

    Setting in Visual Studio:

    • Open your project in VS (I am using VS2013 for tutorial, have successfully tested on VS2012 and VS 2015)
    • Right Click on web project and select Properties option11
    • Select Web Tab from properties window12
    • Choose Dont open a page. Wait for a request from an external application from Start Action sub menu, then note the port number from project URL text box and save the properties file (ctrl + s)13
    • Now right click on project, Select Power Commands and click on Open Command prompt14 
    • Execute below command in CMD, Change port number which you copied earlier from Project URL textbox, mention path of files which you want to monitor like css, js, html, cshtml etc.
      Please note in CMD always make sure it is pointing towards your project (for example in this case c:\Users\hassan.muhammad\Desktop\MS\bing\Bing.Web>, otherwise browser will look for js,css and html files from root folder and will not reload changes on browser. 
       browser-sync start --proxy localhost:3495 --files "content/*.css, scripts/*.js, views/**/*.cshtml"

      15

    • As soon you execute above statement in CMD, this will trigger browser-sync and it will load your project in browser16 
    • Browser-sync notification will also be available on your browser for a while confirming any changes you made to these files will be reloaded on browser automatically17 

      [In order to use browser-sync as part of your automation workflow with GulpJS]

GulpJS: Setting up test runner on HTML

Standard

Setting up test runner on HTML

  • Use gulp-jasmine-browser in order to execute jasmine tests in a browser using gulp.
  • In order to check output, type following url in browser window: http://localhost:8888/

Pre Install:

    npm install --save-dev  

Install:

    npm install --save-dev gulp-jasmine-browser

Code:

    var gulp = require('gulp');
    var jasmineBrowser = require('gulp-jasmine-browser');
    var config.files = ['./scripts/lib/angular/angular.js',
        './scripts/lib/angular/angular-mocks.js',
        './scripts/app/myService.services.js',
        './scripts/app/myService.services-spec.js',];

    gulp.task('jasmineBrowser', function () {
        return gulp.src(config.files)
          .pipe(jasmineBrowser.specRunner())
          .pipe(jasmineBrowser.server({ port: 8888 }));
    });

Execute:

    gulp jasmineBrowser

GulpJS: E2E Testing with Protractor

Standard

E2E Testing with Protractor

  • Protractor is an end-to-end test framework for AngularJS applications
  • It execute tests against your application running in a real browser, interacting with it as a real life user.
  • Make sure you have updated version of webdriver-manager otherwise execute below command in cmd before executing gulp task
webdriver-manager update --standalone
  • In protractor.config.js file mention file path to the selenium server jar, path of chrome driver and comment out address of a running selenium server before executing gulp task
seleniumServerJar: './node_modules/protractor/selenium/selenium-server-standalone-2.48.2.jar',
chromeDriver: './node_modules/protractor/selenium/chromedriver.exe',
//seleniumAddress: 'http://localhost:4444/wd/hub',
  • Start webdriver-manager in seperate console before executing gulp task
webdriver-manager start
  • __dirname is global object of NodeJS for the name of the directory that the currently executing script resides in

Pre Install:

    npm install --save-dev gulp

Install:

    npm install --save-dev gulp-protractor protractor

Code:

    var gulp = require('gulp');
    var protractor = require("gulp-protractor").protractor;

    gulp.task('e2e', function (done) {
        gulp.src(__dirname + './protractor_test/')
        .pipe(protractor({
            configFile: './protractor.config.js',
            args: ['--baseUrl', 'http://127.0.0.1:8000']
        }))
        .on('error', function (e) { throw e })
    });

Execute:

    gulp e2e

GulpJS: Unit Testing with Jasmine and Karma

Standard

Unit Testing with Jasmine and Karma

  • karma is Test Runner for JavaScript, a tool that allows you to execute JS code in multiple real browsers
  • karma is A Karma plugin. used to generate code coverage.
  • Task singleRun refers to execute tests once, it can fail a build but perfect for continuous integration
  • Task alwaysRun refers to execute tests and stay alive, monitors changes in file and re-run with each change
  • Please make sure karma.config.js file is included in your project before executing gulp task
  • __dirname is global object of NodeJS for the name of the directory that the currently executing script resides in

Pre Install:

    npm install --save-dev gulp

Install:

    npm install --save-dev karma phantomjs karma-coverage karma-growl-reporter karma-phantomjs-launcher  karma-firefox-launcher karma-ie-launcher karma-chrome-launcher karma-jasmine jasmine

Code:

    var gulp = require('gulp');

    gulp.task('singleRun', function (done) {
        startTests(true, done);
    });

    gulp.task('alwaysRun',  function (done) {
        startTests(false, done);
    });

    function startTests(singleRun, done) {
        var karma = require('karma').server;
        var excludeFiles = [];
        var serverSpecs = 'tests/**/*.spec.js'

        karma.start({
            configFile: __dirname + '/karma.config.js',
            exclude: excludeFiles,
            singleRun: !!singleRun
        }, karmaCompleted);

        function karmaCompleted(karmaResult) {
            if (karmaResult === 1) {
                done('karma: tests failed with code ' + karmaResult);
            } else {
                done();
            }
        }
    }

Execute:

    gulp singleRun
    gulp alwaysRun

GulpJS: File Version

Standard

File Version

  • Use gulp-bump for vesrioning in package.json and bower.json
  • –type=pre will bump the prerelease version ..*-x
  • –type=patch or no flag will bump the patch version ..x
  • –type=minor will bump the minor version .x.
  • –type=major will bump the major version x..
  • –version=1.2.3 will bump to a specific version and ignore other flags
  • for –version=1.2.3 means 1 corresponds to major, 3 corresponds to minor and 3 corresponds to package version

Pre Install:

    npm install --save-dev gulp gulp-load-plugins yargs

Install:

    npm install --save-dev gulp-bump

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var args = require('yargs').argv;

    gulp.task('version', function () {
        var type = args.type;
        var version = args.version;
        var options = {};
        if (version) {
            options.version = version;
        } else {
            options.type = type;
        }
        return gulp
            .src([ './package.json', './bower.json' ])
            .pipe($.bump(options))
            .pipe(gulp.dest('./'));
    });

Execute:

    gulp version --version=2.0.0
    gulp version --type=minor

GulpJS: File Revisions

Standard

Revisions

  • Use gulp-rev in order to implement static asset revisioning by appending content hash to filenames: unicorn.css => unicorn-d41d8cd98f.css
  • Use gulp-rev-replace in order to rewrite occurences of filenames which have been renamed by gulp-rev in index.html(html referencing file)
  • gulp-rev-replace solves the cache problem too

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-rev gulp-rev-replace

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });

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

        return gulp
            .src('src/*.js')
            .pipe($.rev())
            .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp revision

GulpJS: Angular Dependency Injection

Standard

Angular Dependency Injection

  • Use gulp-ng-annotate in order to provide automatic security blanket because manglin your code can break angular dependency injection
  • gulp-ng-annotate looks for dependency injection and adds angular injection
  • Use ** /* @ngInject / * annotation on top of controller, services, anonymous function etc to resolve dependency injection if forget to use Strict Dependency Injection (ng-strict-di) or $inject Property Annotation.
  • @ngInject provide code hint for gulp-ng-annotate to add angular injections
  • Avoid implementing @ngInject for third party libraries

Pre Install:

    npm install --save-dev gulp gulp-load-plugins

Install:

    npm install --save-dev gulp-ng-annotate

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var assets = $.useref.assets({ searchPath:  './' });
    var cssFilter = $.filter('**/*.css');
    var jsLibFilter = $.filter('**/' + config.optimized.lib);
    var jsAppFilter = $.filter('**/' + config.optimized.app);

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

        return gulp
        .src('./build/index.html')
        .pipe(assets)
        .pipe(cssFilter)
        .pipe($.csso())
        .pipe(cssFilter.restore())
        .pipe(jsLibFilter)
        .pipe($.uglify())
        .pipe(jsLibFilter.restore())
        .pipe(jsAppFilter)
        .pipe($.ngAnnotate())
        .pipe($.uglify())
        .pipe(jsAppFilter.restore())
        .pipe(assets.restore())
        .pipe($.useref())
        .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp di

GulpJS: Minifying Files

Standard

Minifying Files

  • Use gulp-Uglify to remove whitespace, comments, minify javascript files
  • Use gulp-CSSO to remove whitespace, comments, transform css files
  • Use gulp-filter to seperate out/reduce/filter files from gulp stream
  • Manglin your code can break angular dependency injection, in order to avoid this use Strict Dependency Injection (ng-strict-di) or $inject Property Annotation
  • Filter.restore() function put filter back into stream

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-filter@v2.0.0 gulp-csso gulp-uglify

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var assets = $.useref.assets({ searchPath:  './' });
    var cssFilter = $.filter('**/*.css');
    var jsFilter = $.filter('**/*.js');

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

        return gulp
            .src('./build/index.html')
            .pipe(assets)
            .pipe(cssFilter)
            .pipe($.csso())
            .pipe(cssFilter.restore())
            .pipe(jsFilter)
            .pipe($.uglify())
            .pipe(jsFilter.restore())
            .pipe(assets.restore())
            .pipe($.useref())
            .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp minify 

GulpJS: Combing all JS and CSS into respective one file

Standard

Combing all JS and CSS into respective one file

  • Use gulp-useref in order to concatenate all css into one css file and all js files into one js file
  • Parse build blocks in HTML files to replace references to non-optimized scripts or stylesheets.
  • Similar to gulp-inject
  • Index.html should have bower/inject/build section, bower and inject area should be populated first using wiredep and gulp-inject task, then execute this task to concatenate all css and js file into respective single file as mentioned under build tag of index.html

Pre Install:

    npm install --save-dev gulp gulp-load-plugins

Install:

    npm install --save-dev gulp-useref@v1.1.0

Syntax in HTML File for gulp-useref:

    <!-- build:css content/lib.css -->
    <!-- bower:css -->
    <!-- endbower -->
    <!-- endbuild -->

    <!-- build:css content/site.css -->
    <!-- inject:css -->
    <!-- inject -->
    <!-- endbuild -->

    <!-- build:js js/lib.js -->
    <!-- bower:js -->
    <!-- endbower -->
    <!-- endbuild -->

    <!-- build:js js/app.js -->
    <!-- inject:js -->
    <!-- endinject -->
    <!-- endbuild -->

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var assets = $.useref.assets({ searchPath: './' });

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

        return gulp
            .src('./build/index.html')
            .pipe(assets)
            .pipe(assets.restore())
            .pipe($.useref())
            .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp combine
  • $.useref.assets() collects assets from the HTML comment
  • $.useref.restore() restore the files to the index.html
  • $.useref() will concatenate files