Wednesday, June 15, 2016

ncline-screenshots: New ncline Module For Managing Screenshot Files

When I'm observing a multi-step process during a debugging exercise, I often take screenshots at each breakpoint.  It gives me a record of the data values and behavior at particular points in the process, sometimes recording something I didn't realize I needed to pay attention to until after the fact.

On Windows computers, I use the freeware application Greenshot to take my screenshots.  One of the features of Greenshot is that it lets you use date and time parameters in the filename settngs, so I have it set to save each screenshot with a name and folder location based on date and time.  If I were to take a screenshot on June 16, 2016 at 3:30pm, I'd end up with a file named "screenshot-15-30-00.png" in a "2016-06-16" subdirectory of my root screenshot directory.

I recently started using a Mac laptop as my primary personal laptop, and I was disappointed to learn that there is no Greenshot version for Macintosh.  OS X's native screenshot implementation is less than ideal:  it saves the screenshot file on the desktop and provides no control over the naming of the screenshot (though it does include the timestamp in the name).  I looked at what Mac-compatible screenshot programs were out there and found many of them had a workflow geared towards manipulating the screenshot right after taking it.  I just wanted to take the screenshot, move on to the next one, and review all of them later.

So I decided to solve my Mac screenshot problem myself.  First, I followed the instructions for changing the location where OS X saves the screenshots (it's not a setting you can change in the OS X UI anywhere) so the files would be created somewhere other than the desktop.  Then I wrote ncline-screenshots, a new, separately-downloaded command module for my Node-powered ncline project.  It uses the chokidar npm module, an enhancement on the native Node file watcher library, to watch the directory where the screenshot files are created.  When a new file is found in that directory, it gets processed by a series of processing rules that rename and/or move the file.

The command module creates the watcher task, provides private functions that implement the processing rules, and includes a few commands for changing configuration settings and rule processing behavior.  Creating additional rules is simply a matter of writing additional functions that manipulate the file and pass on the results of the change to the next rule in the sequence.

Even though it was written to solve a Mac-specific gap in my workflow, ncline-screenshots works on Windows systems as well.

Friday, February 12, 2016

Announcing ncline: a Node Program/Platform for Executing JavaScript Functions from a Command Line

I'm pleased to announce the release of my new open-source project, ncline. ncline stands for "Node Command Line", and it's a platform for writing Node-powered JavaScript functions ("commands") that can be executed from a command line interface.

When you launch ncline, it loops through the collections of module folders within the master "cmdModules" folder and adds any functions exported under the "commands" property to a catalog of executable commands. The user can then execute any of those commands from the ncline command prompt by typing the command name followed by any required or optional arguments. Arguments can be provided in positional order or as a set of "name:value" pairs enclosed in brackets.



Ncline is designed to allow developers to customize it to their needs. Writing a command function that ncline can execute is no different from writing a regular JavaScript command, so experts and beginners alike can create basic commands fairly easily. The main ncline functions take care of registering the commands and managing the passage of arguments from the command line to the function. ncline provides generic Levitra online library functions for parsing arguments and for generating feedback to the ncline console (warnings, error messages, etc.) that can be leveraged within commands.



ncline also provides conventions for the creation and storage of user-generated command data that persists between sessions as private JSON data and for adding command documentation via a JSON file.

Out of the box, ncline provides commands for:

  • Adding, changing, and deleting aliases for individual or multiple filepaths, and for setting the current target and source filepaths for filepath-related functions.

  • Opening one or more file explorer windows based on the provided alias name.

  • Opening one or more terminal windows based on the provided alias name.

  • Executing a Grunt command in the filepath represented by the provided alias name.

  • Creating or opening a .txt file in Notepad based on the provided alias name (Windows only).

  • Adding, changing, and deleting aliases for Windows batch files (Windows only).

  • Executing the Windows batch file associated with the specified batch alias name (Windows only).

  • Adding, changing, and deleting aliases for opening websites from ncline in the specified browser (useful for opening multiples sites in one browser or the same site in different browsers quickly).

Further information can be found on the GitHub site for ncline at https://github.com/bcswartz/ncline.

Sunday, December 13, 2015

Instructing Proxyquire To Ignore Nested Requires

When writing unit tests for Node.js applications, you can use the proxyquire npm module to override the modules pulled in by the file under test using require(), replacing them with your own.  So say your file containing the methods you want to test pulls in two other modules using require:


//underTest.js
var moduleA = require( './moduleA' );
var master = require( '../../core/master' );
...
module.exports = {
  runFoo: function() { return moduleA.outputResult() }
};

...in your unit test, you can use a stub library like Sinon in conjunction with proxyquire to instantiate the file under test but with the stubs used in place of the normal modules:


//underTest.spec.js
var sinon = require( 'sinon' );
var proxyquire = require( 'proxyquire' );

describe( 'underTest.js functions', function() {
  var stubModuleA, stubMaster;

  before( function() {

    var stubModuleA = sinon.stub();
    var stubMaster = sinon.stub();

    underTest = proxyquire( './underTest', {
      './moduleA': stubModuleA,
      '../../core/master': stubMaster
    });
  
  });
  
});

...and then you can spy on and define the function behavior of the stubbed objects for your tests.

When I first did this, I ran into problems because one of the modules I was replacing (say moduleA) itself pulled in a module of its own:


//moduleA.js
var main = require( '../../main' );

...and in that main module were functions that executed as soon as the file was loaded via require(), and the execution of those functions caused the before() block of my test file to bomb.

After some research, I discovered that one solution was to use proxyquire to override the require() call in moduleA, and instruct proxyquire to essentially ignore the require by not calling through to it.


//underTest.spec.js (revised)
var sinon = require( 'sinon' );
var proxyquire = require( 'proxyquire' );

describe( 'underTest.js functions', function() {
  var stubModuleA, stubMaster;

  before( function() {

    var stubModuleA = proxyquire( './moduleA', {
      '../../main': { '@noCallThru': true }
    });
    
    var stubMaster = sinon.stub();

    underTest = proxyquire( './underTest', {
      './moduleA': stubModuleA,
      '../../core/master': stubMaster
    });
  
  });
  
});

Wednesday, April 8, 2015

Mild Hack for Unit Testing the Run Method of an Angular Module

In Angular 1.x, the run() method of a module behaves similar to the main method or constructor method concept found in other languages:  it's a method that runs as soon as all of the dependencies have been resovled and the module has been configured.

Because of this, even if you use run() to execute a named method that can be called separately in your unit test, the code in that method gets executed during the process of instantiating the module to use in your tests.  That makes it difficult to do any testing that compares the state of data prior to running the method or tests that require mocking dependencies and dependency behavior inside of the method.

So when I ran into this problem, I came up with a mild "hack" to work around the immediate execution of the run() method.  I made the execution of the code inside my run method dependent on the value of a Boolean constant:


angular.module( 'mainModule', [] )
    .constant( 'executeRunMethod', true )
    .run( runMethod );

function runMethod( $rootScope, authService, executeRunMethod ) {
    if ( executeRunMethod ) {
        //Execute the code as expected
    }
}

runMethod.$inject = [ '$rootScope', 'authService', 'executeRunMethod' ];

With the executeRunMethod constant set to true, the runMethod() code executes via run() once the module is wired up as expected, so everything "runs" normally.

In my unit test however, I can override the executeRunMethod constant during the process of instantiating the module, setting it to false, effectively preventing the run() method from executing.


'use strict';

describe( 'mainModule', function () {
    var $rootScope,
        mockAuthService;

    beforeEach( function () {

        module( 'mainModule', function ( $provide ) {
            // The executeRunMethod constant is overridden to be false
            $provide.constant( 'executeRunMethod', false );
        } );

        inject( function ( $injector ) {
            $rootScope = $injector.get( '$rootScope' );
            mockAuthService = { requestUser: function() {} };
        } );

    });

Later in the test file, I can test the runMethod directly, passing in the needed arguments, including a "true" instance of the executeRunMethod argument allowing the code to be executed:


describe( 'the runMethod function', function() {

        var executeRunMethod = true;

        it( 'performs the expected action', function () {

            runMethod( $rootScope, mockAuthService, executeRunMethod );

            expect( result ).toEqual( expectation );
        });
});

So this arrangement lets me test the code used by the module run() method just as if it was a normal method.

Monday, March 9, 2015

Using a Route Naming Convention to Control View Access in AngularJS

Suppose for a moment that you have an AngularJS single-page application, one with view routes managed with then ngRoute module, that is used by users with different roles.  A user in your company's Sales group has access to certain areas of the application, while a user in Accounting works in other parts of the application.  And there are also some areas of the application that are common to all users.

Now, you already have the navigation menu wired up so that users only see the navigation links appropriate to their user roles.  And even if a Sales user somehow ends up in a view meant for an Accounting user, the server answering the REST calls for the data powering that view is going to check the security token sent with the request and isn't going to honor that request.  But you'd still like to keep users out of UI views that aren't meant for them.

You could do a user access check at the start of each controller, or perhaps within the resolve property of each route, but that would be repetitive and it's something you could forget to do on occasion.

What's cool about the route URLs you can construct with the ngRoute $routeProvider is that they don't have any relation to the actual file structure in your application.  You could define a route like so:


$routeProvider.
  when( '/the/moon/is/full/and/the/night/is/foggy', {
  templateUrl: 'views/fullmoon.html',
  controller: 'moonController'
 })

...and it's perfectly okay as long as the templateUrl and controller are legit.

So let's use that fact about route URLs to solve the challenge presented by having the route URL determine user access to the view attached to the route.

Pretend you have a sessionService module in your Angular application that manages the current session and stores the current user's information in a user object, and that user object has a "roles" property that is an array of all of the security roles that user has. If you add the following code in your main application module (the module named in the ng-app attribute in your application)...


.constant( 'authRoles', [ 'sales', 'accounting' ] )

.run( [ '$rootScope', '$location', 'sessionService', 'authRoles', function( $rootScope, $location, sessionService, authRoles ) {

    $rootScope.$on( '$routeChangeStart', function ( event, next, current ) {
        if( sessionService.isActive() ) {
            var targetRoute = $location.path();
            if( targetRoute.split( '/' )[1] == 'auth' ) {
                var routeRole = targetRoute.split( '/' ).length > 2 ? targetRoute.split( '/' )[2] : '';
                 if( sessionService.getUser() == undefined ) {
                    $location.path( '/login' );
                } else if ( routeRole && authRoles.indexOf( routeRole ) > -1 && sessionService.getUser().roles.indexOf( routeRole ) == -1 ) {
                    $location.path( '/unauthorized' );
                }
            }
        }
    });

 }])

...then when a route change is initiated, the requested route URL will be parsed to determine if the route is secured in any way. Any route URL beginning with "auth" is only accessible to authenticated users, and any URL where the location segment after "auth" matches one of the user roles defined in the "authRoles" constant (in this case, "sales" and "accounting") will only be accessible to a user having that role in their "roles" array.

So the given users attempting to navigate to the given routes will get the given results:

User Route Result
Unauthenticated user /home Routed to "home" view
Unauthenticated user /auth/viewAccount Routed to "/login" (login page)
User with Sales role /auth/viewAccount Routed to "viewAccount" view
User with Sales role /auth/sales/customer/1 Routed to detail page for customer 1
User with Sales role /auth/accounting/stats Routed to "/unauthorized" ("you are not authorized" page)
User with Accounting role /auth/viewAccount Routed to "viewAccount" view
User with Accounting role /auth/accounting/stats Routed to the "stats" view
User with Accounting role /auth/sales/propects Routed to "/unauthorized" ("you are not authorized" page)
User with Accounting role /auth/marketing/addAccount Routed to the "addAccount" view, as "marketing" isn't a recognized role
User with Sales and Accounting roles /auth/accounting/stats Routed to the "stats" view

 

What if you had three roles (Sales, Accounting, HR) and you had a route that you wanted to only be accessible to the Sales and Accounting users?  In that scenario, you'd either have to create a new user role that Sales and Accounting folks would both have, or you'd only secure the route with "auth" and fall back to doing a manual role check in the route's controller or resolve property.  So it's not a technique that solves every scenario, but it's a good first step.

Monday, March 2, 2015

Introducing Sparker: A Codebase Library Management Tool Showcasing AngularJS, Protractor, and Grunt Techniques

Sometimes projects take on a life of their own, and you end up with something unexpected.

I set out to create an template for CRUD-focused single page AngularJS web applications, something I and perhaps my colleagues could use as a foundation for writing new applications.  But under the momentum of self-applied scope creep, what I ended up creating was a Grunt-powered codebase library management tool, with my original template concept as the first codebase of potentially multiple foundational codebases.

After sitting back and looking at what I ended up with, I decided to name the project Sparker for two reasons:

  • I didn't want to use terms like "templates", "scaffolds", or "foundations" for the codebases housed in the project (partly because the project encourages creating demo codebases to accompany the "clean slate" template codebases).  So the codebases are organized into "sparks" and Sparker is the tool for managing them.

  • I wanted to focus on the inspirational aspect of the project:  that, at worst, the techniques in the sparks and in Sparker could "spark" ideas in other developers for how to approach certain problems.

At the end of the day, I see Sparker as a functional proof-of-concept, something individuals or particular teams can play around with or use in their shops to maintain and build off of their own spark libraries, but not something adopted for widespread use by the developer community.  It's not designed to compete with things like Yeoman or Express.js because, like I said, it didn't come out of a design.  But it was fun to develop, and I think there's value in sharing it.

Some of the things you'll find in Sparker today:

  • An example of how to organize Grunt tasks and task options into separate files, and how to execute two different sets of tasks from the same directory/Gruntfile.

  • A Grunt build task that determines which resource files to concatenate based on the <link> and <script> tags in your index.html file.

  • A technique for executing the login process and running certain sets of Protractor tests based on the user role being tested.

  • Convention-based Angular routes for restricting user access based on authentication state/user roles.

  • Example of mocking REST calls within a demo Angular application using the ngMockE2E module.

  • Examples of Angular unit tests and Protractor tests that utilize page objects.

Sparker is available on GitHub at https://github.com/bcswartz/Sparker.

Tuesday, February 24, 2015

Lightning Talk Presentations from the Recent AngularJS DC Meetup

Last week I participated in a series of lightning talks at the AngularJS DC Meetup, hosted by Difference Engine, and I thought I'd share the links to the slide decks and demos presented (unfortunately, the equipment recording the entire event failed, otherwise I would just share that).

Not all of the presenters have posted their material, but here what's been shared so far: