rive-app / rive-react

React runtime for Rive

Home Page:https://rive-app.github.io/rive-react

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to test Rive in React 18

michaelrenops opened this issue · comments

Hi,

I'm trying to write a unit test for my code, but it doesn't work.
I got this error:

ReferenceError: IntersectionObserver is not defined

So I tried to write a simple Rive component like this

import React from 'react';
import { render } from '@testing-library/react';
import Rive from 'rive-react';

jest.mock('@rive-app/react-canvas', () => ({
  Rive: jest.fn().mockImplementation(() => ({
    on: jest.fn(),
    stop: jest.fn()
  })),
  Layout: jest.fn(),
  Fit: {
    Cover: 'cover'
  },
  Alignment: {
    Center: 'center'
  },
  EventType: {
    Load: 'load'
  },
  StateMachineInputType: {
    Number: 1,
    Boolean: 2,
    Trigger: 3
  }
}));

describe('LoadingAnimation', () => {
  it('should render ', () => {
    const loadingAnimation = render(
      <Rive src={LoadingAnimationAsset)} className="container-styles" />
    );

    expect(loadingAnimation.firstChild).toHaveClass('container-styles');
  });
});

Still got the same error:

ReferenceError: IntersectionObserver is not defined

image

I've tried to downgrade to

"@rive-app/canvas": "^1.0.82",
"@rive-app/react-canvas": "^3.0.20",

and still no luck

Version used:

"rive-react": "^3.0.21"
"@rive-app/canvas": "^1.0.83",
"@rive-app/react-canvas": "^3.0.23",

Please help.

Kind regards
Michael Reno

Hey @michaelrenops

Try this:

import React from "react";
import { render } from "@testing-library/react";
import Rive from "@rive-app/react-canvas";

jest.mock("@rive-app/canvas", () => ({
  Rive: jest.fn().mockImplementation(() => ({
    on: jest.fn(),
    stop: jest.fn(),
  })),
  Layout: jest.fn(),
  Fit: {
    Cover: "cover",
  },
  Alignment: {
    Center: "center",
  },
  EventType: {
    Load: "load",
  },
  StateMachineInputType: {
    Number: 1,
    Boolean: 2,
    Trigger: 3,
  },
}));

describe("LoadingAnimation", () => {
  beforeEach(() => {
    global.IntersectionObserver = jest.fn(() => ({
      disconnect: jest.fn(),
      observe: jest.fn(),
      takeRecords: jest.fn(),
      unobserve: jest.fn(),
    }));
  });

  it("should render ", () => {
    const loadingAnimation = render(
      <Rive src={"https://test/file.riv"} className="container-styles" />
    );

    expect(
      loadingAnimation.container.querySelector(".container-styles")
    ).toBeInTheDocument();
  });
});

We do something similar in our own unit tests

Hi @avivian

Thank you for the answer

Unfortunately the global.IntersectionObserver gave me this error, but the test passes

Type 'Mock<{ disconnect: Mock<any, any>; observe: Mock<any, any>; takeRecords: Mock<any, any>; unobserve: Mock<any, any>; }, []>' is not assignable to type '{ new (callback: IntersectionObserverCallback, options?: IntersectionObserverInit | undefined): IntersectionObserver; prototype: IntersectionObserver; }'.
Type '{ disconnect: Mock<any, any>; observe: Mock<any, any>; takeRecords: Mock<any, any>; unobserve: Mock<any, any>; }' is missing the following properties from type 'IntersectionObserver': root, rootMargin, thresholdsts(2322)

So I did this

class IntersectionObserverStub {
  disconnect() {
    /* implementation is ignored */
  } // stub method

  observe() {
    /* implementation is ignored */
  } // stub method

  takeRecords() {
    /* implementation is ignored */
  } // stub method

  unobserve() {
    /* implementation is ignored */
  } // stub method
}

and this

  beforeEach(() => {
    jest.doMock('intersection-observer-mock', () => IntersectionObserverStub, { virtual: true });
    global.IntersectionObserver = jest.requireMock('intersection-observer-mock');
    jest.spyOn(IntersectionObserver.prototype, 'disconnect').mockImplementation();
    jest.spyOn(IntersectionObserver.prototype, 'observe').mockImplementation();
    jest.spyOn(IntersectionObserver.prototype, 'takeRecords').mockImplementation();
    jest.spyOn(IntersectionObserver.prototype, 'unobserve').mockImplementation();
  });

It works now.

Thankyou so much.

Kind regards
Michael Reno