Deepthy G
Deepthy G

Reputation: 11

TypeError: Cannot read properties of undefined (reading 'xhtml')

I'm trying to write Unit test cases for a React component containing jointJs library it is throwing below error. How to solve this error ?

TypeError: Cannot read properties of undefined (reading 'xhtml')

      175 |     graphRef.current = graph;
      176 |     const tree = new joint.layout.TreeLayout({ graph: graph });
    > 177 |     const paper = new joint.dia.Paper({
          |                   ^
      178 |       width: width,
      179 |       height: height,
      180 |       model: graph,

      at child.xhtml [as children] (node_modules/@clientio/rappid/rappid.js:31722:31)
      at result (node_modules/lodash/lodash.js:13708:44)
      at child.result [as renderChildren] (node_modules/@clientio/rappid/rappid.js:18445:34)
      at child.renderChildren (node_modules/@clientio/rappid/rappid.js:31770:15)
      at child.apply [as render] (node_modules/@clientio/rappid/rappid.js:18696:27)
      at child.render [as init] (node_modules/@clientio/rappid/rappid.js:31572:15)
      at child.init [as initialize] (node_modules/@clientio/rappid/rappid.js:18433:15)
      at child.Backbone.View (node_modules/backbone/backbone.js:1310:21)
      at child.call [as constructor] (node_modules/@clientio/rappid/rappid.js:18425:24)
      at new child (node_modules/backbone/backbone.js:2070:41)
      at src/components/Configuration/SiteNavigation/SiteNavigation.tsx:177:19
      at commitHookEffectListMount (node_modules/react-dom/cjs/react-dom.development.js:19731:26)
      at commitPassiveHookEffects (node_modules/react-dom/cjs/react-dom.development.js:19769:11)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:188:14)
      at HTMLUnknownElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:104:17)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:237:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:292:31)
      at flushPassiveEffectsImpl (node_modules/react-dom/cjs/react-dom.development.js:22853:9)
      at unstable_runWithPriority (node_modules/scheduler/cjs/scheduler.development.js:653:12)
      at runWithPriority$1 (node_modules/react-dom/cjs/react-dom.development.js:11039:10)
      at flushPassiveEffects (node_modules/react-dom/cjs/react-dom.development.js:22820:12)
      at Object.<anonymous>.flushWork (node_modules/react-dom/cjs/react-dom-test-utils.development.js:876:10)
      at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:994:9)
      at render (node_modules/@testing-library/react/dist/pure.js:97:26)

This is how we declared graph object and paper object in UseEffect hook which will be called on intial render of the component

const tree = new joint.layout.TreeLayout({ graph: graph });
    const paper = new joint.dia.Paper({
      width: width,
      height: height,
      model: graph,
      gridSize: 10,
      perpendicularLinks: false,
      drawGrid: { name: "mesh", args: { color: "#D3D4D5", scaleFactor: 4 } },
      background: {
        color: "rgba(0, 255, 0, 0.0)",
      },
      interactive: true,
    });

Upvotes: 0

Views: 530

Answers (2)

Pooja Thapa
Pooja Thapa

Reputation: 143

You need to first mock your method before running any assertions. Something like this -

  jest.mock("jointjs", () => {
  return {
    dia: {
      Paper: jest.fn().mockImplementation(() => {
        width: 100,
        height: 100,
        model: graph,
        gridSize: 10,
        perpendicularLinks: false,
        drawGrid: {
          name: "mesh",
          args: {
            color: "#D3D4D5",
            scaleFactor: 4
          }
        },
        background: {
          color: "rgba(0, 255, 0, 0.0)",
        },
        interactive: true,
      })
    }
  }
})

And then have add your required assertions. I am assuming you are using react testing library. E.g.

 test("Render element", async () => {
  render(<Your component />);
  await waitFor(() => {
    expect(your method).toBeTruthy();
  });

For reference, these docs may help:

  1. https://jestjs.io/docs/mock-functions
  2. https://docs.jointjs.com/learn/testing/jest
  3. https://ericdcobb.medium.com/advanced-react-component-mocks-with-jest-and-react-testing-library-f1ae8838400b

Upvotes: 1

James
James

Reputation: 336

Jest uses JSDOM which doesn't support a lot of SVG APIs. It is necessary to mock some functionality.

To fix this error, you can add the following to your tests setup file.

// Mock SVGAngle which is used for sanity checks in Vectorizer library
Object.defineProperty(window, 'SVGAngle', {
  writable: true,
  value: jest.fn().mockImplementation(() => ({
      new: jest.fn(),
      prototype: jest.fn(),
      SVG_ANGLETYPE_UNKNOWN: 0,
      SVG_ANGLETYPE_UNSPECIFIED: 1,
      SVG_ANGLETYPE_DEG: 2,
      SVG_ANGLETYPE_RAD: 3,
      SVG_ANGLETYPE_GRAD: 4
  }))
});

You can see an example of some mocks for Jest here: https://github.com/clientIO/joint-plus-tutorial-react/blob/main/src/setupTests.ts

Upvotes: 0

Related Questions