How To Easily Mock Moment.js In Jest

Recently whilst writing some unit tests in Jest, I had to test some code that took ISO date strings and converted them to formatted date strings, then code that converts them back to ISO strings before it’s sent to the server.

My first attempt was to use jest.mock and mock each individual method. For some of the uses of moment where simple dates are being converted, it is easy enough to mock format and other methods, but once you start chaining Moment methods, things get tricky from a mocking perspective.

This is some code that would be a nightmare to mock in Jest:

moment.utc().add('1', 'years').format('YYYY')

It turns out there is a much easier way to “mock” moment, without actually mocking it at all. You get a fully functional (well in my use case) version of Moment that actually converts dates and allows you to use chaining features.

jest.mock('moment', () => {
  const moment = jest.requireActual('moment');

  return {default: moment };
});

You use the jest.requireActual method to require the real Moment package, then you return it inside of an object. I am having to return it with default because moment is being included in my application like this:

import moment from 'moment';

It’s a surprisingly simple, functional and elegant solution. It requires no absurd nested mock functions and code. If for whatever reason you need to override certain Moment methods, you can do so either inside of the mock declaration or on a per-use basis.

Fixing The Webpack File Loader [object Module] Issue

Recently I updated to the latest version at the time of writing this post 5.0.2 of the file-loader plugin for Webpack. I use this for dealing with some image files in my project amongst other things.

To my surprise after updating, I noticed my SVG images had all broken without explanation. It turns out a recent fix to the esModule option had enabled a default value of true for esModule which generates Javascript modules that use ES syntax.

This simple fix had some serious consequences in my application, all of my SVG image elements were showing [object Module] as the source (which clearly is not going to work).

Now, it does not take a genius to see the problem here. If you are dealing with SVG files, this is going to break them. Maybe the file-loader plugin was never intended to be used with SVG images, but I and many others do, so it is a bit of a problem.

To cut a long story short, the fix is to set esModule to false:

{
    test: /\.(ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/i,
    loader: 'file-loader',
    options: {
        esModule: false,
    },
},

This essentially reverts the behaviour back to the way file-loader has always worked, by using CommonJS syntax to resolve back to the default export of the file itself.

GraphQL Is Superior To REST

When it comes to API’s, you traditionally will opt for a RESTful API that returns JSON data. The REST approach has served us well for many years, but as web applications have evolved and grown in complexity, so too, have the needs of what API’s do. Fortunately, the smart folks over at Evil Inc (Facebook) created something called GraphQL, which is one of the best things to happen to APIs since REST.

Instead of defining controllers in your API and making calls to your database via rigid actions, GraphQL allows the client to query for the data using a JSON-like format. It can do reads, writes and updates like a traditional REST api, only you don’t have to bother your backend team to add in new controllers, actions or touch existing ones and potentially break other parts of your application.

The true value in GraphQL is the ability to implement new features or update existing ones on the client-side without requiring anything else. If you have to make some changes to your application, you can do so in a safer manner.

Couple this with the fact that GraphQL requires you to define your schema and type said values in the schema and you know that the type of data you are querying is the type of data that is being returned.

If you opt for a decent server (I highly recommend Apollo Server) some of the painful aspects of GraphQL such as caching and query complexity have been solved and documented for your convenience. Some of the lighter and in my opinion, inferior options for implementing GraphQL on the server-side give it a bad name as they generally do not deal with these problems for you (at least not out-of-the-box).

In my experience, a properly implemented GraphQL solution should be easy to maintain and equally, easy to understand and improve. In all of my uses of GraphQL, I make sure my resolvers are simple and easy to follow. A resolver is just a simple function that returns data and in some instances, one or more arguments for filtering and querying data.

On all of my side-projects, I have moved to GraphQL and I generally host it within a Firebase Cloud Function, with minimal work in my resolvers to communicate with my database and return data. Where I possibly can, I will always opt for GraphQL over REST because it is vastly superior.

As with anything, you should not default to choosing GraphQL for every single use case. As great as GraphQL is, it does introduce a little more complexity into your stack, it requires a little more configuration. For medium to large applications dealing with a lot of data, you will see the true value of GraphQL quite quickly. Small hobbyist projects, perhaps not so much.

My Experiences Using Apollo Client & Server With Blockchain

Some of you might know that I spend my time immersing myself in the latest and greatest technologies and a couple of years ago got active involved in cryptocurrencies and blockchain.

The rise of GraphQL has become too high to ignore. Unlike traditional RESTful API’s, GraphQL uses an expressive query language to allow you to query your server for the pieces of data that you need, leaving the implementation details on the server in resolver functions.

At the start of 2019, I open sourced a GraphQL implementation over the top of the Steem blockchain, specifically a layer on top of the Steem blockchain called Steem Engine. I named the library Steem Engine QL. If you are not aware, the Steem blockchain is a fast blockchain with no fees and 3 second block times. It is perfect for content, decentralised applications and other use cases where you need a fast open source blockchain.

GraphQL is a perfect fit for blockchain

After creating my initial implementation one thing that stood out immediately was how much easier it made querying the blockchain and returning data.

In some instances, I needed to combine data from multiple sources and return it in the one request. On the client-side, this would have taken two API requests, then taking the results, filtering and combining into the final structure. Now, this happens on the server and the API returns everything as one. A good example is the coinPairs type here.

On the front-end, that coinPairs data is fetched like this (the code is located here):

query {
  coinPairs {
    name,
    pegged_token_symbol,
    symbol
  }
}

GraphQL === Fast Feature Iteration

Having used the above GraphQL server implementation in a large-scale open source project one of the biggest benefits is the ability to iterate and implement new features.

Instead of having to write implementation logic on the server to return needed data, once all of the query types and resolvers have been implemented, you just query for what you need. If a REST API were being used, it would require continual development work to add in new endpoints and maintain existing ones.

Because GraphQL promotes typing your resolvers and return types, everything is self-documented, so you know what the server supports and returns data wise. This is an area where REST simply cannot compete, and I am a huge TypeScript fan so it aligns with my code quite nicely.

Case in point, just yesterday in a few short hours of work, an entire new feature was implemented into the codebase without requiring any API work whatsoever. Most of the work was simply just UI, querying the API for the needed pieces of information.

Why Apollo?

I tried a few different GraphQL implementations before settling on Apollo for the server. The thing with Apollo is that the company seems comitted to open source and is well-funded as well. It has great integration with numerous frameworks and libraries, and has sorted out some of the painpoints in GraphQL: namely caching and request batching support using DataLoader.

On the other side of the stack, the Apollo Client library makes querying the Apollo Server a breeze, with support for caching including an in memory cache which does a fantastic job caching your GraphQL queries.

You can find the code for Steem Engine QL here and see it being used in an open-source application here.

Storing The Last Dispatched Action In Aurelia Store

Another day, another Aurelia Store tip/hack. Recently, I encountered an interesting situation where I wanted to know when a specific action has fired, being able to check for it within my state subscriptions.

Now, it is highly likely there is a better way to do this. RxJS is quite magical and has a seemingly bottomless trove of treasures and ways to work with observables and data.

The use case is simple. Inside of my subscriptions, I want to know if a specific action has fired and in some cases, what the parameters for said action were. I decided this was the perfect use case for an Aurelia Store middleware.

function lastCalledActionMiddleware(state: State, originalState: State, settings = {}, action: CallingAction) {
    state.$action = {
        name: action.name,
        params: action.params ?? {}
    };

    return state;
}

This is the middleware function and registration. It sets a property defined in your state called $action which stores the currently fired action passing through the middleware as well as the parameters supplied. I prefix with a $ to make the chances of it being overwritten elsewhere highly unlikely.

When registering the middleware, I only want to know when it has fired. So, I choose to place it after.

this.store.registerMiddleware(lastCalledActionMiddleware, MiddlewarePlacement.After);

As you can see below in Redux Developer Tools, my property is being stored and the parameters supplied to the dispatched action.

If you know of a better way to do this, I would love to hear about it. For my use cases, this works quite well and fine. A middleware seems like the perfect use case for something like this.

Some Small Blog Changes Preempting Aurelia 2

As Aurelia 2 draws near, I have made some changes to my blog. Acknowledging that many of you rely on my blog as a source of information and help with Aurelia 1, I have created an Aurelia 2 category and renamed the existing category to Aurelia 1.

This will hopefully alleviate any confusion that you might have when Aurelia 2 is released. While many of my Aurelia 1 articles will still be relevant, they might not always apply to the new version of Aurelia.

Until Aurelia 2 is released, these changes do not currently mean much. But, after release, they will.

Another change you might have noticed is a new theme. The existing theme served me well for years, but now, it is time to try something newer and still easy to read. I am using the Less theme.

Getting Typescript 3.7 To Work With Webpack and ts-loader

At the time of writing this post, TypeScript 3.7 is in beta. Eventually, this post will become irrelevant. But, for the moment if you are trying to get TypeScript 3.7 Beta or any of the RC builds working with Webpack and ts-loader you might have encountered a bunch of red text in your console.

In my case, I had target: "esnext" set in my tsconfig.json file which the ts-loader plugin should read and set the appropriate settings. And yet, TypeScript 3.7 Beta was not working despite making sure everything was up to date.

It turns out at present, ts-loader does not seem to work with esnext as the target value (hopefully, this changes when TypeScript 3.7 is released). To get things working, all you need to do is change your target value in tsconfig.json to es2018 like this: "target": "es2018"

In my case, that fixed the issue and I could use the exciting new features TypeScript has to offer such as Nullish Coalescing and Optional Chaining. Happy days.

Getting a 404 Error Dealing With File Uploads To Storage In Firebase?

I am a huge proponent of Firebase and interestingly, up until recently, I had never used Firebase Storage. Instead, I usually opt for Amazon’s S3 service which I am familiar with. Wanting to keep everything in the one service is appealing to me, so I started to add in file upload functionality in a Firebase Cloud Function.

It was not as straightforward as I would have hoped. I am using Express with Firebase and the Google Cloud NPM package as documented in code examples and numerous tutorials.

After adding in the @google-cloud/storage package into my Cloud Function file, I plumbed it all in and figured it would work. Then I got this vague error.

{
    "errors": [
        "domain": "global",
        "reason": "notFound",
        "message": "Not Found"
    ]
}

Even with an error message, I was left scratching my head. I had nothing I could really Google, looking through the documentation failed to give me the answer and then out of frustration and trial and error, I discovered the cause.

This is the code that I had setting up my storage object and bucket instance. Tell me if you can spot the problem.

import { Storage } from '@google-cloud/storage';
const storage = new Storage();

const bucket = storage.bucket('steem-engine-dex');

The problem is with the bucket name, I also had to add in the project ID as well.

storage.bucket('steem-engine-dex.appspot.com', {
    userProject: 'steem-engine-dex'
});

The bucket name in Firebase requires adding .appspot.com into the bucket name and sure enough, if you go into Firebase itself and into the Storage section, you’ll notice something that points to this.

The bucket name after the protocol gs:// actually has the bucket name with appspot.com in it. Unless I am blind, nowhere does it mention any of this in the documentation, it really tripped me up.

I wasted a lot of time working this out. So, hopefully, if you have experienced the same issue, this blog post saved you a few hours or days worth of wasted work. Happy coding.

Jest Not Finding Tests In Travis CI? You Might Be Ignoring The Build Folder

Recently, I encountered an issue in Travis CI and my Aurelia application which uses Jest for the tests suite. I erroneously copied some older configuration code for Jest and used it in my Jest configuration, assuming it would work.

This error took a while to isolate and resolve. It was out of pure desperate that I accidentally discovered the fix. If I made the mistake, it is possible that you might as well. Does this sound familiar to you?

Tests were working locally. Running Jest would run my tests and they would all pass, giving a nice 0 code, happy days. Pushing my changes up causing my Travis CI build to automatically run would result in an error. The error looked like the following (this is the actual error):

One thing you will notice is my testRegex is saying there are 3 matches, which is correct. I have three test files which run and work locally without issue. I tried modifying my testRegex I tried changing the location of my tests, nothing worked. Then I noticed I had testPathIgnorePatterns defined in my Jest configuration (part of my older config).

This is my actual code. I was ignoring my build, dist and sample directories from testing. It turns out defining this locally causes no problem, but causes Travis CI to fail. At first, I was confused, why is this breaking Travis CI.

Then it dawned on me. It’s the fact I am using some outdated configuration option, the issue is the path in which tests and code are run inside of the virtualised Travis CI environment.

Can you spot the issue? The path is /home/travis/build/steem-engine-exchange/steem-engine-dex what is contained within this path? A folder named buildwhich is located under /home/travis ignoring build causes this to get matched and thus, it breaks the tests from running.

My innocent ignore rule was being triggered only in Travis CI, not locally because locally my files are run from my home directory and not within a build directory.

Using Wallaby.js With Aurelia, Jest and TypeScript

Wallaby.js is one of the most amazing additions you can make to your testing workflow. I have been a happily paid user for a couple of years now and if you are looking to up your testing game, I highly recommend it.

Chances are if you are reading this post, you already use Wallaby and you are looking to get it working in your Aurelia applications with Jest and TypeScript. It’s a combination that is not all too uncommon these days, TypeScript is the future.

The Wallaby.js configuration itself requires very little code to work out-of-the-box with Aurelia and Jest.

module.exports = function (wallaby) {

  return {
    files: [
      '!**/*.css',
      'src/**/*.ts',
      'src/**/*.html',
      'test/unit/helpers.ts',
      'test/unit/mock-data/**/*.ts',
      'test/unit/stubs/**/*.ts',
      'aurelia_project/environments/**/*.ts',
      'test/jest.setup.ts',
      'tsconfig.json'
    ],

    tests: [
      'test/unit/**/*.spec.ts'
    ],

    compilers: {
      '**/*.ts': wallaby.compilers.typeScript({ module: 'commonjs' })
    },

    env: {
      runner: 'node', 
      type: 'node'
    },

    testFramework: 'jest',

    debug: true
  };
};

The above configuration assumes your files live in src and in my case, inside of my test/unit directory I have a helpers.ts file which has some functions making testing easier, a mock-data directory for mock data to import, a stubs directory for stubbing out certain mocks as well as my main Jest configuration file jest.setup.ts.

Do not copy the above file line-for-line. Make sure it reflects your project and the files inside of it.

In the compilers section we have to tell Wallaby to compile our TypeScript to commonjs format. In my case, I was originally targeting esnext as my module format and Wallaby does not work with modern JS syntax just yet. the rest is fairly explanatory.

Here is what Wallaby looks like running in an application I am currently working on.