Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for React 18 #2524

Open
TeoTN opened this issue Jun 10, 2021 · 14 comments
Open

Support for React 18 #2524

TeoTN opened this issue Jun 10, 2021 · 14 comments

Comments

@TeoTN
Copy link

TeoTN commented Jun 10, 2021

I would like to ask for support for React 18, as the alpha version was recently released: https://reactjs.org/blog/2021/06/08/the-plan-for-react-18.html

While this is an alpha release, my understanding is that this release is targeted towards library maintainers. The React team announced they're open for feedback:

We’ve published a React 18 Alpha so that library authors can try it and provide feedback.

I'm asking early, because it might be a good moment to start looking into React 18 adapter, and to try influence React in case there are major issues with onboarding Enzyme onto it.

@ljharb
Copy link
Member

ljharb commented Jun 14, 2021

That’d be great, but first we’d need to resolve #2429.

@mahdizaabi
Copy link

is there enzyme support for react 17 ?

@ljharb
Copy link
Member

ljharb commented Jun 30, 2021

@mahdizaabi nope, see #2429

@tomer-dev

This comment has been minimized.

@csvan
Copy link

csvan commented Mar 31, 2022

React 18 is now stable: https://reactjs.org/blog/2022/03/29/react-v18.html

@cbazureau
Copy link

cbazureau commented May 3, 2022

If you've got a large number of enzyme unit tests (> 1200 in our case) but you still want to switch to react 18 right now and migrate to react-testing-library progressively you can do it with this method (inspired by this article) :

  • update to react 18
  • create another package.json in a sub-folder like ./testing-react-17 and npm/yarn install it
{
  "private": true,
  "description": "Old enzyme based test that required react 17",
  "dependencies": {
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-test-renderer": "17.0.2"
  }
}
// jest.config.js
  ...
  testMatch: ['**/*.spec.js'],
  moduleDirectories: [
    'node_modules',
  ],

// jest2.config.js
  ...
  testMatch: ['**/*.spec2.js'],
  moduleDirectories: [
    '<rootDir>/test-react-17/node_modules',
    'node_modules',
  ],
  • run jest twice : on --config jest.config.js then on --config jest2.config.js
  • use .spec2.js for new tests using react-testing-library (and react 18 under the hood)
  • keep your old .spec.js for old tests using enzyme (and react 17 under the hood) and migrate them progressively

It's not perfect but i think it's better than waiting for the migration of all our tests or for an hypothetical official (or unofficial) enzyme-adapter-react-18.

@ayxos
Copy link

ayxos commented May 4, 2022

Using enzyme-adapter-react-17 and a bit tweak such as (https://stackoverflow.com/a/72109612/3764994)

const Environment = require('jest-environment-jsdom-global');
/**
 * A custom environment to set the TextEncoder
 */
module.exports = class CustomTestEnvironment extends Environment {
    constructor({ globalConfig, projectConfig }, context) {
        super({ globalConfig, projectConfig }, context);
        if (typeof this.global.TextEncoder === 'undefined') {
            const { TextEncoder } = require('util');
            this.global.TextEncoder = TextEncoder;
        }
    }
};

everything should work with react v18 and jest28

@bertho-zero

This comment was marked as spam.

@ArtemFedorchuk
Copy link

So, guys do we already have the solution how to use Enzyme in react 18?

@igorpupkinable
Copy link

igorpupkinable commented Sep 5, 2023

So, guys do we already have the solution how to use Enzyme in react 18?

We have successfully used @cfaester/enzyme-adapter-react-18 to run over 3500 tests. This gives you a possibility to migrate off Enzyme progressively.

Packages with these versions which proven to be working together on a large amount of various tests.
The whole thing is very fragile, so you have to stick to these MINOR or exact PATCH versions.

"devDependencies": {
  "@cfaester/enzyme-adapter-react-18": "^0.5.1",
  "@testing-library/react": "^13.3.0",
  "@types/enzyme": "^3.10.12",
  "enzyme": "^3.11.0",
  "enzyme-to-json": "^3.6.1",
  "@types/react": "^18.0.15",
  "@types/react-dom": "^18.0.6",
  "react": "^18.2.0",
  "react-docgen-typescript": "^2.2.2",
  "react-dom": "^18.2.0",
  "ts-react-display-name": "^1.2.2",

  // Jest versions working with this setup in case you have issues
  "@types/jest": "^27.5.2",
  "jest": "^27.5.1",
  "ts-jest": "^27.1.5",
}

Generally, three methods are causing issues with new React: simulate, setProps and mount.
You have to wait before component updates because the update happens asynchronously in multiple rounds which old adapter has no compatibility with.
I have added a nasty workaround, but hey.. it is better than convincing your stackeholders to rewrite several thousands of tests, right?!

The nasty hack is to absolutely wait for all component updates before continuing executing the rest of the test.
Here is an example which may be of some help.

test-utils/src/testComponentHelper.ts

import {
  act,
} from '@testing-library/react';
import type {
  CommonWrapper,
} from 'enzyme';

// State update magic happens here
const waitForComponentToPaint = async (wrapper: CommonWrapper): Promise<void> => {
  await act(async () => {
    await new Promise<void>((resolve) => {
      window.setTimeout(
        () => {
          /*
           * Make sure it is the last task in the queue.
           * https://dmitripavlutin.com/javascript-promises-settimeout/
           */
          window.setTimeout(
            resolve,
            1,
          );
        },
        1,
      );
    });
  });
  wrapper.update();
};

export default waitForComponentToPaint;

And then you do terrible things like these in your old tests:

wrapper.setProps({ value: 'foobar' });
await waitForComponentToPaint(wrapper);

and

wrapper.find('input').simulate('change', { target: { files: mockFiles } });
await waitForComponentToPaint(wrapper);

and

const wrapper = mount(...);
// Wait even longer for complex component updates
await waitForComponentToPaint(wrapper);
await waitForComponentToPaint(wrapper);

This is not perfect, but it works for old React 16/17 components and buys you time to migrate to React Testing Library.
It is possible to run smart search&replace to add waits to existing tests where needed.
Hope this helps. ;)

https://github.com/cfaester/enzyme-adapter-react-18

@eduardoacskimlinks
Copy link

@igorpupkinable I like the solution. Do you have the configuration that you use for the adapter, and if you use jest, which version

@igorpupkinable
Copy link

igorpupkinable commented Oct 22, 2023

@igorpupkinable I like the solution. Do you have the configuration that you use for the adapter, and if you use jest, which version

Standard adapter configuration as follows:

import Adapter from '@cfaester/enzyme-adapter-react-18';
import { configure } from 'enzyme';

configure({ adapter: new Adapter() });

"jest": "^27.5.1", in that particular project, but it should not matter.

@eduardoacskimlinks
Copy link

Thanks, @igorpupkinable. I initially used 29.x.x, but I couldn't get it to work due to missing support for jest-enzyme and jest-environment-enzyme. Therefore, I had to downgrade back to 24.8.0, but I am glad I could have gone for 27.5.1.

Screenshot 2023-10-19 at 14 26 59

@igorpupkinable
Copy link

@eduardoacskimlinks thanks for the feedback. I have updated my answer accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests