Skip to content

Commit

Permalink
Add tests for conditional exports
Browse files Browse the repository at this point in the history
Summary: Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D43117824

fbshipit-source-id: 1cfb6596f5df52b7ad412a374fa8571cf1d854f3
  • Loading branch information
huntie authored and facebook-github-bot committed Feb 15, 2023
1 parent 38b96f8 commit a929d35
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 16 deletions.
185 changes: 171 additions & 14 deletions packages/metro-resolver/src/__tests__/package-exports-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,29 +249,186 @@ describe('with package exports resolution enabled', () => {
});

test('should not log warning when no "exports" field is present', () => {
const context = {
...baseContext,
...createPackageAccessors({
'/root/node_modules/test-pkg/package.json': {
main: 'index-main.js',
},
}),
};

expect(Resolver.resolve(context, 'test-pkg/private/bar', null)).toEqual(
{
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/private/bar.js',
},
);
// TODO(T142200031): Assert inaccessible import warning is NOT logged
});
});
});

describe('conditional exports', () => {
const baseContext = {
...createResolutionContext({
'/root/src/main.js': '',
'/root/node_modules/test-pkg/package.json': JSON.stringify({
name: 'test-pkg',
main: 'index.js',
exports: {
'./foo.js': {
import: './lib/foo-module.mjs',
development: './lib/foo-dev.js',
'react-native': {
import: './lib/foo-react-native.mjs',
require: './lib/foo-react-native.cjs',
default: './lib/foo-react-native.js',
},
browser: './lib/foo-browser.js',
require: './lib/foo-require.cjs',
default: './lib/foo.js',
},
},
}),
'/root/node_modules/test-pkg/index.js': '',
'/root/node_modules/test-pkg/lib/foo.js': '',
'/root/node_modules/test-pkg/lib/foo-require.cjs': '',
'/root/node_modules/test-pkg/lib/foo-module.mjs': '',
'/root/node_modules/test-pkg/lib/foo-dev.js': '',
'/root/node_modules/test-pkg/lib/foo-browser.js': '',
'/root/node_modules/test-pkg/lib/foo-react-native.cjs': '',
'/root/node_modules/test-pkg/lib/foo-react-native.mjs': '',
'/root/node_modules/test-pkg/lib/foo-react-native.js': '',
'/root/node_modules/test-pkg/lib/foo.web.js': '',
}),
originModulePath: '/root/src/main.js',
unstable_enablePackageExports: true,
};

test('should resolve "exports" subpath with conditions', () => {
const context = {
...baseContext,
unstable_conditionNames: ['require', 'react-native'],
};

expect(Resolver.resolve(context, 'test-pkg/foo.js', null)).toEqual({
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/lib/foo-react-native.cjs',
});
});

test('should resolve "exports" subpath with nested conditions', () => {
const context = {
...baseContext,
unstable_conditionNames: ['require', 'react-native'],
};

expect(Resolver.resolve(context, 'test-pkg/foo.js', null)).toEqual({
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/lib/foo-react-native.cjs',
});
});

test('should resolve asserted conditions in order specified by package', () => {
const context = {
...baseContext,
unstable_conditionNames: ['react-native', 'import'],
};

expect(Resolver.resolve(context, 'test-pkg/foo.js', null)).toEqual({
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/lib/foo-module.mjs',
});
});

test('should fall back to "default" condition if present', () => {
const context = {
...baseContext,
unstable_conditionNames: [],
};

expect(Resolver.resolve(context, 'test-pkg/foo.js', null)).toEqual({
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/lib/foo.js',
});
});

test('should throw FailedToResolvePathError when no conditions are matched', () => {
const context = {
...baseContext,
...createPackageAccessors({
'/root/node_modules/test-pkg/package.json': {
main: 'index.js',
exports: {
'./foo.js': {
import: './lib/foo-module.mjs',
require: './lib/foo-require.cjs',
// 'default' entry can be omitted
},
},
},
}),
unstable_conditionNames: [],
};

// TODO(T145206395): Improve this error trace
expect(() => Resolver.resolve(context, 'test-pkg/foo.js', null))
.toThrowErrorMatchingInlineSnapshot(`
"Module does not exist in the Haste module map or in these directories:
/root/src/node_modules
/root/node_modules
/node_modules
"
`);
});

describe('unstable_conditionsByPlatform', () => {
test('should resolve "browser" condition for `web` platform when configured', () => {
const context = {
...baseContext,
unstable_conditionNames: [],
unstable_conditionsByPlatform: {
web: ['browser'],
},
};

expect(Resolver.resolve(context, 'test-pkg/foo.js', null)).toEqual({
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/lib/foo.js',
});
expect(Resolver.resolve(context, 'test-pkg/foo.js', 'web')).toEqual({
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/lib/foo-browser.js',
});
});

test('should resolve using overridden per-platform conditions', () => {
const context = {
...baseContext,
unstable_conditionNames: [],
unstable_conditionsByPlatform: {
web: ['development', 'browser'],
},
};

expect(Resolver.resolve(context, 'test-pkg/foo.js', 'web')).toEqual({
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/lib/foo-dev.js',
});
expect(
Resolver.resolve(
{
...baseContext,
...createPackageAccessors({
'/root/node_modules/test-pkg/package.json': {
main: 'index-main.js',
},
}),
},
'test-pkg/private/bar',
null,
{...context, unstable_conditionsByPlatform: {}},
'test-pkg/foo.js',
'web',
),
).toEqual({
type: 'sourceFile',
filePath: '/root/node_modules/test-pkg/private/bar.js',
filePath: '/root/node_modules/test-pkg/lib/foo.js',
});
// TODO(T142200031): Assert inaccessible import warning is NOT logged
});
});
});

describe('conditional exports', () => {
describe('main entry point', () => {
const baseContext = {
...createResolutionContext({
Expand Down
6 changes: 4 additions & 2 deletions packages/metro-resolver/src/__tests__/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ export function createResolutionContext(
resolveHasteModule: (name: string) => null,
resolveHastePackage: (name: string) => null,
sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx'],
unstable_conditionNames: [],
unstable_conditionsByPlatform: {},
unstable_conditionNames: ['import', 'require'],
unstable_conditionsByPlatform: {
web: ['browser'],
},
unstable_enablePackageExports: false,
...createPackageAccessors(fileMap),
};
Expand Down

0 comments on commit a929d35

Please sign in to comment.