felippenardi/lottie-react-web

TypeError: Cannot set property 'fillStyle' of null

akshay-kochhar opened this issue ยท 16 comments

Getting this error for all the test cases when they try to mount the component using enzyme.
It shows error corresponding to the import line "import Lottie from 'lottie-react-web';"

Error:-
With :- import Lottie from 'lottie-react-web';
at ../../common/temp/node_modules/.office.pkgs.visualstudio.com/lottie-web/5.5.2/node_modules/lottie-web/build/player/lottie.js:4165:23
at ../../common/temp/node_modules/.office.pkgs.visualstudio.com/lottie-web/5.5.2/node_modules/lottie-web/build/player/lottie.js:4168:6
at ../../common/temp/node_modules/.office.pkgs.visualstudio.com/lottie-web/5.5.2/node_modules/lottie-web/build/player/lottie.js:4268:2
at ../../common/temp/node_modules/.office.pkgs.visualstudio.com/lottie-web/5.5.2/node_modules/lottie-web/build/player/lottie.js:7:26

Installing and setting up https://www.npmjs.com/package/jest-canvas-mock worked for me

Its a shame you can't easlier to use with create-react-app though

@hutber You can use it with CRA

I just added require('jest-canvas-mock'); to the top of my setupTests.js file :)

Is there another fix for this? My test suite is AVA?

For those of us not using jest, my fix was to install canvas and JSDOM then mock the canvas

Installing and setting up https://www.npmjs.com/package/jest-canvas-mock worked for me

Also

$ yarn install canvas

@hutber You can use it with CRA

I just added require('jest-canvas-mock'); to the top of my setupTests.js file :)

This totally worked for me. Thanks!!

A better way is to setup jest to handle this. jest.config.js:

module.exports = {
  setupFilesAfterEnv: ['jest-canvas-mock'],
};
bidva commented

I still have the issue
my app is created by react-app-rewired
I have installed and setup jest-canvas-mock on package.json
also installed canvas

"jest": {
    "setupFiles": [
      "<rootDir>/src/setupTests.js",
      "jest-canvas-mock"
    ],
    "collectCoverageFrom": [
      "src/**/*.{js,jsx,ts,tsx}",
      "!src/**/*.d.ts"
    ]
  },

and then imported that top of my setupTests.js

import 'jest-canvas-mock';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

// Included to mock local storage in JS tests, see docs at
// https://www.npmjs.com/package/jest-localstorage-mock#in-create-react-app

require('jest-localstorage-mock');
// for plotly.js to work
//
window.URL.createObjectURL = function createObjectURL() {};
// to fix Error: Not implemented: HTMLCanvasElement.prototype.getContext
window.HTMLCanvasElement.prototype.getContext = () => {}; 

but still getting:

TypeError: Cannot set property 'fillStyle' of undefined

    > 1 | import { Player } from '@lottiefiles/react-lottie-player';
        | ^
      2 | import projection_replay from '../assets/lottie/projection_replay.json';
      3 |
      4 | const ProjectionNotReady = () => {

      at canvas (node_modules/@lottiefiles/react-lottie-player/node_modules/lottie-web/build/player/lottie.js:4699:9)
      at ImagePreloaderFactory (node_modules/@lottiefiles/react-lottie-player/node_modules/lottie-web/build/player/lottie.js:4701:12)
      at factory (node_modules/@lottiefiles/react-lottie-player/node_modules/lottie-web/build/player/lottie.js:4897:10)
      at lottie (node_modules/@lottiefiles/react-lottie-player/node_modules/lottie-web/build/player/lottie.js:7:26)
      at value (node_modules/@lottiefiles/react-lottie-player/node_modules/lottie-web/build/player/lottie.js:10:31)
      at value (node_modules/@lottiefiles/react-lottie-player/node_modules/tslib/tslib.es6.js:234:105)
      at Object.<anonymous> (node_modules/@lottiefiles/react-lottie-player/node_modules/tslib/tslib.es6.js:234:105)
      at Object.<anonymous> (src/components/ProjectionNotReady.js:1:1)
      at Object.<anonymous> (src/containers/Home/Models/Model.js:37:1)
      at Object.<anonymous> (src/containers/Home/Models/Models.js:27:1)
      at Object.<anonymous> (src/containers/Home/Home.js:10:1)
      at Object.<anonymous> (src/containers/Home/index.js:1:1)
      at Object.<anonymous> (src/containers/index.js:1:1)
      at Object.<anonymous> (src/Routes.jsx:4:1)
      at Object.<anonymous> (src/App.js:2:1)
      at Object.<anonymous> (src/App.test.js:3:1)

here is my component to test

import React from 'react';
import Routes from './Routes';
import { WithErrors } from './hocs/WithErrors';
import 'antd/dist/antd.css';
import './styles/styles.scss';

export const App = () => {
  return <Routes />;
};

export default WithErrors(App);

and here is my test

import React from 'react';
import renderer from 'react-test-renderer';
import App from './App';

describe('App', () => {
  test('Should render', () => {
    const tree = renderer.create(<App />).toJSON();
    expect(tree).toMatchSnapshot();
  });
});

any idea?

bidva commented

just for others, adding to import to existed setupTest.js didn't work for me but adding it to a new file worked. it's a bit strange but just said.

Any updates on this?

doing the require('jest-canvas-mock'); at the top of setupTests.ts file worked fine, but It would be nice to not include a third-party lib just to use lottie.

none of the above mentioned solutions work for me.

 TypeError: Cannot set properties of null (setting 'fillStyle')

      1 | import animationData from 'assets/lotties/paperplane.json';
      2 | import { useAuth } from 'hooks/useAuth';
    > 3 | import Lottie from 'lottie-react';

have installed jest-canvas-mock as devDep & have imported on top of setupTests.ts.
i am using CRA with default react-scripts

This is my current solution. While I'm trying to import jest-canvas-mock in my setupTests file, I also do this in the error test file :

// Mock the CanvasRenderingContext2D object
class CanvasRenderingContext2DMock {
  fillStyle = '';
  fillRect = jest.fn();
  // Add any other necessary properties and methods
}

// Set up the mock before running the tests
beforeEach(() => {
  // @ts-ignore
  window.HTMLCanvasElement.prototype.getContext = () => {
    return new CanvasRenderingContext2DMock();
  };
});

// Now you can run your tests without encountering the error

For vitejs

  1. Create file vitest.setup.ts
import { vi } from "vitest";

/* @ts-ignore */
HTMLCanvasElement.prototype.getContext = () => {
  return {
    fillStyle: '',
    fillRect: vi.fn()
  }
}
  1. Add in your vitest.config.ts
export default defineConfig({
  test: {
    setupFiles: ['./vitest.setup.ts'],
  }
});
kinoli commented

This was needed for me in my vitest.setup.ts file.

/* @ts-ignore */
HTMLCanvasElement.prototype.getContext = () => {
  return {
    fillStyle: '',
    fillRect: vi.fn(),
    clearRect: vi.fn(),
    scale: vi.fn(),
  }
}

For vitejs

  1. Create file vitest.setup.ts
import { vi } from "vitest";

/* @ts-ignore */
HTMLCanvasElement.prototype.getContext = () => {
  return {
    fillStyle: '',
    fillRect: vi.fn()
  }
}
  1. Add in your vitest.config.ts
export default defineConfig({
  test: {
    setupFiles: ['./vitest.setup.ts'],
  }
});

Work for me, Thanks.