diff --git a/packages/utils/upgrade/resources/examples/disable-jsx-buttons.code.ts b/packages/utils/upgrade/resources/examples/disable-jsx-buttons.code.ts new file mode 100644 index 0000000000..60aa33eaf6 --- /dev/null +++ b/packages/utils/upgrade/resources/examples/disable-jsx-buttons.code.ts @@ -0,0 +1,42 @@ +import type { Transform } from 'jscodeshift'; +import { relative } from 'node:path'; + +const transform: Transform = (file, api) => { + const j = api.jscodeshift; + const root = j.withParser('JSX')(file.source); + + const isReactFile = file.path.endsWith('.jsx') || file.path.endsWith('.tsx'); + + if (!isReactFile) { + return root.toSource(); + } + + const fileName = relative(process.cwd(), file.path); + + console.log(`Found React file: ${fileName}`); + + const buttons = root.findJSXElements('Button'); + + console.log(`Found ${buttons.length} buttons in ${fileName}`); + + buttons.forEach((button) => { + const { openingElement } = button.node; + const isDisabled = openingElement.attributes.some( + (attribute) => j.JSXAttribute.check(attribute) && attribute.name.name === 'disabled' + ); + + console.log(`Is disabled? ${isDisabled}`); + + if (!isDisabled) { + openingElement.attributes.push( + j.jsxAttribute(j.jsxIdentifier('disabled'), j.jsxExpressionContainer(j.literal(true))) + ); + + console.log('Added the disabled attribute'); + } + }); + + return root.toSource(); +}; + +export default transform; diff --git a/packages/utils/upgrade/src/modules/project/__tests__/project.test.ts b/packages/utils/upgrade/src/modules/project/__tests__/project.test.ts index 61845e724a..fc5f2fc90c 100644 --- a/packages/utils/upgrade/src/modules/project/__tests__/project.test.ts +++ b/packages/utils/upgrade/src/modules/project/__tests__/project.test.ts @@ -23,6 +23,8 @@ const srcFiles = { 'b.ts': 'console.log("b.ts")', 'c.js': 'console.log("c.js")', 'd.json': `{ "foo": "bar", "bar": 123 }`, + 'e.jsx': `console.log('e.jsx')`, + 'f.tsx': `console.log('f.tsx')`, }; const defaultVolume = { 'package.json': packageJSONFile, src: srcFiles }; @@ -92,7 +94,7 @@ describe('Project', () => { const project = projectFactory(defaultCWD); - expect(project.files.length).toBe(5); + expect(project.files.length).toBe(7); expect(project.files).toStrictEqual( expect.arrayContaining([path.join(defaultCWD, 'package.json'), ...srcFilenames(defaultCWD)]) ); @@ -111,7 +113,7 @@ describe('Project', () => { project.refresh(); - expect(project.files.length).toBe(5); + expect(project.files.length).toBe(7); expect(project.files).toStrictEqual( expect.arrayContaining([path.join(defaultCWD, 'package.json'), ...srcFilenames(defaultCWD)]) ); @@ -149,6 +151,22 @@ describe('Project', () => { ); }); + test('Get .jsx files only', () => { + const project = projectFactory(defaultCWD); + + const tsFiles = project.getFilesByExtensions(['.jsx']); + + expect(tsFiles).toStrictEqual(expect.arrayContaining([srcFilename(defaultCWD, 'e.jsx')])); + }); + + test('Get .tsx files only', () => { + const project = projectFactory(defaultCWD); + + const tsFiles = project.getFilesByExtensions(['.tsx']); + + expect(tsFiles).toStrictEqual(expect.arrayContaining([srcFilename(defaultCWD, 'f.tsx')])); + }); + test('Get both .js and .ts files', () => { const project = projectFactory(defaultCWD); diff --git a/packages/utils/upgrade/src/modules/project/constants.ts b/packages/utils/upgrade/src/modules/project/constants.ts index 06293f6e44..c65589ba61 100644 --- a/packages/utils/upgrade/src/modules/project/constants.ts +++ b/packages/utils/upgrade/src/modules/project/constants.ts @@ -2,7 +2,22 @@ export const PROJECT_PACKAGE_JSON = 'package.json'; export const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; -export const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; +export const PROJECT_DEFAULT_CODE_EXTENSIONS = [ + // Source files + 'js', + 'mjs', + 'ts', + // React files + 'jsx', + 'tsx', +]; + +export const PROJECT_DEFAULT_JSON_EXTENSIONS = ['json']; + +export const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = [ + ...PROJECT_DEFAULT_CODE_EXTENSIONS, + ...PROJECT_DEFAULT_JSON_EXTENSIONS, +]; export const PROJECT_DEFAULT_PATTERNS = ['package.json']; diff --git a/packages/utils/upgrade/src/modules/project/project.ts b/packages/utils/upgrade/src/modules/project/project.ts index 8e8e40c73d..d68343ab95 100644 --- a/packages/utils/upgrade/src/modules/project/project.ts +++ b/packages/utils/upgrade/src/modules/project/project.ts @@ -75,18 +75,26 @@ export class Project implements ProjectInterface { } private createProjectCodemodsRunners(dry: boolean = false) { - const jsonFiles = this.getFilesByExtensions(['.json']); - const codeFiles = this.getFilesByExtensions(['.js', '.ts', '.mjs']); + const jsonExtensions = constants.PROJECT_DEFAULT_JSON_EXTENSIONS.map( + (ext) => `.${ext}` + ); + const codeExtensions = constants.PROJECT_DEFAULT_CODE_EXTENSIONS.map( + (ext) => `.${ext}` + ); + + const jsonFiles = this.getFilesByExtensions(jsonExtensions); + const codeFiles = this.getFilesByExtensions(codeExtensions); const codeRunner = codeRunnerFactory(codeFiles, { dry, + parser: 'ts', + runInBand: true, + babel: true, + extensions: constants.PROJECT_DEFAULT_CODE_EXTENSIONS.join(','), + // Don't output any log coming from the runner print: false, silent: true, - extensions: 'js,ts', - runInBand: true, verbose: 0, - babel: true, - parser: 'ts', }); const jsonRunner = jsonRunnerFactory(jsonFiles, { dry, cwd: this.cwd });