Skip to content

Commit 6eeee2f

Browse files
authored
fix(react): enhance upgrade-packages to support workspace glob patterns for projects without explicit workspaces (#1424)
1 parent 3db622c commit 6eeee2f

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

packages/core/update/Update.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,22 @@ export async function updateWorkspace(rootPath: string): Promise<boolean> {
116116
}
117117
});
118118
} else {
119+
// For React and WebComponents projects without explicit workspaces,
120+
// check for common project patterns like projects/* in addition to src/
119121
workspaces.push(path.join(rootPath, "src"));
122+
123+
// Check for projects/* pattern common in React demo/example repositories
124+
// Only check if projects directory exists to avoid unnecessary glob calls
125+
const projectsDir = path.join(rootPath, "projects");
126+
if (fs.directoryExists(projectsDir)) {
127+
const projectsPattern = "projects/*";
128+
const projectsWorkspaces = fs.glob(rootPath, projectsPattern);
129+
projectsWorkspaces.forEach(projectPath => {
130+
if (fs.directoryExists(projectPath)) {
131+
workspaces.push(projectPath);
132+
}
133+
});
134+
}
120135
}
121136
break;
122137
default:

spec/unit/update-spec.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,8 @@ title = 'igniteui-angular example';
521521
}
522522
};
523523
(fsSpy.fileExists as jasmine.Spy).and.returnValue(true);
524+
// Mock directoryExists to return false for projects directory to avoid extra glob calls
525+
(fsSpy.directoryExists as jasmine.Spy).and.returnValue(false);
524526
(fsSpy.glob as jasmine.Spy).and.returnValues // per workspace
525527
([ "package.json" ], // root package.json
526528
[], // html files
@@ -708,6 +710,8 @@ export default function Home() {
708710
return fileEntry.content;
709711
});
710712
(fsSpy.fileExists as jasmine.Spy).and.returnValue(true);
713+
// Mock directoryExists to return false for projects directory to avoid extra glob calls
714+
(fsSpy.directoryExists as jasmine.Spy).and.returnValue(false);
711715
spyOn(PackageManager, "ensureRegistryUser").and.returnValue(true);
712716
expect(await updateWorkspace("")).toEqual(true);
713717
for (const fileEntry of mockFileArray) {
@@ -926,12 +930,118 @@ export default defineConfig({
926930
});
927931
(fsSpy.fileExists as jasmine.Spy).and.returnValue(true);
928932
spyOn(PackageManager, "ensureRegistryUser").and.returnValue(true);
933+
// Mock directoryExists to return false for projects directory to avoid extra glob calls
934+
(fsSpy.directoryExists as jasmine.Spy).and.returnValue(false);
929935
expect(await updateWorkspace("")).toEqual(true);
930936
for (const fileEntry of mockFileArray) {
931937
expect((fsSpy.writeFile as jasmine.Spy)).toHaveBeenCalledWith(fileEntry.path, fileEntry.expected);
932938
}
933939
expect(fsSpy.glob).toHaveBeenCalledTimes(6);
934940
});
941+
942+
it("Should detect and update React projects with projects/* structure but no explicit workspaces", async () => {
943+
const mockFileArray: MockFile[] = [
944+
{
945+
path: "package.json",
946+
content:
947+
`{
948+
"name": "grid-demos-react",
949+
"dependencies": {
950+
"igniteui-react-grids": "^18.5.1",
951+
"some-package": "^0.0.0"
952+
}
953+
}
954+
`,
955+
expected:
956+
`{
957+
"name": "grid-demos-react",
958+
"dependencies": {
959+
"@infragistics/igniteui-react-grids": "^18.5.1",
960+
"some-package": "^0.0.0"
961+
}
962+
}
963+
`
964+
},
965+
{
966+
path: "projects/erp-hierarchical-grid/src/app.tsx",
967+
content:
968+
`import { IgrGridModule, IgrGrid } from 'igniteui-react-grids';
969+
import 'igniteui-react-grids/grids/themes/light/bootstrap.css';
970+
971+
export default function App() {
972+
return <IgrGrid />;
973+
}`,
974+
expected:
975+
`import { IgrGridModule, IgrGrid } from '@infragistics/igniteui-react-grids';
976+
import '@infragistics/igniteui-react-grids/grids/themes/light/bootstrap.css';
977+
978+
export default function App() {
979+
return <IgrGrid />;
980+
}`
981+
},
982+
{
983+
path: "projects/finance-grid/src/components/GridComponent.tsx",
984+
content:
985+
`import { IgrColumn } from 'igniteui-react-grids';
986+
987+
export const GridComponent = () => {
988+
return <IgrColumn />;
989+
}`,
990+
expected:
991+
`import { IgrColumn } from '@infragistics/igniteui-react-grids';
992+
993+
export const GridComponent = () => {
994+
return <IgrColumn />;
995+
}`
996+
}];
997+
998+
(fsSpy.fileExists as jasmine.Spy).and.returnValue(true);
999+
// Mock directoryExists to return true for projects directories and src
1000+
(fsSpy.directoryExists as jasmine.Spy).and.callFake((dirPath: string) => {
1001+
return dirPath === "projects" || dirPath.endsWith("/projects") || dirPath.includes("projects/") || dirPath === "src" || dirPath.endsWith("/src");
1002+
});
1003+
1004+
// Mock glob to simulate finding projects directories and files
1005+
(fsSpy.glob as jasmine.Spy).and.callFake((dirPath: string, pattern: string) => {
1006+
if (pattern === "package.json") {
1007+
return ["package.json"];
1008+
} else if (pattern === "projects/*") {
1009+
return ["projects/erp-hierarchical-grid", "projects/finance-grid"];
1010+
} else if (pattern === "**/*.tsx") {
1011+
if (dirPath.includes("erp-hierarchical-grid")) {
1012+
return ["projects/erp-hierarchical-grid/src/app.tsx"];
1013+
} else if (dirPath.includes("finance-grid")) {
1014+
return ["projects/finance-grid/src/components/GridComponent.tsx"];
1015+
} else if (dirPath.endsWith("/src")) {
1016+
return []; // src directory has no tsx files
1017+
}
1018+
return [];
1019+
} else if (pattern === "**/*.css") {
1020+
return [];
1021+
} else if (pattern === "**/package.json") {
1022+
return [];
1023+
} else if (pattern === "vite.config.ts") {
1024+
return [];
1025+
}
1026+
return [];
1027+
});
1028+
1029+
(fsSpy.readFile as jasmine.Spy).and.callFake((filePath: string) => {
1030+
if (filePath.indexOf("package.json") > -1) {
1031+
return mockFileArray.find(entry => entry.path === "package.json").content;
1032+
}
1033+
const fileEntry = mockFileArray.find(entry => entry.path === filePath);
1034+
return fileEntry ? fileEntry.content : "";
1035+
});
1036+
spyOn(PackageManager, "ensureRegistryUser").and.returnValue(true);
1037+
spyOn(Util, "log");
1038+
expect(await updateWorkspace("")).toEqual(true);
1039+
for (const fileEntry of mockFileArray) {
1040+
expect((fsSpy.writeFile as jasmine.Spy)).toHaveBeenCalledWith(fileEntry.path, fileEntry.expected);
1041+
}
1042+
// Expect calls for: package.json, projects/*, src tsx files, src css files, src package.json, vite.config.ts, erp-hierarchical-grid tsx files, erp-hierarchical-grid css files, erp-hierarchical-grid package.json, finance-grid tsx files, finance-grid css files, finance-grid package.json
1043+
expect(fsSpy.glob).toHaveBeenCalledTimes(13);
1044+
});
9351045
});
9361046

9371047
describe("Webcomponents", () => {
@@ -994,6 +1104,8 @@ export default defineConfig({
9941104
}
9951105
};
9961106
(fsSpy.fileExists as jasmine.Spy).and.returnValue(true);
1107+
// Mock directoryExists to return false for projects directory to avoid extra glob calls
1108+
(fsSpy.directoryExists as jasmine.Spy).and.returnValue(false);
9971109
(fsSpy.glob as jasmine.Spy).and.returnValues // per workspace
9981110
([ "package.json" ], // root package.json
9991111
[], //index.html
@@ -1168,6 +1280,8 @@ export default class App extends LitElement {
11681280
return fileEntry.content;
11691281
});
11701282
(fsSpy.fileExists as jasmine.Spy).and.returnValue(true);
1283+
// Mock directoryExists to return false for projects directory to avoid extra glob calls
1284+
(fsSpy.directoryExists as jasmine.Spy).and.returnValue(false);
11711285
spyOn(PackageManager, "ensureRegistryUser").and.returnValue(true);
11721286
expect(await updateWorkspace("")).toEqual(true);
11731287
for (const fileEntry of mockFileArray) {
@@ -1373,6 +1487,8 @@ export default defineConfig(({ mode }) => {
13731487
return fileEntry ? fileEntry.content : "";
13741488
});
13751489
(fsSpy.fileExists as jasmine.Spy).and.returnValue(true);
1490+
// Mock directoryExists to return false for projects directory to avoid extra glob calls
1491+
(fsSpy.directoryExists as jasmine.Spy).and.returnValue(false);
13761492
spyOn(PackageManager, "ensureRegistryUser").and.returnValue(true);
13771493
expect(await updateWorkspace("")).toEqual(true);
13781494
for (const fileEntry of mockFileArray) {

0 commit comments

Comments
 (0)