WARNING: a `go` object on the root object is already defined

Hello,

I am getting the following warning in a jest test:

WARNING: a `go` object on the root object is already defined.  version: 2.1.29, replaced with version: 2.1.29

    > 1 | import go from "gojs";
        | ^

I am importing gojs for an instanceof check in the test class:
if (model instanceof go.GraphLinksModel) {

What does the error message mean and do you by any chance know if (and how) this needs to be fixed in the jest setup?

That means the library is being loaded twice, which should be avoided.

First, try changing it to import * as go from "gojs";, as that’s the typical way of importing. Then make sure all places you are importing GoJS are using the same source, i.e. not using the debug version in one place and the release version in another.

Thanks for the feedback!
Changing the imports to * as go didn’t help. Also they should all use the same source.

I’ve investigated further and it seems like the issue only occurs if I have the gojs import in a mocked class.

import { ChangeIconItemCategoryUpdate } from "../ChangeIconItemCategoryUpdate";
jest.mock("../ChangeIconItemCategoryUpdate");

where ChangeIconItemCategoryUpdate contains the import go from "gojs"

Without inizializing the mock I don’t get the WARNING (but then I obviously cannot use the mock in the test).

Therefore I’d assume that the mock function is somehow loading/importing the gojs library a second time.

I also just checked and it works with goJS 2.0.10 but doesn’t with the latest 2.1.29

Yes it’s only recently that we tightened up the warning.

I think that one file can reference Go one way and other code references it another way, where even if it is the same file, module resolution is not clever enough to know this and loads them twice. However it is happening, it can be bad because if Go gets loaded twice, some initialization state can happen twice, or two clipboards could exist internally where half the code uses one clipboard and the other half the code uses the other clipboard, so its worth figuring out why.

I am supposing that there are not 2 instances of go.js (or even 2 instances of node_modules/gojs/release/) in the project, though maybe Jest is making copies or something behind the scenes. If not, then maybe try having the import statements reference the file exactly (node_modules/gojs/release/go.js) and see if that fixes it.

Alternatively, you could have 1 file import GoJS, and maybe export the go symbol, and then have the 2nd file import go from that first file.

Sorry that I don’t have a very precise answer, just some guesses. Let us know what you find.

The issue seems to occur if a jest test

  • imports a class/module which itself imports gojs, and
  • auto-mocks another class which also imports gojs

As a workaround we are currently using the module factory for creating mocks instead of auto mocking.
Unfortunately the module factory is more complex/verbose for most cases.

If not, then maybe try having the import statements reference the file exactly (node_modules/gojs/release/go.js) and see if that fixes it.

Unfortunately this didn’t change the outcome.

I could image that jest has some special handling for the imported/mocked modules (somehow load them in a separate context), just to make sure that the tests don’t interfere with each other, especially since test can also run in parallel.

Is there some non-official property I could set on goJs so it doesn’t throw an error if it is loaded twice?
Would it help if I’d set up a repository to reproduce the issue?

No, because loading it twice really can cause subtle problems. We got tired of dealing with the support burden. Which does place more of a burden on developers to make sure their imports are all consistent with each other. And which is why we recommend that programmers copy extensions into their own projects. (Which is also suggested because we do change extensions from time-to-time, ignoring the kind of GoJS version number change.)

I have one library with gojs. I’ll call it canvas-lib. I added a constant that it owns and my parent-repo needs it as well.

In canvas-lib:

export const THING = 1234;

In my parent-repo, we are using canvas-lib, as we were before, but now the constant is available.
But, when I try to import that constant, only my jest tests, all of my all of my jest tests that mock something that indirectly imports import { THING } from 'canvas-lib';, is now giving me the warning:

WARNING: a `go` object on the root object is already defined.  version: 2.1.56, replaced with version: 2.1.56

Reading through the responses here, I cannot put 2 and 2 together on what to do next. Thank you for any information.

How are you loading the GoJS library?

In the canvas-lib, there are all sorts of import type { Something } from 'gojs'.

In the parent-repo, there is one component (CanvasComponent) where we are doing this:

import * as go from 'gojs';

and then in a test file we are doing this:

import type { Diagram } from 'gojs';
import go from 'gojs';

along with other imports.

And this all works - until I export that constant from canvas-lib.

Note:
I’m checking to see if this is just a corrupted package-lock issue. Stand by, please. - Nope it’s not that.

Try using the not-yet-released GoJS library that you can grab from https://gojs.net/2.2.15/release/go.js

That does require upgrading to v2.2 from v2.1, but it should be compatible.