Expect a function to throw an exception in Jest

Unit testing functions in JavaScript using Jest sometimes requires checking if an exception was thrown, or testing the specific type of exception thrown.

Suppose we want to test the following function using Node.js and assert that it indeed throws an error:

func.js:

const func = () => {
  throw new Error('my error')
}

module.exports = func

func.test.js:

const func = require('./func')

describe('exception test', () => {
  it('should throw an error', () => {
    expect(func).toThrow()
  })
})

Note that func should not be called within the expect; calling the function will cause the error to be thrown unexpectedly.

We can also assert that an error is not thrown using:

expect(func).not.toThrow()

If we need to assert the specific name of the thrown error, we can use the following form:

it('should throw an error', () => {
  expect(func).toThrowError('my error')
})

If no exceptions are thrown, Jest will report:

Expected the function to throw an error. 
But it didn't throw anything.
Expecting Async Functions to Throw Exceptions

 

Writing a unit test to expect an async function to throw an exception can be done as follows. First we define the async function in a module, then in the test code we use the rejects property to test for any thrown errors. Essentially, we are asserting that our function causes a promise rejection.

async-func.js:

const func = async () => {
  throw new Error('my error')
} 

module.exports = func

async-func.test.js:

const func = require('./async-func.js')

describe('exception test', () => {
  it('should throw an error', async () => {
    await expect(func()).rejects.toThrow()
  })
})

Note that the function passed to it() is async itself so that we can use await inside.

Note also that func is called inside expect in this case; this will cause a promise rejection which can then be tested within the rejects property.

The case of testing for a specific error to be thrown inside the async function is similar and looks like this:

it('should throw an error', async () => { 
  await expect(func()).rejects.toThrowError('my error')
})
Expect a Function with Parameters to Throw an Exception

If we want to expect a function to throw an exception for certain input parameters, the key point is that we must pass in a function definition and not call our function inside the expect. The code is below for an example of a function which should throw an exception for negative integer inputs:

func.js:

const func = (n) => {
  if (n < 0) {
    throw new Error("negative input")
  }
  return n
}

module.exports = func

func.spec.js:

const func = require('./func.js')

describe('exception test', () => {
  it('should throw an exception', () => {
    expect(
    () => func(-1) // Do not simply call func
    ).toThrow()
  })
})

We pass an anonymous function to expect, which will throw for the input. Expect can then determine that this function will throw.

Running a Single Test Only Using Jest

Jest provides a convenient way to run only one unit test at a time.

First, run only the single test file which contains the single test to run, similar to the following:

jest my-test-suite.spec.js

The single test in the suite that we wish to run should be changed to use it.only() as in the example below:

describe('My test suite', () => {
  it('should meet condition 1', () => {
    expect(condition1).toEqual(true)
  })

  it.only('should meet condition 2', () => {
    expect(condition2).toEqual(true)
  })

  it('should meet condition 3', () => {
    expect(condition3).toEqual(true)
  })
})

Jest will run only the second test, and will show the others as skipped.

Note that it.only() can be used multiple times in the file, so that we can run only two or only several jest tests as desired.

Another way to run several tests only is to select the tests that should not be run, and use it.skip() for these. The specific tests only will be skipped.

There is also a way to run a single test suite at a time inside a file, which is handy for running a group of related tests: describe.only().

Convenient Ways to Print Out Entire Objects in JavaScript

Quick debugging in JavaScript often requires one to print out or log a full object to see what values it contains.

The usual console log can often print “[Object object]”, which is not useful.

Some convenient ways to see the entire object in logs are below.

Using the %o format specifier, which means “formatted as an object”:

console.log("%o", myObject)

Using the dir function:

console.dir(myObject)

The “dir” in console.dir() comes from “directory”, as in a directory of all the properties of the object. This always outputs a full hierarchical representation of the object.

Another way is to fully serialize the object into a JSON string:

console.log(JSON.stringify(myObject))

This is very useful especially in the context of loggers, so if logger is an instance of a logging object (such as a Winston logger), then we can log a complete JSON object using:

logger.info(JSON.stringify(myObject))

The Fields Pattern in REST API Design

The Fields Pattern or Field Selection Pattern for REST API design is a useful approach whenever the representations returned from the API become quite large and the API can be used by many clients in different contexts. For example, a native app client may only require a select few fields from the usual resource representation.

Suppose we have a resource employees, with employee representations containing a large number of fields. With the fields pattern, a client could make a request of the form:

GET /employees?fields=name,role,salary

The API will respond to this request with only these fields in addition to id:

{
   "id": "12345",
   "name": "John Smith",
   "role": "Developer",
   "salary": "100,000K"
}

A different client can request a different selection of fields:

GET /employees?fields=projectId,address
{
   "id": "12345",
   "projectId": "6789",
   "address": {
      "streetName": "REST Avenue",
      "postalCode": "J6V 9M2",
      "city": "Toronto"
   }
}

It is also possible to omit the id field, though arguably a resource representation should always have its primary identifier present, even when selecting fields.

If the fields parameter is omitted, the API responds with all fields of the employee resource available.

What if we want to be able to select fields of sub-objects, such as the address object? There are several options, for example:

GET /employees?fields=address:city

GET /employees?fields=address.city

GET /employees?addressFields=city

However, none of these are fully satisfying and venture into inventing syntax. Almost certainly, no two API designs will select the same syntax, and so none of these are ideal for a natural, simple design.

Selection of fields on arbitrarily complex objects is one of the many elegant, standard solutions provided by GraphQL, so a GraphQL API design may be preferable in cases where complex multi-level field selection is desired.

apiVersion field missing error in OpenShift

If you are running into the following error message in OpenShift when processing a YAML template:

error: unable to get type info from the object “*unstructured.Unstructured”: Object ‘apiVersion’ is missing in ‘object has no apiVersion field’

The cause is a problem with the apiVersion field in the template — even if it is present; the error message is misleading.

  ...
-kind: ImageStream
  apiVersion: 1 # Incorrect, must be v1
  metadata: 
    ....

The apiVersion value must be v1 instead of 1.

 

bash Version Differences in Mac OS X

Beware of differences in Mac OS shell commands executed by /bin/bash and /bin/sh.

These are not the same shell, despite the version output (example on Mac OS High Sierra). The version output is identical as shown below:

>/bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
Copyright (C) 2007 Free Software Foundation, Inc.
>/bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)

Yet, the behaviour of these two binaries differs, for example in the echo command:

>/bin/sh
sh-3.2$ echo -n "test"
-n test
sh-3.2$
>/bin/bash
bash-3.2$ echo -n "test"
testbash-3.2$

Note that echo in /bin/sh does not recognize “-n” and simply outputs the string, while /bin/bash recognizes the switch to mean omit newline.

Recursive Anonymous Functions in JavaScript

It is possible to create recursive anonymous functions in JavaScript.

Usually we need a name for a function to recursively refer to itself, but since anonymous functions have no name, JavaScript provides arguments.callee as a way to refer to the function that called the function we are currently executing!

First, here is a regular factorial function using its name to refer to itself:

var fact = function(n) {
  if (n === 0) {
    return 1;
  } else {
    return n * (fact(n - 1));
  }
}

We can replace that name reference with arguments.callee:

var fact = function(n) {
  if (n === 0) {
    return 1;
  } else {
    return n * (arguments.callee(n - 1));
  }
}

In this way, we can use recursive functions without ever giving them a name!

In the following code we print out the factorial of 5 computed with an anonymous function, never giving it a name:

console.log(
  (function(n) {
    if (n === 0) {
      return 1;
    } else {
      return n * (arguments.callee(n - 1));
    }
  })(5)
);

See these important notes about this feature of JavaScript:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee

GraphQL Terminology

The following is a glossary of common terms and definitions used in GraphQL.

Fragment

A group of fields specified together (on the client) which can be used in many places in one query or in several queries. For example: name, ID and address could be grouped together in a fragment called EmployeeInfo, and this fragment can be used to request this group of fields in several places in a query.

Inline Fragment

Inline Fragments are elements of queries used to request fields of a Union Type or an Interface Type. Suppose we have a type Thing which is a union of Book and Car – if we want to query a list of Things, we might want to get titles for books and brands for cars, which are fields that only make sense for these individual types respectively. So with inline fragments we can write something like this:
{  
   allThings {
      ... on Book {
         title 
      }
      ... on Car {
         brand
      }
}

Root Type

Root types are GraphQL types which allow us to reach all the other types: they are the starting points for queries and appear as the entry points to explore from in the GraphiQL explorer. There are three root types: Query, Mutation, Subscription. For example, we can reach all of the specific query types possible from the root type called Query.

Union Type

A union type or simply union in GraphQL is a type made up of several other types. For example, we can define a type Pet to be a union of Cat and Dog. This would mean that Pet type objects can be either Cat or Dog objects, with potentially different fields. The syntax is:

union Pet = Cat | Dog

 

Indicating deprecation of a field in a GraphQL Schema

The GraphQL Schema Language provides a very handy feature to indicate that a field has been deprecated. This will show as a prominent text box on auto-complete in the query builder in GraphiQL, as well as in the documentation explorer. This is a great way to indicate to developers using your GraphQL API that code using a field should  ideally be changed. The reason for deprecation can be included as an annotation right in the schema itself!

In the following schema, we have indicated that the field topic is deprecated for the Book type:

type Book {
   id: Int!,
   title: String,
   topic: String @deprecated (reason: "Field is no longer needed")
}

When we explore the schema with GraphiQL, the deprecation message will display when viewing the field.

The best way to install the latest Node.js on Ubuntu

There are many ways to install Node, but for the latest version you cannot use apt install or apt-get install.

The best way is to use the Node Version Manager (nvm) to install Node.

Note that there is no Ubuntu package for nvm and nvm is not a regular binary, but rather a shell function.

Note also that nvm is not meant to be used with sudo ! The install will be for your current regular user.

Before installing: make sure to have a .bash_profile file in your home directory.

The following steps will install nvm and node (and hence npm).

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash

Reload your terminal.

Find the latest version listed by the following command:

nvm ls-remote

At the time of writing the latest was 9.5.0, so:

nvm install 9.5.0

nvm use 9.5.0

Check that the latest versions of node and npm are ready:

node -v

npm -v