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!
Top comments (0)