Skip to main content
Glama
SiroSuzume

MCP ts-morph Refactoring Tools

by SiroSuzume
rename-file-system-entry.index.test.ts5.8 kB
import { describe, it, expect } from "vitest"; import * as path from "node:path"; import { Project } from "ts-morph"; import { renameFileSystemEntry } from "./rename-file-system-entry"; // --- Test Setup Helper --- const setupProject = () => { const project = new Project({ useInMemoryFileSystem: true, compilerOptions: { baseUrl: ".", paths: { "@/*": ["src/*"], }, esModuleInterop: true, allowJs: true, }, }); // 共通のディレクトリ構造をメモリ上に作成 project.createDirectory("/src"); project.createDirectory("/src/utils"); project.createDirectory("/src/components"); project.createDirectory("/src/myFeature"); project.createDirectory("/src/anotherFeature"); project.createDirectory("/src/featureA"); project.createDirectory("/src/core"); return project; }; describe("renameFileSystemEntry Index File Cases", () => { it("index.ts ファイル自体をリネームする", async () => { const project = setupProject(); const oldIndexPath = "/src/utils/index.ts"; const newIndexPath = "/src/utils/main.ts"; const componentPath = "/src/components/MyComponent.ts"; project.createSourceFile(oldIndexPath, "export const utilFromIndex = 1;"); project.createSourceFile( componentPath, "import { utilFromIndex } from '../utils';", ); await renameFileSystemEntry({ project, renames: [{ oldPath: oldIndexPath, newPath: newIndexPath }], dryRun: false, }); expect(project.getSourceFile(oldIndexPath)).toBeUndefined(); expect(project.getSourceFile(newIndexPath)).toBeDefined(); const updatedComponent = project.getSourceFileOrThrow(componentPath); // index.ts をリネームした場合、ディレクトリ参照はリネーム後のファイル名になるべき expect(updatedComponent.getFullText()).toContain( "import { utilFromIndex } from '../utils/main';", ); }); it("ディレクトリリネーム時に、内部からの '.' や外部からの '..' による index.ts 参照が正しく更新される", async () => { const project = setupProject(); const oldDirPath = "/src/featureA"; const newDirPath = "/src/featureRenamed"; const indexTsPath = path.join(oldDirPath, "index.ts"); const componentTsPath = path.join(oldDirPath, "component.ts"); const serviceTsPath = "/src/core/service.ts"; project.createSourceFile(indexTsPath, "export const featureValue = 'A';"); project.createSourceFile( componentTsPath, "import { featureValue } from '.';", ); project.createSourceFile( serviceTsPath, "import { featureValue } from '../featureA';", ); await renameFileSystemEntry({ project, renames: [{ oldPath: oldDirPath, newPath: newDirPath }], dryRun: false, }); const newComponentTsPath = path.join(newDirPath, "component.ts"); const updatedComponent = project.getSourceFileOrThrow(newComponentTsPath); const updatedService = project.getSourceFileOrThrow(serviceTsPath); expect(updatedComponent.getFullText()).toContain( "import { featureValue } from '.';", ); // service.ts の '../featureA' 参照は '../featureRenamed/index' に更新されるはず expect(updatedService.getFullText()).toContain( "import { featureValue } from '../featureRenamed/index';", ); }); it("index.ts でデフォルトエクスポートされた変数をパスエイリアス付きディレクトリ名でインポートしている場合、index.ts リネーム時にパスが正しく更新される", async () => { const project = setupProject(); const featureDir = "/src/myFeature"; const oldIndexPath = path.join(featureDir, "index.ts"); const newIndexPath = path.join(featureDir, "mainComponent.ts"); const importerPath = "/src/app.ts"; project.createSourceFile( oldIndexPath, "const MyFeatureComponent = () => {};\nexport default MyFeatureComponent;", ); project.createSourceFile( importerPath, "import MyFeature from '@/myFeature';\nMyFeature();", ); await renameFileSystemEntry({ project, renames: [{ oldPath: oldIndexPath, newPath: newIndexPath }], dryRun: false, }); const updatedImporterContent = project .getSourceFileOrThrow(importerPath) .getFullText(); expect(project.getSourceFile(oldIndexPath)).toBeUndefined(); expect(project.getSourceFile(newIndexPath)).toBeDefined(); // パスエイリアス参照がリネーム後のファイルパスに更新されることを期待。 expect(updatedImporterContent).toContain( "import MyFeature from './myFeature/mainComponent';", ); }); it("index.ts でデフォルトエクスポートされた関数をパスエイリアス付きディレクトリ名でインポートしている場合、index.ts リネーム時にパスが正しく更新される", async () => { const project = setupProject(); const featureDir = "/src/anotherFeature"; const oldIndexPath = path.join(featureDir, "index.ts"); const newIndexPath = path.join(featureDir, "coreFunction.ts"); const importerPath = "/src/main.ts"; project.createSourceFile( oldIndexPath, "export default function myCoreFunction() {}\n", ); project.createSourceFile( importerPath, "import CoreFunc from '@/anotherFeature';\nCoreFunc();", ); await renameFileSystemEntry({ project, renames: [{ oldPath: oldIndexPath, newPath: newIndexPath }], dryRun: false, }); const updatedImporterContent = project .getSourceFileOrThrow(importerPath) .getFullText(); expect(project.getSourceFile(oldIndexPath)).toBeUndefined(); expect(project.getSourceFile(newIndexPath)).toBeDefined(); // パスエイリアス参照がリネーム後のファイルパスに更新されることを期待。 expect(updatedImporterContent).toContain( "import CoreFunc from './anotherFeature/coreFunction';", ); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SiroSuzume/mcp-ts-morph'

If you have feedback or need assistance with the MCP directory API, please join our Discord server