From de589cba61d8af778d994265a15cdb7aebc2d287 Mon Sep 17 00:00:00 2001 From: Chris Bobbe Date: Mon, 26 Oct 2020 15:07:00 -0700 Subject: [PATCH] jest: Fix facebook/jest#10221 locally. This is much easier than forking React Native, as we considered in zulip/react-native#5. See https://github.com/facebook/jest/issues/10221#issuecomment-714335771. --- jest.config.js | 21 +++++++++++++++++++-- jest/presetAndroid.js | 14 ++++++++++++++ jest/presetIos.js | 14 ++++++++++++++ jest/restorePromise.js | 3 +++ jest/savePromise.js | 4 ++++ 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 jest/presetAndroid.js create mode 100644 jest/presetIos.js create mode 100644 jest/restorePromise.js create mode 100644 jest/savePromise.js diff --git a/jest.config.js b/jest.config.js index 766671c42f..cc1feba609 100644 --- a/jest.config.js +++ b/jest.config.js @@ -30,8 +30,25 @@ const projectForPlatform = platform => { } return { displayName: platform, - // See https://github.com/expo/expo/blob/master/packages/jest-expo/README.md#platforms. - preset: platform === 'ios' ? 'jest-expo/ios' : 'jest-expo/android', + + // Ideally, these would simply be `jest-expo/ios` and + // `jest-expo/android`; see + // https://github.com/expo/expo/blob/master/packages/jest-expo/README.md#platforms. + // These custom presets are a workaround for a bug: + // + // `jest-expo`'s presets are based on `react-native`'s preset, + // which does something messy: it overwrites the global `Promise`. + // That's facebook/react-native#29303. Jest doesn't work well with + // that; that's facebook/jest#10221. + // + // So, until one of those is fixed, we use these custom presets to + // sandwich the code that replaces `global.Promise` with a fix: + // + // 1) save `global.Promise` to something else on `global` + // 2) let the `react-native` preset do its thing (like mocking RN + // libraries) + // 3) assign `global.Promise` back to what we saved in step 1 + preset: platform === 'ios' ? './jest/presetIos' : './jest/presetAndroid', // Finding and transforming source code. testPathIgnorePatterns: ['/node_modules/', '/src/__tests__/lib/', '-testlib.js$'], diff --git a/jest/presetAndroid.js b/jest/presetAndroid.js new file mode 100644 index 0000000000..88abafacfc --- /dev/null +++ b/jest/presetAndroid.js @@ -0,0 +1,14 @@ +/** + * The preset we're making tweaks to. + */ +const basePreset = require('../node_modules/jest-expo/android/jest-preset.js'); + +// See comment in our Jest config about how this is used. +module.exports = { + ...basePreset, + setupFiles: [ + require.resolve('./savePromise.js'), + ...basePreset.setupFiles, + require.resolve('./restorePromise.js'), + ], +}; diff --git a/jest/presetIos.js b/jest/presetIos.js new file mode 100644 index 0000000000..d89f565893 --- /dev/null +++ b/jest/presetIos.js @@ -0,0 +1,14 @@ +/** + * The preset we're making tweaks to. + */ +const basePreset = require('../node_modules/jest-expo/ios/jest-preset.js'); + +// See comment in our Jest config about how this is used. +module.exports = { + ...basePreset, + setupFiles: [ + require.resolve('./savePromise.js'), + ...basePreset.setupFiles, + require.resolve('./restorePromise.js'), + ], +}; diff --git a/jest/restorePromise.js b/jest/restorePromise.js new file mode 100644 index 0000000000..9a21e55f8d --- /dev/null +++ b/jest/restorePromise.js @@ -0,0 +1,3 @@ +// For facebook/jest#10221. After savePromise.js and Jest's setup +// files have run, restore the natural value of `global.Promise`. +global.Promise = global.originalPromise; diff --git a/jest/savePromise.js b/jest/savePromise.js new file mode 100644 index 0000000000..cf3088d9b6 --- /dev/null +++ b/jest/savePromise.js @@ -0,0 +1,4 @@ +// For facebook/jest#10221. Before Jest's setup files have run, take +// note of what the natural value of `global.Promise` is, so we can +// restore it in restorePromise.js. +global.originalPromise = Promise;