-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Automated Testing: Enforce no-unresolved checks for test files #79718
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
Changes from 2 commits
4874131
a572626
a7451a6
420b2cc
7b21905
9c64d86
46d2e4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,11 +8,81 @@ const PACKAGES_DIR = path.resolve( __dirname, '../../packages' ); | |
|
|
||
| exports.interfaceVersion = 2; | ||
|
|
||
| /** | ||
| * @typedef ExportEntryObject | ||
| * | ||
| * @property {string} import ESM import entrypoint. | ||
| * @property {string} default Default export entrypoint. | ||
| */ | ||
|
|
||
| /** | ||
| * @typedef {string|ExportEntryObject} ExportEntry | ||
| */ | ||
|
|
||
| /** | ||
| * Given an export entry and a subpath, returns the resolved export path for | ||
| * the matching entry. Defaults to the ESM entrypoint if available, falling back | ||
| * to the default export or the root entry if it is a string. | ||
| * | ||
| * @param {ExportEntry} exportEntry Export entry from package manifest. | ||
| * | ||
| * @return {string|undefined} The resolved export path, or undefined if no | ||
| * matching entry is found. | ||
| */ | ||
| function getResolvedExportPath( exportEntry ) { | ||
| return typeof exportEntry === 'string' | ||
| ? exportEntry | ||
| : exportEntry?.import ?? exportEntry?.default; | ||
| } | ||
|
|
||
| /** | ||
| * Given a package entrypoint identifier, returns the resolved export path for | ||
| * the matching entry. Supports matching wildcard entries, and defaults to the | ||
| * ESM entrypoint if available. | ||
| * | ||
| * @param {string} subpath Package entrypoint identifier. | ||
| * @param {Record<string, ExportEntry>} exportMap Export map from package manifest. | ||
| * | ||
| * @return {string|void|undefined} The resolved export path, or undefined if no | ||
| * matching entry is found. | ||
| */ | ||
| function getResolvedExport( subpath, exportMap ) { | ||
| if ( Object.hasOwn( exportMap, subpath ) ) { | ||
| return getResolvedExportPath( exportMap[ subpath ] ); | ||
| } | ||
|
|
||
| for ( const key in exportMap ) { | ||
| if ( ! Object.hasOwn( exportMap, key ) ) { | ||
| continue; | ||
| } | ||
|
|
||
| const wildcardIndex = key.indexOf( '*' ); | ||
| if ( wildcardIndex === -1 ) { | ||
| continue; | ||
| } | ||
|
|
||
| if ( subpath.startsWith( key.substring( 0, wildcardIndex ) ) ) { | ||
| const wildcardPath = subpath.substring( wildcardIndex ); | ||
| const resolvedPath = getResolvedExportPath( exportMap[ key ] ); | ||
| return resolvedPath?.replace( '*', wildcardPath ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| exports.resolve = function ( source, file, config ) { | ||
| const resolve = ( sourcePath ) => | ||
| resolverNode.resolve( sourcePath, file, { | ||
| ...config, | ||
| extensions: [ '.tsx', '.ts', '.mjs', '.js', '.json', '.node' ], | ||
| extensions: [ | ||
| '.tsx', | ||
| '.ts', | ||
| '.mjs', | ||
| '.js', | ||
| '.jsx', | ||
| '.cjs', | ||
| '.json', | ||
| '.node', | ||
| ], | ||
| } ); | ||
|
|
||
| if ( source.startsWith( '@wordpress/' ) ) { | ||
|
|
@@ -30,11 +100,15 @@ exports.resolve = function ( source, file, config ) { | |
| try { | ||
| const manifestPath = path.join( packagePath, 'package.json' ); | ||
| const manifest = JSON.parse( readFileSync( manifestPath, 'utf8' ) ); | ||
| const subpath = path.join( '.', pathParts.join( '/' ) ); | ||
| const exportPath = manifest.exports?.[ subpath ]?.import; | ||
|
Comment on lines
-33
to
-34
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know that this was working at all before for anything other than the
https://nodejs.org/api/packages.html#targets-must-be-relative-urls So trying to access |
||
| let subpath = '.'; | ||
| if ( pathParts.length > 0 ) { | ||
| subpath += '/' + pathParts.join( '/' ); | ||
| } | ||
| const exportPath = getResolvedExport( subpath, manifest.exports ); | ||
|
|
||
| const sourcePath = exportPath | ||
| .replace( 'build-module', 'src' ) | ||
| .replace( /\.mjs$/, '.js' ); | ||
| .replace( /build(-module)?/, 'src' ) | ||
| .replace( /\.[cm]?js$/, '.js' ); | ||
|
|
||
| return resolve( path.join( packagePath, sourcePath ) ); | ||
| } catch { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes break the unit tests, which similarly expect to be able to run without a preceding build. Which leaves us in a tricky spot because the point of the import rules is to ensure valid imports, and the previous code here is not valid:
@wordpress/block-librarydoesn't export/src/on its package API surface.Not entirely sure yet what the best option here would be, but a couple ideas to explore:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have something like this, but only supporting top-level package imports:
gutenberg/test/unit/jest.config.js
Lines 25 to 31 in 0fc4838
gutenberg/test/unit/jest.config.js
Lines 47 to 48 in 0fc4838
It looks like we already had to hack around this for some package subpath exports, like in
@wordpress/theme:gutenberg/test/unit/jest.config.js
Lines 49 to 50 in 0fc4838
Maybe that's the short-term option here: Add a remapping for these block imports to simulate support, and separately work to mirror the remapping behavior consistently between ESLint and Jest.