Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 0 additions & 58 deletions jest.preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,62 +14,4 @@ module.exports = {
maxWorkers: 1,
testEnvironment: 'node',
setupFiles: ['../../scripts/unit-test-setup.js'],
moduleNameMapper: {
// TypeScript source mappings needed for Jest to resolve imports correctly
// Until ts-jest supports ts references, see: https://github.com/kulshekhar/ts-jest/pull/4689 & https://github.com/kulshekhar/ts-jest/issues/1648
'^@nx/devkit$': '<rootDir>/../devkit/index.ts',
'^@nx/devkit/testing$': '<rootDir>/../devkit/testing.ts',
'^@nx/devkit/internal-testing-utils$':
'<rootDir>/../devkit/internal-testing-utils.ts',
'^@nx/devkit/src/(.*)$': '<rootDir>/../devkit/src/$1',
'^nx/src/devkit-exports$': '<rootDir>/../nx/src/devkit-exports.ts',
'^nx/src/devkit-internals$': '<rootDir>/../nx/src/devkit-internals.ts',
'^nx/src/devkit-testing-exports$':
'<rootDir>/../nx/src/devkit-testing-exports.ts',
'^nx/src/internal-testing-utils/(.*)$':
'<rootDir>/../nx/src/internal-testing-utils/$1',
'^nx/src/generators/(.*)$': '<rootDir>/../nx/src/generators/$1',
'^nx/src/plugins/(.*)$': '<rootDir>/../nx/src/plugins/$1',
'^nx/src/utils/(.*)$': '<rootDir>/../nx/src/utils/$1',
'^nx/src/config/(.*)$': '<rootDir>/../nx/src/config/$1',
'^nx/src/command-line/(.*)$': '<rootDir>/../nx/src/command-line/$1',
'^nx/src/project-graph/(.*)$': '<rootDir>/../nx/src/project-graph/$1',
'^nx/src/daemon/(.*)$': '<rootDir>/../nx/src/daemon/$1',
'^nx/src/utils/(.*)$': '<rootDir>/../nx/src/utils/$1',
'^nx/src/hasher/(.*)$': '<rootDir>/../nx/src/hasher/$1',
'^nx/src/tasks-runner/(.*)$': '<rootDir>/../nx/src/tasks-runner/$1',
'^nx/src/adapter/(.*)$': '<rootDir>/../nx/src/adapter/$1',
'^nx/package.json$': '<rootDir>/../nx/package.json',
'^@nx/workspace$': '<rootDir>/../workspace/index.ts',
'^@nx/workspace/src/(.*)$': '<rootDir>/../workspace/src/$1',
// TS Solution: Map workspace packages to their TypeScript source
'^@nx/rollup$': '<rootDir>/../rollup/index.ts',
'^@nx/eslint$': '<rootDir>/../eslint/index.ts',
'^@nx/vite$': '<rootDir>/../vite/index.ts',
'^@nx/vite/src/(.*)$': '<rootDir>/../vite/src/$1',
'^@nx/jest$': '<rootDir>/../jest/index.ts',
'^@nx/js$': '<rootDir>/../js/src/index.ts',
'^@nx/js/src/(.*)$': '<rootDir>/../js/src/$1',
'^@nx/eslint/src/(.*)$': '<rootDir>/../eslint/src/$1',
'^@nx/esbuild$': '<rootDir>/../esbuild/index.ts',
'^@nx/react$': '<rootDir>/../react/index.ts',
'^@nx/playwright/plugin$': '<rootDir>/../playwright/plugin.ts',
'^@nx/rollup$': '<rootDir>/../rollup/index.ts',
'^@nx/rspack$': '<rootDir>/../rspack/src/index.ts',
'^@nx/plugin$': '<rootDir>/../plugin/index.ts',
'^@nx/plugin/src/(.*)$': '<rootDir>/../plugin/src/$1',
'^@nx/angular$': '<rootDir>/../angular/index.ts',
'^@nx/angular/src/(.*)$': '<rootDir>/../angular/src/$1',
'^@nx/react/src/(.*)$': '<rootDir>/../react/src/$1',
'^@nx/next$': '<rootDir>/../next/index.ts',
'^@nx/next/src/(.*)$': '<rootDir>/../next/src/$1',
'^@nx/nuxt$': '<rootDir>/../nuxt/index.ts',
'^@nx/nuxt/src/(.*)$': '<rootDir>/../nuxt/src/$1',
'^@nx/node$': '<rootDir>/../node/index.ts',
'^@nx/node/src/(.*)$': '<rootDir>/../node/src/$1',
'^@nx/web/src/(.*)$': '<rootDir>/../web/src/$1',
'^@nx/webpack/src/(.*)$': '<rootDir>/../webpack/src/$1',
'^@nx/cypress/src/(.*)$': '<rootDir>/../cypress/src/$1',
'^@nx/jest/src/(.*)$': '<rootDir>/../jest/src/$1',
},
};
241 changes: 111 additions & 130 deletions scripts/patched-jest-resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module.exports = function (modulePath, options) {
'@nx/eslint',
'@nx/vite',
'@nx/jest',
'@nx/docker',
'@nx/js',
'@nx/next',
'@nx/storybook',
Expand All @@ -61,7 +62,6 @@ module.exports = function (modulePath, options) {
'@nx/workspace',
'@nx/module-federation',
'@nx/rspack',
'@nx/docker',
'@nx/eslint-plugin',
'@nx/angular',
'@nx/create-nx-plugin',
Expand Down Expand Up @@ -109,155 +109,136 @@ module.exports = function (modulePath, options) {
return options.defaultResolver(modulePath, options);
}

const packagesPath = '../';
// Find workspace root - avoid filesystem lookups inside node_modules
// For PNPM workspaces, we know the structure: workspace/packages/packageName
let workspaceRoot = options.rootDir;

// If we're in a packages subdirectory, go up two levels to workspace root
if (workspaceRoot.includes('/packages/')) {
const packagesIndex = workspaceRoot.lastIndexOf('/packages/');
workspaceRoot = workspaceRoot.substring(0, packagesIndex);
} else {
// Fallback: go up directories until we find packages/ (but check pnpm-lock.yaml for validation)
while (workspaceRoot && workspaceRoot !== path.dirname(workspaceRoot)) {
const pnpmLock = path.join(workspaceRoot, 'pnpm-lock.yaml');
const packagesDir = path.join(workspaceRoot, 'packages');
if (fs.existsSync(pnpmLock) && fs.existsSync(packagesDir)) {
break;
}
workspaceRoot = path.dirname(workspaceRoot);
}
}

const packagesPath = path.join(workspaceRoot, 'packages');

// Handle main @nx/* package imports (e.g., '@nx/devkit', '@nx/js')
const nxPackageMatch = modulePath.match(/^@nx\/([^/]+)$/);
if (nxPackageMatch) {
const packageName = nxPackageMatch[1];

// TS Solution: Allow specific workspace packages to be resolved to TypeScript source
const tsWorkspacePackages = {
'@nx/rollup': path.resolve(
options.rootDir,
`${packagesPath}rollup/index.ts`
),
'@nx/eslint': path.resolve(
options.rootDir,
`${packagesPath}eslint/index.ts`
),
'@nx/vite': path.resolve(options.rootDir, `${packagesPath}vite/index.ts`),
'@nx/jest': path.resolve(options.rootDir, `${packagesPath}jest/index.ts`),
'@nx/js': path.resolve(options.rootDir, `${packagesPath}js/src/index.ts`),
// Additional packages where tests are working
'@nx/next': path.resolve(options.rootDir, `${packagesPath}next/index.ts`),
'@nx/storybook': path.resolve(
options.rootDir,
`${packagesPath}storybook/index.ts`
),
'@nx/rsbuild': path.resolve(
options.rootDir,
`${packagesPath}rsbuild/index.ts`
),
'@nx/react-native': path.resolve(
options.rootDir,
`${packagesPath}react-native/index.ts`
),
'@nx/express': path.resolve(
options.rootDir,
`${packagesPath}express/index.ts`
),
'@nx/web': path.resolve(options.rootDir, `${packagesPath}web/index.ts`),
'@nx/vue': path.resolve(options.rootDir, `${packagesPath}vue/index.ts`),
'@nx/workspace': path.resolve(
options.rootDir,
`${packagesPath}workspace/index.ts`
),
'@nx/module-federation': path.resolve(
options.rootDir,
`${packagesPath}module-federation/index.ts`
),
'@nx/react': path.resolve(
options.rootDir,
`${packagesPath}react/index.ts`
),
'@nx/remix': path.resolve(
options.rootDir,
`${packagesPath}remix/index.ts`
),
'@nx/webpack': path.resolve(
options.rootDir,
`${packagesPath}webpack/index.ts`
),
'@nx/playwright': path.resolve(
options.rootDir,
`${packagesPath}playwright/index.ts`
),
'@nx/rspack': path.resolve(
options.rootDir,
`${packagesPath}rspack/src/index.ts`
),
};
// Check if this package exists in workspace
const packageDir = path.join(packagesPath, packageName);

if (tsWorkspacePackages[modulePath]) {
return tsWorkspacePackages[modulePath];
// Try different entry points based on package structure
const possibleEntries = [
path.join(packageDir, 'index.ts'),
path.join(packageDir, 'src', 'index.ts'),
];

for (const entry of possibleEntries) {
if (fs.existsSync(entry) && fs.lstatSync(entry).isFile()) {
return entry;
}
}
}

// Handle @nx/js/src/* paths
if (modulePath.startsWith('@nx/js/src/')) {
const relativePath = modulePath.replace('@nx/js/src/', '');
return path.resolve(
options.rootDir,
`${packagesPath}js/src/`,
relativePath + '.ts'
);
// Handle @nx/*/src/* subpath imports (e.g., '@nx/devkit/src/utils/something')
const nxSubpathMatch = modulePath.match(/^@nx\/([^/]+)\/src\/(.+)$/);
if (nxSubpathMatch) {
const packageName = nxSubpathMatch[1];
const subpath = nxSubpathMatch[2];

// Try different patterns for subpath resolution
const possiblePaths = [
path.join(packagesPath, packageName, 'src', subpath + '.ts'), // Direct file
path.join(packagesPath, packageName, 'src', subpath, 'index.ts'), // Directory with index.ts
];

for (const possiblePath of possiblePaths) {
if (
fs.existsSync(possiblePath) &&
fs.lstatSync(possiblePath).isFile()
) {
return possiblePath;
}
}
}

// Handle @nx/eslint/src/* paths
if (modulePath.startsWith('@nx/eslint/src/')) {
const relativePath = modulePath.replace('@nx/eslint/src/', '');
return path.resolve(
options.rootDir,
`${packagesPath}eslint/src/`,
relativePath + '.ts'
);
// Handle @nx/* other subpaths (e.g., '@nx/devkit/testing', '@nx/devkit/package.json')
const nxOtherMatch = modulePath.match(/^@nx\/([^/]+)\/(.+)$/);
if (nxOtherMatch) {
const packageName = nxOtherMatch[1];
const subpath = nxOtherMatch[2];

const packageDir = path.join(packagesPath, packageName);

// Try different patterns for subpath resolution
const possiblePaths = [
path.join(packageDir, subpath), // For files like package.json
path.join(packageDir, subpath + '.ts'),
path.join(packageDir, 'src', subpath + '.ts'),
];

for (const possiblePath of possiblePaths) {
if (
fs.existsSync(possiblePath) &&
fs.lstatSync(possiblePath).isFile()
) {
return possiblePath;
}
}
}

if (modulePath.startsWith('@nx/docker/generators')) {
return path.resolve(
options.rootDir,
`${packagesPath}docker/generators.ts`
// Handle nx/src/* imports (direct nx package imports)
const nxSrcMatch = modulePath.match(/^nx\/src\/(.+)$/);
if (nxSrcMatch) {
const subpath = nxSrcMatch[1];
const resolvedPath = path.join(
packagesPath,
'nx',
'src',
subpath + '.ts'
);
if (fs.existsSync(resolvedPath) && fs.lstatSync(resolvedPath).isFile()) {
return resolvedPath;
}
}

// Handle other packages with src/* structure where tests are working
const srcPackages = [
'rspack',
'nx',
'eslint-plugin',
'react',
'vite',
'rollup',
'workspace',
'angular',
'next',
'node',
'web',
'webpack',
'cypress',
'jest',
];
for (const pkg of srcPackages) {
if (modulePath.startsWith(`@nx/${pkg}/src/`)) {
const relativePath = modulePath.replace(`@nx/${pkg}/src/`, '');
return path.resolve(
options.rootDir,
`${packagesPath}${pkg}/src/`,
relativePath + '.ts'
);
}
// Handle nx/package.json specifically
if (modulePath === 'nx/package.json') {
return path.join(packagesPath, 'nx', 'package.json');
}

// Handle nx/src/* paths (for direct nx package imports)
if (modulePath.startsWith('nx/src/')) {
const relativePath = modulePath.replace('nx/src/', '');
return path.resolve(
options.rootDir,
`${packagesPath}nx/src/`,
relativePath + '.ts'
);
// Handle other nx/* patterns
const nxOtherPatternMatch = modulePath.match(/^nx\/(.+)$/);
if (nxOtherPatternMatch) {
const subpath = nxOtherPatternMatch[1];
const resolvedPath = path.join(packagesPath, 'nx', subpath + '.ts');
if (fs.existsSync(resolvedPath)) {
return resolvedPath;
}
}

// Block other Nx packages from auto-resolution
// Block excluded Nx packages from auto-resolution
if (
modulePath.startsWith('@nx/') &&
!modulePath.startsWith('@nx/powerpack-') &&
!excludedPackages.some((pkg) => modulePath.startsWith(pkg))
) {
throw new Error('custom resolution blocked');
}

if (modulePath.startsWith('nx/') && !modulePath.startsWith('nx/src/'))
throw new Error('custom resolution blocked');

if (modulePath.includes('@nx/workspace')) {
throw new Error(
'Reference to local Nx package found. Use local version instead.'
// If we get here, it means the workspace package couldn't be resolved above
// This might indicate a missing file or incorrect import
console.warn(
`[resolver] Could not resolve workspace package: ${modulePath}`
);
}

Expand Down
Loading