How to test Web Workers with Jest

Andrea Stagi

Andrea Stagi

Oct 20, 2020
2 min read
Share on Twitter or LinkedIn

As you could read in Alex's article, Use Web Workers in your Vue.js Components for Max Performance, you can use Web Workers to maximize performance in your Vue.js app instead of running heavy tasks in the main thread which is UI-blocking.

But how can we test Web Workers? Webpack-bundled Web Workers are not supported by Jest so we have to mock the worker in order to test it! Let's see how to do in 3 simple steps, starting from a simple Vue app to calculate the Fibonacci number, where fibonacci function is the heavy task performed by the Web worker (you can follow the code here)

First of all we need to isolate the main functionality of our worker, in this case is really straightforward because it's just our fibonacci function (src/fibonacci.js)

let fibonacci = (num) => {
  if (num <= 1) return 1;
  return fibonacci(num - 1) + fibonacci(num - 2);
}

export default fibonacci

and keep the worker minimal (src/fibonacci.worker.js):

import fibonacci from "./fibonacci";

self.onmessage = async function (e) {
  self.postMessage(fibonacci(e.data));
};

This way we can mock just the Web Worker part of our implementation (src/__mocks__/fibonacci.worker.js)

import fibonacci from "../fibonacci";

export default class fibonacciWorker {
  constructor() {
    // Note that `onmessage` should be overwritten by the code using the worker.
    this.onmessage = () => { };
  }

  postMessage(data) {
    this.onmessage({ data: fibonacci(data) });
  }
}

and easily test the main functionality

import { shallowMount } from '@vue/test-utils'
import App from '@/App.vue'

jest.mock("@/fibonacci.worker")

describe('Fibonacci App.vue', () => {
  it('should calculate Fibonacci number', async () => {
    const wrapper = shallowMount(App)
    await wrapper.find('input').setValue('10')
    await wrapper.find('button').trigger('click')
    expect(wrapper.find('.result').element.innerHTML).toBe('Result: 89')
  })
})

I created workerloader-jest-transformer to generalize this solution so that all workers are mocked at once. This Jest transformer helps you to test Web Workers loaded with Webpack worker-loader module in Jest. It's easy to use, install it with

yarn add workerloader-jest-transformer --dev

and add the tranformation rule to your Jest configuration:

transform: {
  "^.+\\.worker.[t|j]sx?$": "workerloader-jest-transformer"
}

This transformer is inspired by jsdom-worker and implements Web Worker API for JSDOM, so you can remove any mocking code as you can see here.

Workerloader-jest-transformer is highly experimental and code is available on Github, any contribution and advice would be greatly appreciated!

Don't miss out anything about Vue, your favourite framework.

Subscribe to receive all the articles we publish in a concise format, perfect for busy devs.

Related Articles

How to use the new Fetch in Nuxt.js

The Nuxt team is on fire, releasing new stuff every week! In this tip Samuel shows you a feature that might've gone unnoticed... till now.

Samuel Snopko

Samuel Snopko

Sep 7, 2020

Generate and deploy the blog as a full static Nuxt site

Your site is ready for the world. Wait, where and how do I publish it? You only need 5 minutes to learn how to deploy a Nuxt.js site in Netlify.

Alex Jover Morales

Alex Jover Morales

Aug 25, 2020

Optimize SEO and Social Media Sharing in a Nuxt blog

Do you want your blog to reach an audience? Then you should have SEO in your mind. Learn two techniques you can easily apply to your Nuxt blog.

Alex Jover Morales

Alex Jover Morales

Aug 18, 2020

Sponsors

VueDose is proudly supported by its sponsors. If you enjoy it, consider supporting it to ensure the project maintainability.

Silver
Learning Partner