Testing TypeScript Node app with Jasmine

Setup Jasmine testing framework with Node and TypeScript

My typescript project setup is described in this article. To be able to write tests in typescript with Jasmine framework we need to setup project environment with some Jasmine specifics.

This scaffold project is also available on the github.

Initialize typescript compiler and linter :

Compiled javascript files for code and jasmine test specifications will be saved to “dist” folder.

Now we need to install Jasmine and jasmine to typescript reporter:

Jasmine typescript console reporter (jasmine-ts-console-reporter) will report errors based on typescript files instead of javascript files. It will tell you which test and the location in the file failed referring to typescript files instead of javascript files.

Initialize jasmine in your project :

Change generated jasmine.json to match this one:

Create special helper to enable “jasmine to typescript” console reporter. In the spec/helpers folder add new file “ts_console.ts” with the content:

Prepare test code

Write some program logic and tests:

To test this simple api we create “myapi-spec.ts” file in the spec folder:

The full project structure:

To compile all typescript to javascript run “tsc” command in the root of the project.

And to run jasmine tests we run locally installed jasmine with the command:

If everything is correct, jasmine will report result of the run in the console:

Because we add additional “typescript console reporter” to jasmine, the errors reported are referenced to typescript (.ts) files with exact line/column and error message.

Integrate jasmine test results with Code editor

First we need to understand how vs code editor tasks works. As we see in jasmine report, each failure is described in multiple lines. The problem matcher should analyze multiple lines pattern, this is described here.

Problems tab should display errors in tests after test run

Create task for running jasmine and to intercept errors as “problems” in the visual studio code problems tab:

As we see in the screenshot, the exceptions in jasmine test results are intercepted by vs code editor and presented as “problems”.  If you click on the single problem line, the file under the error will be opened and cursor will be moved to the corresponding location.

Task

In the .vscode folder create “tasks.json” file with the jasmine command and additional logic to parse results (problemMatcher) :

How to write regular expressions

If you will study the pattern matching you should remember that matcher works on the console results line by line. All patterns together (all regexp lines patterns) represent one intercepted error.

If you need to change any of patterns in the future, the regex string in the tasks.json file is written in the “escaped” form. To develop and test patterns interactively, use this interactive javascript regex tester.  You can copy specific line from the result (line by line!) into the regex tester and develop a pattern to recognize searched variables.

Some problems still exists:

Because the matching is done line by line, when console window is small, and the lines are wrapped, they are not consistent with the written lines from the jasmine reporter anymore. The reported errors are wrapped at the width of the console and pattern matching doesn’t recognize them as errors any more.

You can somehow mitigate that with larger terminal window or with smaller terminal window font. This way the reported errors will remain in single lines consistent with the jasmine reporter. I wish that this wrapping could be disabled but for now it is not an option.

To change the size of the font in the terminal window add this settings to the settings.json file:

Anyway, this problem is already recognized and I hope it will be resolved in the future.

Create a Node cluster with Koa and TypeScript

Cluster

Any JavaScript program runs in single OS process but of course is able to process requests asynchronously.  On the Node server we are able to start multiple processes.  To do that we use cluster module, so you are not really limited to one CPU core anymore.

Before start you need to install project prerequisites:

If you need help with basic project setup look at this blog article where I describe basic setup steps.

Create Koa web server application

The purpose of this server application is for testing cluster technology only.  The application support two routes , first is default route (/) for checking on which process runs and another (/stop) for stopping active process. The console log show workers statuses from starting , stopping and restarting.

If you want to debug this server application just create simple index.ts and start the ServerRun class.

Create cluster server start

To start this server in the cluster we need to fork process workers and start koa application.

To start this server we need to compile everything to TypeScript first and then start node with “run_cluster” procedure.

As we see on the console the server start multiple processes and listen on the same port. Well, that’s whole point, to be able to send requests to the same address and server will divide load to multiple processes.

Test the server

Now if you go to browser and navigate to “localhost:3002/”, the server will respond with value of the current process id and count variable. Try refreshing multiple times, the counter will always increase by 1. If you then kill the process and navigate again, you will get another process id and the counter will start again with one. Each process has his own Koa application instance.

Kill the process and test server robustness

If you navigate to “localhost:3002/stop”, you will essentially kill current process. After irrecoverable failure on the server process,  cluster “exit” event is triggered and we simply start new process again.

 

 

Asynchronous programming with async/await pattern

JavaScript is single threaded

Everything running in JavaScript is running in the single OS process and consume a single thread. But when you are waiting for something outside the JavaScript process to happen, like waiting for database query to be executed or some file stream reader to load a file, you are able to return control back to your main JavaScript event loop and therefore any new event/request in your JavaScript program will be processed in the meantime.

It means your JavaScript program, if written properly, will never really waiting. It just runs all the time.

Async/Await pattern

Returning control to JavaScript event loop when waiting something outside JavaScript to happen,  is not automatic. You need to specify this manually in code with proper use of “Promise” objects and async/await functionality.

Sometimes the promise object is implicitly defined by “async” keyword in front of the function but on the end you always work with the promises.

Using asynchronous programming with TypeScript

To learn how to properly use promises and async/await in typescript I create a very small web application.

Create minimal server app

For this mini app I use Koa server. The app will support two routes: “/” and “/start”.  With “start” I will start long running operation and with “/” route I will check if server is still available and responsive.

Prepare project for sample code

 

After running the sample (index.ts) node application we should be able to start long running task with navigating to “localhost:3002/start” address and in the same time check if the same server is still active and responsive with default route “localhost:3002” which show new value of the counter after each refresh.

Long running task will not always succeed, only when random value is higher then 500 will. If value is lower then the error is thrown and implemented error handling intercept it with try/catch block.

Code for this sample app:

As we see the code looks more or less like ordinary synchronously written one except async keyword used in function declaration and await keyword where asynchronous methods are called.

Promise

If function is marked as async then the function will automatically return promise object. If function doesn’t have return statement, then this promise will be void (Promise<void>). If you write return with some real value, then promise will represent that value. Function will automatically wrap your value and return promise with it. Returning a value from async function means resolving the promise. If you throw exception from async function means your promise will be rejected.

Writing promise by hand

If you use async functions what’s really behind is actually exactly the same as when you work with promises directly, just syntactically is more synchronous looking and much more readable.

Working with multiple async functions in parallel

If you need to execute more then one function in parallel, you need to use Promise.all( [ array of promises] ).

The parallel call is made in the line :

Await in “parallel()” function will be called back after all promises will be resolved. The longest operation in array of promises define the maximum time spend here.