Total results: 29

How to stub Date in Jest tests: building a `stubDate` helper

tl;dr: the stubDate helper can be copied from the bottom of the article.

It is a common case in unit testing to need a static date returned in your tests so that you can either have a fixed expectations (e.g. in a JSON), or to prevent random failures when tests are executed seconds later than when the expectations where made.

For this reason, if you are using Jest, you want to stub the Date object inside your Jest tests so that when calling new Date() or Date.now() aways returns the same result.

Jest does not provide a built in method for stubbing the JavaScript Date object so we have to do this manually. This can be done by overriding the global Date object.

const fixedDate = new Date('2018-02-28T09:39:59');

Date = class extends Date {
  constructor() {
    super();

    return fixedDate;
  }
};

This is enough to get a test passing, which will always return the time "2018-02-28 09:39:59", regardless which Date methods are called. For example, calling getTime() on the date instance will always return "1519807199000".

beforeAll and afterAll

Since we are using Jest we can use the beforeAll function to set the date before all tests in a test file, so that this code does not have to be copied into each test case.

const fixedDate = new Date('2018-02-28T09:39:59');

beforeAll(() => {
  Date = class extends Date {
    constructor() {
      super();

      return fixedDate;
    }
  };
});

It is also important to reset Date back to the original "real" Date object after all tests have run to prevent confusing errors in future tests where you expect to work with a non-stubbed date. We can do this with a Jest afterAll function. This means we have to cache the original Date object in the beforeAll.

const fixedDate = new Date('2018-02-28T09:39:59');
let _originalDate;

beforeAll(() => {
  _originalDate = Date;

  Date = class extends Date {
    constructor() {
      super();

      return constantDate;
    }
  };
});

afterAll(() => {
  Date = _originalDate;
});

stubDate helper

Finally we can piece this all together into a handy stubDate helper than can be imported into any test file, leaving the test implementation clean of the stubbing boilerplate code. I usually use a file called test-helper.js where helper functions like this live.

// test-helper.js

export const stubDate = fixedDate => {
  let _originalDate;

  beforeAll(() => {
    _originalDate = Date;

    Date = class extends Date {
      constructor() {
        super();

        return fixedDate;
      }
    };
  });

  afterAll(() => {
    Date = _originalDate;
  });
};

This can then be imported into a test file and the before and after actions will automatically be applied to your tests. For example:

// my-spec.js

import { stubDate } from './test-helper';

it('can stub the global date object', () => {
  const myDate = new Date('2018-02-28T09:39:59');

  stubDate(myDate);

  // This expectation will always pass regardless of what time the test is run
  expect(Date.now()).toEqual(1519807199000);
});

Building a PDF Library with Gatsby.js

Like most developers I have large libraries of PDF books lying around in a folder somewhere. In order to organise the books and get a better overview I decided to work on a weekend project designed to investigate Gatsby.js, a React / GraphQL based static site generator. The project was to use Gatsby to build a PDF library that would allow me to put my PDF books into the project and then build a simple static website that would list the PDFs, give some information about each book, allow me to read them online, and finally download them if I wanted.

Demo

My static Gatsby based PDF library ended up with the following features:

  • List view of PDF books, read from the file system
  • Metadata extraction from the PDF book (Author, Page count, etc.)
  • Read a book online
  • "Fullscreen" reading mode
  • Download a book
  • Remember your page number, for future reading
  • Search for books

You can see a demo of the Library here: https://blakesimpson.github.io/gatsby-library/

What is Gatsby?

Gatsby

As mentioned in the introduction, Gatsby.js is a static site generator built with JavaScript. Gatsby uses React for building the views and a GraphQL API that is queried from your views to read information about your static files.

This means you can add, for example, a bunch of Markdown files to your project and Gatsby will run through each file (what it calls a "node") to index these and put them into the GraphQL index. You can then build a list of your Markdown articles to the home page and link to each one and render it as a web page.

With this setup, Gatsby is very good for building static websites that do not rely on a database at runtime, for example, a blog.

However, Gatsby can not only read Markdown files from your system, it can read any file type such as an Excel spreadsheet, or as I discovered, a PDF.

Before going on to show how I extracted PDF information and put it into the Gatsby index you might want to try out some Gatsby starter examples such as the gatsby-blog.

Also, if you have never worked with Gatsby before, it is a good idea to work through the tutorial which helps to understand the Gatsby concepts such as configuration, the node server, and how the plugins work.

Writing a local IP proxy with node.js

I recently had the issue where I needed to proxy traffic from my IP address to a different server, in order to perform mobile testing. The setup I have is a "local" server running on my development machine with a local hostname, since my phone can not access this hostname, I decided to use a proxy that allows me to visit the IP address of my development machine on my phone and all traffic would forward to the local domain.

I decided to use Express.JS as it is an easy to use server. Express also has large amount of community contributed middlewares, such as express-http-proxy which fills all of my requirements.

Additionally I use the package "ip" that will discover the local IP address of my development machine.

These dependencies can be installed with:

yarn add express express-http-proxy ip

The proxy server is quite small, and looks as follows:

Serving static files with Server.js

Update 14/03/2018:

Thanks to a pull request to my example repository by Francisco Presencia, the creator of Server.js, he explains that my original example can actually be cut down to a single line of code.

Server.js already contains the static middleware from Express so there is no need to include and configure the server manually. Server.js assumes that you want to serve static files from a directory called public/ in your project, in which case you can simply create the server as:

require('server')();

If you would like to serve the static files from a different directory, such as the root directory, as in my case you can simply pass a public configuration option when initializing the server. For example:

require('server')({ public: '.' });

This highlights how Server.js is even simpler to use than I assumed.


Server.js is a node based server that is based on Express.js but provides you with an even easier interface to write your server with.

As server.js was only recently released, I was trying to find a tutorial on how to serve a directory of static files but could not find one. After reading the documentation, I noticed that since Server.js is built on express, you can use express middlewares out of the box. Since Express already has a express.static() method, I noitced that I could use this to serve static files as I wanted.

The example server is very basic, it simply serves all files in the current directory.

First of all, I import server and express:

const server = require('server');
const express = require('express');

Next I import the modern method from server.utils that allows us to attach Express middleware to our server:

const { modern } = server.utils;

I then call the express.static middleware, and pass it to modern:

const middleware = modern(express.static('./'));

Finally, I start the server and pass the static middleware:

server(middleware);

The final server is only 7 lines long:

const server = require('server');
const express = require('express');
const { modern } = server.utils;

const middleware = modern(express.static('./'));

server(middleware);

You can test this by writing this to a file called server.js and calling it with node server.js. The server will then be running at: http://localhost:3000/.

If you then write an index.html file in the same directory, it will be served when visiting this address in your browser.

For full example code, please visit this repo: https://github.com/BlakeSimpson/serverjs-static-files

Sorting a German date format in Tablesorter.js

The German date format is 01.05.2015 as opposed to the UK date format 01/05/2015 which Tablesorter.js comes prebuilt to parse.

To sort by a German date, you have to add a custom parser. Here is one that will work for a date with the German dot notation.

$.tablesorter.addParser({
  id: 'dotDate',
  is: function (content) {
    return /\d{1,2}\.\d{1,2}\.\d{1,4}/.test(content);
  },
  format: function (content) {
    content = content.replace(/\-/|:|\.|\//g,' ').split(' ');
    return $.tablesorter.formatFloat(new Date(content[2], content[1]-1, content[0]).getTime());
  },
  type: 'numeric'
});

Simply add this parser and then tell your tablesorter initializer function which column the German date is in.

$('table').tablesorter({
  headers: {
    0: { sorter: 'dotDate' }
  }
});

If your date only has 2 numbers for the year instead of 4, you can adjust the is method to use the regex /\d{1,2}\.\d{1,2}\.\d{1,2}/.

Detect Internet Explorer 10 without conditional comments

Commonly to target specific versions of Internet Explorer we will use conditional HTML comments to apply a specific class name to the <html> tag. With this approach it is then trivial to target a specific browser via CSS for special styling. For example:

<!--[if IE 8]> <html class="ie8"> <![endif]-->

Since Internet Explorer conditional comments have been disabled since IE10, we can no longer use the following syntax.

<!--[if IE 10]> <html class="ie10"> <![endif]-->

JavaScript to the rescue

In order not to break from the pattern of HTML specific class names for IE versioning, a JavaScript can be used to manually add a class targeting IE10.

if (navigator.userAgent.match('MSIE 10.0;')) {
  $('html').addClass('ie10');
}

Or in pure JavaScript, if you do not have jQuery available.

if (navigator.userAgent.match('MSIE 10.0;')) {
  document.querySelector('html').className += " ie10"
}

This is not the ideal approach. In general feature detection is a better method to tell if a feature is available but when looking to target Internet Explorer purely for CSS styling purposes this may be the most pragmatic approach.

A simple jQuery add/remove class name pattern

Often when using jQuery and you aim to add or remove a class based on a state variable, you will see a function such as.

function updateInterface () {
    var shouldShowLogout = user.isLoggedIn;

    if (shouldShowLogout)
        $('.logout-button').addClass('active');
    } else {
        $('.logout-button').removeClass('active');
    }
 } 

This function is hard to read and basically repeats itself in the if and else clauses. The function implementation can be refactored down to 2 lines using a ternary if operator.

function updateInterface () {
    var shouldShowLogout = user.isLoggedIn;
    $('.logout-button')[ shouldShowLogout ? 'addClass' : 'removeClass' ]('active');
}

Since you can access functions of a an object in JavaScript like values, you can use the [] accessor to return the correct function based on the ternary if statement and them immediately call it using (), or in this case passing our class name value ('active').

You could even take this down to a single line.

function updateInterface () {
    $('.logout-button')[ user.isLoggedIn ? 'addClass' : 'removeClass' ]('active');
}

Although this final single line approach may be confusing to the next developer who is not already familiar with the pattern.

Ember Server "Bus Error 10" Fix

If you are using the ember-cli package to access the ember command line tool and experience a "Bus Error 10" that crashes the ember server every time you save a file then it is probably due to an incompatible Node.js version.

To fix this issue simply head to the Node.js downloads page and get the latest version of Node for your operating system.

For a functional ember server you should be using Node.js version 0.10.21 or higher, personally I upgraded from 0.10.20 to 0.10.29 and now the server runs perfectly, including the live reload functionality.

JavaScript Beacon API Explained

Beacons are a new API that is being experimentally introduced by browser vendors that will allow an XHR call to be made to a server when a webpage unloads without blocking the thread in order to create a better user experience. Quoting the W3C Beacon Specification.

"analytics and diagnostics code will typically make a synchronous XMLHttpRequest in an unload or beforeunload handler to submit the data. The synchronous XMLHttpRequest forces the User Agent to delay unloading the document, and makes the next navigation appear to be slower. There is nothing the next page can do to avoid this perception of poor page load performance."

This specification will prevent developers from having to use tricks and hacks to bend the rules of the browser, creating a better experience for everyone.

© Blake Simpson, 2012 – 2018