Code Monkey home page Code Monkey logo

jsdom-worker's Introduction

jsdom-worker

Lets you use Web Workers in Jest!

This is an experimental implementation of the Web Worker API (specifically Dedicated Worker) for JSDOM.

It does not currently do any real threading, rather it implements the Worker interface but all work is done in the current thread. jsdom-worker runs wherever JSDOM runs, and does not require Node.

It supports both "inline" (created via Blob) and standard (loaded via URL) workers.

Hot Take: this module likely works in the browser, where it could act as a simple inline worker "poorlyfill".

npm travis

Why?

Jest uses a JSDOM environment by default, which means it doesn't support Workers. This means it is impossible to test code that requires both NodeJS functionality and Web Workers. jsdom-worker implements enough of the Worker spec that it is now possible to do so.

Installation

npm i jsdom-worker

Example

import 'jsdom-global/register';
import 'jsdom-worker';

let code = `onmessage = e => postMessage(e.data*2)`;
let worker = new Worker(URL.createObjectURL(new Blob([code])));
worker.onmessage = console.log;
worker.postMessage(5); // 10

Usage with Jest

For single tests, simply add import 'jsdom-worker' to your module.

Otherwise, add it via the setupFiles Jest config option:

{
  "setupFiles": [
    "jsdom-worker"
  ]
}

License

MIT License

jsdom-worker's People

Contributors

developit avatar g07cha avatar msftenhanceprovenance avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jsdom-worker's Issues

Release New Version

👋 Thanks for the great library!

It looks like support for importScripts was added in: #2 However it looks like a release hasn't happened since then. Would is be possible to get a new release so I can use this?

Issues when running jest with coverage for all packages within a lerna monorepo

I am not 100% sure if my problem really is jsdom-worker related but I guess here is my best starting point:

I am currently working on a lerna monorepo where one of the packages executes a function in a worker. I therefore included jsdom-worker in the corresponding test for this package. The function is an export from a different file of this package. I had to add /* istanbul ignore file */ to it because otherwise the coverage would fail due to cov_* variables added during testing not being reachable for the worker. Jest is used for testing and coverage.

So far this would be OK - and tests as well as coverage run just fine when run localy from within the package.

But if I do run the coverage from the root directory it always fails with ReferenceError: cov_2j8vgqrgle is not defined in node_modules/jsdom-worker/src/index.js:89:18.

The function that is run in the worker has a function imported from another package of the monorepo and if I do run global coverage (remember: running coverage from within the package is 100% fine) this one seems to be interpreted and cov_* gets added to it which is guaranteed to fail.

Any idea what goes wrong and if there is anything I can do about it?

test double for importScripts

I came across a scenario that I actually would like to load a script to test my code, here goes the snippet:

importScripts('https://unpkg.com/[email protected]/fmt2json.min.js'); // this is a library to format json that I actually wanted to have loaded

onmessage = async (e) => {
  const value = e.data.jsonAsString;
  const spacing = e.data.spacing;

  if (value) {
    const format = await fmt2json(value, { 
      expand: true,
      escape: false,
      indent: spacing
    });
  
    try {
      JSON.parse(value);
    } catch (e) {
      postMessage({ error: true, originalJson: value, result: format.result });
      return;
    }
    
    postMessage({ error: false, originalJson: value, result: format.result });
    return;
  }
  // empty json was given
  postMessage({ error: false, originalJson: value, result: value });

Given #2 importScripts is just a random function that does nothing?

In that case how can I at least intercept the call to importScripts and return the functionally I want to? (Same as jest.mock does)

Error when running with jest

console.error node_modules/jsdom-worker/dist/jsdom-inline-worker.js:1
    Error: only absolute urls are supported
        at /Users/aaronvasquez/Oyster/webnode/directories/node_modules/node-fetch/index.js:54:10
        at new Promise (<anonymous>)
        at new Fetch (/Users/aaronvasquez/Oyster/webnode/directories/node_modules/node-fetch/index.js:49:9)
        at Fetch (/Users/aaronvasquez/Oyster/webnode/directories/node_modules/node-fetch/index.js:37:10)
        at Object.<anonymous>.global.fetch (/Users/aaronvasquez/Oyster/webnode/directories/node_modules/jsdom-worker/dist/jsdom-inline-worker.js:1:876)
        at new Worker (/Users/aaronvasquez/Oyster/webnode/directories/node_modules/jsdom-worker/dist/jsdom-inline-worker.js:1:1780)
        at /Users/aaronvasquez/Oyster/webnode/directories/src/utils/bg-worker/index.js:12:29
        at new Promise (<anonymous>)
        at performTask (/Users/aaronvasquez/Oyster/webnode/directories/src/utils/bg-worker/index.js:11:5)
        at Object.<anonymous> (/Users/aaronvasquez/Oyster/webnode/directories/src/utils/bg-worker/bg-worker.test.js:9:29)
        at resolve (/Users/aaronvasquez/Oyster/webnode/directories/node_modules/jest-jasmine2/build/queueRunner.js:38:12)
        at new Promise (<anonymous>)
        at mapper (/Users/aaronvasquez/Oyster/webnode/directories/node_modules/jest-jasmine2/build/queueRunner.js:31:21)
        at Promise.resolve.then.el (/Users/aaronvasquez/Oyster/webnode/directories/node_modules/p-map/index.js:46:16)
        at <anonymous>
        at process._tickCallback (internal/process/next_tick.js:188:7)

This is what I have in my test file:

import "jsdom-worker";

ReferenceError: cov_2a33nrkdo3 is not defined

 console.error
    ReferenceError: cov_2a33nrkdo3 is not defined
        at parseArgs (eval at <anonymous> (/Users/leonardorick/Documents/git/others/utils/javascript/node_modules/jsdom-worker/src/index.js:130:6), <anonymous>:9:3)
        at Object.eval (eval at <anonymous> (/Users/leonardorick/Documents/git/others/utils/javascript/node_modules/jsdom-worker/src/index.js:130:6), <anonymous>:6:23)
        at /Users/leonardorick/Documents/git/others/utils/javascript/node_modules/jsdom-worker/src/index.js:139:2

to reproduce you can go to my repo and run the tests as

npm run test -- --coverage

The error only appear when I try to run the tests with coverage enabled and it looks really like an internal thing breaking that I couldn't understand the relation with the coverage flag

Cannot import jsdom-worker with --experimental-vm-modules

In order to be allowed to use import.meta.url in my jest tests, I turned on the option --experimental-vm-modules. But thereby I cannot import jsdom-worker anymore.

I have the following stack trace:

FAIL  src/anonymized-path/anonymized.test.tsx
  ● Test suite failed to run
                                                                                                                                                              
    Must use import to load ES Module: C:\anonymized-path\anonymized\node_modules\node-fetch\src\index.js

      4 | import { enableFetchMocks } from 'jest-fetch-mock';
      5 | import { readFileSync, readdirSync } from 'fs';
    > 6 | import 'jsdom-worker';
        | ^
      7 | import { getPathFromPublic } from 'utils/helpers';
      8 |
      9 | /* Wasm jest problems - the function locate file returns C:\ instead of localhost when testing with jest

      at Runtime.requireModule (node_modules/jest-runtime/build/index.js:972:21)
      at Object.<anonymous> (node_modules/jsdom-worker/dist/jsdom-worker.js:1:89)
      at Object.<anonymous> (src/setupTests.ts:6:1)

Would you have insight how to solve this issue?

$ node -v
v17.9.1
$ npm -v
8.11.0

Less invasive handling of unsupported methods

Very helpful library, thanks for creating and maintaining it!

I've recently tried using jsdom-worker to test React components using useWorker hook and discovered that it uses worker.terminate() in certain cases which causes an error and stops tests. I wasn't able to find a way to circumvent this through useWorker hook so was wondering if it's possible to make error when terminate method is used less invasive? For example using console.warn or console.error instead?

Testing Worker in Jest

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
  ...

TypeError: Network request failed when using in jest tests from React app

PROBLEM: inline workers do not seem to work in a jest-test. When running tests the following error occurs:

console.error node_modules/jsdom-worker/dist/jsdom-inline-worker.js:1
    TypeError: Network request failed

Steps to reproduce:

  1. Create a React app with create-react-app

  2. Add jsdom-worker and node-fetch, which is a peer dependency for jsdom-worker

  3. Add the following test to the App.test.js:

    it('works', async () => {
      let code = `onmessage = e => postMessage(e.data*2)`
      const blob = new Blob([code], {type: "application/javascript"})
      let worker = new Worker(URL.createObjectURL(blob))
      worker.onmessage = jest.fn()
      worker.postMessage(5) // 10
      expect(worker.onmessage).toHaveBeenCalledWith({ data: 10 })
    })

    and add import 'jsdom-worker' on top

Run the tests and you will see the error.

Support import and require

I'm using jsdom-worker to support third party libs that use service workers in a jest runtime. The third party lib uses require all over the place, which causes issues when jest is otherwise configured as a module (i.e. using import). One way to solve this is to polyfill require -- for example, https://stackoverflow.com/a/71883023/3269537

import { createRequire } from "module";
const require = createRequire(import.meta.url);

It would be really convenient if jsdom-worker supported both require and import, so that it is agnostic to what code is actually being loaded. Can we simply inject the above here: https://github.com/developit/jsdom-worker/blob/main/src/index.js#L129? Happy to send out a pr that tries this

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.