Skip to content

Commit

Permalink
feat(jest-expo): support passing caller to babel-jest (#27637)
Browse files Browse the repository at this point in the history
# Why

If the project babel config is babel-preset-expo then it should have
access to the target platform that the bundler is transforming for. In
this case, the bundler is Jest, so we need to supply the platform caller
option to babel jest to ensure platform-specific transforms can be
applied in a predictable way.

# Test Plan

- I added a test for the new behavior to ensure `process.env.EXPO_OS` is
available in tests that use `babel-preset-expo`. Hopefully all other
tests continue to pass as expected.
- It's unclear if we should also pass `isDev` to the caller as well. It
seems like we currently support users toggling this at runtime in tests.
- Ran `et cp -a --no-build --no-lint --no-uniformity-check` to ensure
all tests keep working.

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
This is required for changes to Expo modules.
-->

- [ ] Documentation is up to date to reflect these changes (eg:
https://docs.expo.dev and README.md).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).

---------

Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
  • Loading branch information
EvanBacon and expo-bot committed Mar 15, 2024
1 parent bc7b8b5 commit ef7d2a6
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 10 deletions.
2 changes: 2 additions & 0 deletions packages/jest-expo/CHANGELOG.md
Expand Up @@ -6,6 +6,8 @@

### 🎉 New features

- Add support for internal `process.env.EXPO_OS` environment variable and passing `platform` to `babel-jest` caller. ([#27637](https://github.com/expo/expo/pull/27637) by [@EvanBacon](https://github.com/EvanBacon))

### 🐛 Bug fixes

### 💡 Others
Expand Down
42 changes: 37 additions & 5 deletions packages/jest-expo/config/getPlatformPreset.js
Expand Up @@ -4,7 +4,16 @@ const { getBareExtensions } = require('@expo/config/paths');
const { withWatchPlugins } = require('./withWatchPlugins');
const expoPreset = require('../jest-preset');

function getPlatformPreset(displayOptions, extensions) {
function getUpstreamBabelJest(transform) {
const upstreamBabelJest = Object.keys(transform).find((key) =>
Array.isArray(transform[key])
? transform[key][0] === 'babel-jest'
: transform[key] === 'babel-jest'
);
return upstreamBabelJest;
}

function getPlatformPreset(displayOptions, extensions, platform, isServer) {
const moduleFileExtensions = getBareExtensions(extensions, {
isTS: true,
isReact: true,
Expand All @@ -20,7 +29,26 @@ function getPlatformPreset(displayOptions, extensions) {
];
});

const upstreamBabelJest = getUpstreamBabelJest(expoPreset.transform) ?? '\\.[jt]sx?$';

return withWatchPlugins({
transform: {
...expoPreset.transform,
[upstreamBabelJest]: [
'babel-jest',
{
caller: {
name: 'metro',
bundler: 'metro',
// Add support for the `platform` babel transforms and inlines such as
// Platform.OS and `process.env.EXPO_OS`.
platform,
// Add support for removing server related code from the bundle.
isServer,
},
},
],
},
displayName: displayOptions,
testMatch,
moduleFileExtensions,
Expand Down Expand Up @@ -52,27 +80,31 @@ module.exports = {
getWebPreset() {
return {
...getBaseWebPreset(),
...getPlatformPreset({ name: 'Web', color: 'magenta' }, ['web']),
...getPlatformPreset({ name: 'Web', color: 'magenta' }, ['web'], 'web'),
testEnvironment: 'jsdom',
};
},
getNodePreset() {
return {
...getBaseWebPreset(),
...getPlatformPreset({ name: 'Node', color: 'cyan' }, ['node', 'web']),
...getPlatformPreset({ name: 'Node', color: 'cyan' }, ['node', 'web'], 'web', true),
testEnvironment: 'node',
};
},
getIOSPreset() {
return {
...expoPreset,
...getPlatformPreset({ name: 'iOS', color: 'white' }, ['ios', 'native']),
...getPlatformPreset({ name: 'iOS', color: 'white' }, ['ios', 'native'], 'ios'),
};
},
getAndroidPreset() {
return {
...expoPreset,
...getPlatformPreset({ name: 'Android', color: 'blueBright' }, ['android', 'native']),
...getPlatformPreset(
{ name: 'Android', color: 'blueBright' },
['android', 'native'],
'android'
),
};
},
};
16 changes: 11 additions & 5 deletions packages/jest-expo/jest-preset.js
Expand Up @@ -14,13 +14,19 @@ jestPreset.moduleNameMapper = {
'^react-native-vector-icons/(.*)': '@expo/vector-icons/$1',
};

// transform
if (!jestPreset.transform) {
jestPreset.transform = {
'\\.[jt]sx?$': 'babel-jest',
};
const upstreamBabelJest = Object.keys(jestPreset.transform).find(
(key) => jestPreset.transform[key] === 'babel-jest'
);
if (upstreamBabelJest) {
delete jestPreset.transform[upstreamBabelJest];
}

// transform
jestPreset.transform['\\.[jt]sx?$'] = [
'babel-jest',
{ caller: { name: 'metro', bundler: 'metro', platform: 'ios' } },
];

const defaultAssetNamePattern = '^.+\\.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp)$';
if (!jestPreset.transform[defaultAssetNamePattern]) {
console.warn(`Expected react-native/jest-preset to define transform[${defaultAssetNamePattern}]`);
Expand Down
7 changes: 7 additions & 0 deletions packages/jest-expo/tests/__tests__/jest-test.js
Expand Up @@ -11,4 +11,11 @@ describe(`jest-expo/universal`, () => {
expect(OS).toContain(Platform.OS);
expect(OS).toMatchSnapshot();
});

it(`injects process.env.EXPO_OS via babel-preset-expo automatically`, () => {
const { OS } = require('../default-extension');
const { Platform } = require('expo-modules-core');
expect(Platform.OS).toEqual(process.env.EXPO_OS);
expect(OS).toContain(process.env.EXPO_OS);
});
});

0 comments on commit ef7d2a6

Please sign in to comment.