diff --git a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js index 729a1147fa7d..866ab11cc1d5 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -407,3 +407,103 @@ describe('delete empty files and folders', () => { ]); }); }); + +describe('findFilesWithExtension', () => { + beforeEach(() => { + jest.resetModules(); + }); + + it('skips hidden files and folders', () => { + const targetFolder = '/project/ios'; + + jest.mock('fs', () => ({ + readdirSync: dirPath => { + if (dirPath === targetFolder) { + return ['.hidden', '.git', 'visible.mm']; + } + return []; + }, + existsSync: () => true, + statSync: () => ({ + isDirectory: () => false, + }), + readFileSync: () => packageJson, + })); + + const { + findFilesWithExtension: findFiles, + } = require('../generate-artifacts-executor/generateRCTThirdPartyComponents'); + + const result = findFiles(targetFolder, '.mm'); + expect(result).toEqual([path.join(targetFolder, 'visible.mm')]); + }); + + it('allows .pnpm folder', () => { + const targetFolder = '/project/node_modules'; + const pnpmFolder = path.join(targetFolder, '.pnpm'); + const packageFolder = path.join(pnpmFolder, 'some-package'); + + jest.mock('fs', () => ({ + readdirSync: dirPath => { + if (dirPath === targetFolder) { + return ['.pnpm', '.hidden']; + } + if (dirPath === pnpmFolder) { + return ['some-package']; + } + if (dirPath === packageFolder) { + return ['Component.mm']; + } + return []; + }, + existsSync: () => true, + statSync: filePath => ({ + isDirectory: () => + filePath === pnpmFolder || + filePath === packageFolder || + filePath === path.join(targetFolder, '.hidden'), + }), + readFileSync: () => packageJson, + })); + + const { + findFilesWithExtension: findFiles, + } = require('../generate-artifacts-executor/generateRCTThirdPartyComponents'); + + const result = findFiles(targetFolder, '.mm'); + expect(result).toEqual([path.join(packageFolder, 'Component.mm')]); + }); + + it('works when project is under a hidden folder', () => { + // This test verifies the fix for projects under hidden folders + // like ~/.jenkins/workspace/ or /.hidden-ci/builds/ + const targetFolder = '/.jenkins/workspace/my-project/ios'; + + jest.mock('fs', () => ({ + readdirSync: dirPath => { + if (dirPath === targetFolder) { + return ['Components']; + } + if (dirPath === path.join(targetFolder, 'Components')) { + return ['MyComponent.mm']; + } + return []; + }, + existsSync: () => true, + statSync: filePath => ({ + isDirectory: () => filePath === path.join(targetFolder, 'Components'), + }), + readFileSync: () => packageJson, + })); + + const { + findFilesWithExtension: findFiles, + } = require('../generate-artifacts-executor/generateRCTThirdPartyComponents'); + + const result = findFiles(targetFolder, '.mm'); + // Should find the file even though the absolute path contains /.jenkins/ + expect(result).toEqual([ + path.join(targetFolder, 'Components', 'MyComponent.mm'), + ]); + }); +}); diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor/generateRCTThirdPartyComponents.js b/packages/react-native/scripts/codegen/generate-artifacts-executor/generateRCTThirdPartyComponents.js index d54bd708c7b7..5c74af0d6162 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor/generateRCTThirdPartyComponents.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor/generateRCTThirdPartyComponents.js @@ -169,11 +169,10 @@ function findFilesWithExtension( return null; } - // Skip hidden folders, that starts with `.` but allow `.pnpm` - if ( - absolutePath.includes(`${path.sep}.`) && - !absolutePath.includes(`${path.sep}.pnpm`) - ) { + // Skip hidden files/folders (starting with `.`) but allow `.pnpm` + // Note: Only check the filename, not the entire path, to avoid false positives + // when the workspace itself is under a hidden folder (e.g., ~/.jenkins/) + if (file.startsWith('.') && file !== '.pnpm') { return null; } @@ -226,5 +225,6 @@ function findRCTComponentViewProtocolClass(filepath /*: string */) { } module.exports = { + findFilesWithExtension, generateRCTThirdPartyComponents, };