timarney / react-app-rewired

Override create-react-app webpack configs without ejecting
MIT License
9.76k stars 425 forks source link

don't concat array in Jest config rewire #613

Closed atvoid closed 2 years ago

atvoid commented 2 years ago

file: scripts/utils/rewireJestConfig.js

if(typeof overrides[key] === 'string' || typeof overrides[key] === 'number' || typeof overrides[key] === 'boolean') {
          config[key] = overrides[key];
        } else if(Array.isArray(overrides[key])) {
          config[key] = overrides[key].concat(config[key]);     // this line should be assignment rather than concat
        }
        else if(typeof overrides[key] === 'object') {
          config[key] = Object.assign({}, config[key], overrides[key]);
        }

config[key] = overrides[key].concat(config[key]); this line should be assignment rather than concat

like config transformIgnorePatterns, the default value is [ "node_modules"], if we use concat here, we can never overwrite the default.

jefer94 commented 2 years ago

Try with [...array1, array2] or {...object1, object2}

atvoid commented 2 years ago

Try with [...array1, array2] or {...object1, object2}

Not quite understand, how can I remove some default values there ? in package.json or jest.config.js like the default value is [ "node_modules"], I need to change the value to ["libA/", "libB/"], but with the concat there, this will never happen.

atvoid commented 2 years ago

@jefer94 if I set the transformIgnorePatterns to ["libA/", "libB/"], the final result will be [ "node_modules/", "libA/", "libB/"], but the expected result is ["libA/", "libB/"]. How can I achieve this ?

Because config[key] has a default value [ "node_modules/"]

dawnmist commented 2 years ago

You can override them by setting them inside the jest option in your config-overrides file rather than in your package.json file.

The part that concatenates the package.json file's information is done prior to passing you the config in config-overrides.

e.g. I've used the following to override transformIgnorePatterns where I needed stuff from the luxon and twemoji libraries in node_modules:

modules.export = {
  webpack: (config, env) => {
    // your webpack config changes here
    return config;
  },
  jest: (config) => {
    config.transformIgnorePatterns = [
      '<rootDir>/node_modules/[^lt]',      // ignore all node_modules libraries not starting with l or t
      '<rootDir>/node_modules/l(?!uxon)', // ignore all node_modules libraries starting with l that are not luxon
      '<rootDir>/node_modules/t(?!wemoji)' // ignore all node_modules libraries starting with t that are not twemoji
    ];
    config.moduleNameMapper = {
      '\\.(css|less|scss|sass)$': 'identity-obj-proxy'
    };
    config.globals = {
      ...config.globals,
      'ts-jest': {
        useBabelrc: true
      }
    };
    if (!config.snapshotSerializers) {
      config.snapshotSerializers = [];
    }
    config.snapshotSerializers.push('enzyme-to-json/serializer');

    return config;
  }
 }
kenlyon commented 2 years ago

I am facing this same pain. I need to replace the transformIgnorePatterns. Changes made in config-overrides.js appeared to have no effect, but with a bit of experimenting, I got it to work.

I was previously exporting a function from config-overrides.js which worked for the build, but seemed to be ignored for the tests. It turns out that you need to add a jest property to the function.

function override(config) {
    console.log("Overriding config...");
    return config;
}

override.jest = (config) => {
    console.log("overrideJest");
    return config;
}

module.exports = override;

If I run react-app-rewired build, the override() function is indeed called.

If I run react-app-rewired test, the override() function is not called, but its jest property is.

I don't know if this is the intended behaviour, but I think if override is a function, you should be calling it rather than looking for a jest property on it.

dawnmist commented 2 years ago

@kenlyon If you're providing changes for jest, the module.exports needs to be an object where the fields of the object are functions, not a function. So yes, the jest property is indeed what is supposed to be called - in this case you should not be providing the override as a function.

Nor does the jest override call the function used for webpack overrides - they deal with different configurations with different structures (one is the jest config, one is a webpack config).

This is documented in the README. See: https://github.com/timarney/react-app-rewired#extended-configuration-options

kenlyon commented 2 years ago

Wow, @dawnmist, you're right enough. Thanks! In my haste before, I hadn't read that part about using the "alternative" form for jest and devServer. I had glazed over that, assuming object vs. function were just two interchangable formats for the same thing.

I will see if I can adapt my function-plus-property accordingly. I'm using a specialized override() function from customize-cra, but from their own docs it seems this can be applied directly to the webpack property like so:

const { override } = require("customize-cra");

module.exports = {
    webpack: override(
        // My webpack override code.
    ),
    jest: (config) => {
        // My jest override code.
        return config;
    }
};
kenlyon commented 2 years ago

I can confirm that the above structure did work for me. The jest part is used for tests and the webpack for the build. I'm glad there was a way to combine everything without needing my weird "feature-with-property" hack.

kenlyon commented 2 years ago

@timarney Thanks for fixing this! Do you have an ETA on the next release?

kenlyon commented 1 year ago

@timarney Could we re-open this? I see now that although it was closed as "completed" there was no code change. The problem still exists.