jsdom-worker icon indicating copy to clipboard operation
jsdom-worker copied to clipboard

Testing Worker in Jest

Open astagi opened this issue 5 years ago • 2 comments

Hi,

I'm trying to test my worker inside a Vue.js project. I load the worker inside my component using the worker-plugin (I also tried loading my Worker using Webpack worker-loader, unfortunately it doesn't provide a compatible interface and I had to mock the worker in that case)

const worker = new Worker('@/utils.worker.js', { type: 'module' });

But when I run my tests with Jest I get

console.error node_modules/jsdom-worker/dist/jsdom-worker.js:1
  TypeError: Only absolute URLs are supported
  ...

astagi avatar Aug 24 '20 13:08 astagi

I’m running into this issue as well with:

const worker = new Worker(new URL('../utils/worker.ts', import.meta.url))

Here, in a development environment, the call to new URL('…', import.meta.url) resolves to a URL with a file: scheme which doesn’t work (supposedly because the scheme needs to be either either http: or https:).

Mocking the worker is possibly an option, but I think I can’t turn my worker file into a module because Firefox doesn’t support it, yet (see bug https://bugzilla.mozilla.org/show_bug.cgi?id=1247687; for what it’s worth, this seems to very much be in active development). I’m not sure how to proceed now.

kleinfreund avatar Oct 04 '22 10:10 kleinfreund

I’m now experimenting with a createWorker utility function which I use in my code instead of calling new Worker directly. This workaround is pretty unsatisfying because a lot of my application’s code ends up using this and so I would need to mock the createWorker utility in each of them.

createWorker.ts:

export function createWorker(url, onMessageHandler) {
  const worker = new Worker(url)

  worker.onmessage = onMessageHandler

  return worker
}

In my test:

jest.mock('@/utils/createWorker', () => {
  const { readFileSync } = require('fs')
  const { resolve } = require('path')
  const code = readFileSync(resolve(__dirname, '../utils/worker.js'), 'utf8')
  const workerUrl = URL.createObjectURL(new global.Blob([code]))

  return {
    __esModule: true,
    createWorker(_url, onMessageHandler) {
      const worker = new global.Worker(workerUrl)

      worker.onmessage = onMessageHandler

      return worker
    },
  }
})

kleinfreund avatar Oct 05 '22 07:10 kleinfreund