From f1da29e3bbca71ac64683c94a0319a2fb7f55777 Mon Sep 17 00:00:00 2001 From: enisn Date: Mon, 16 Feb 2026 12:07:19 +0300 Subject: [PATCH 1/3] fix: Resolve JS proxy namespace mismatch for multi-segment company names When generating a project with a company name containing dots (e.g., 'Demo.App.QoL'), the template replacement was incorrectly camelCasing the company name as 'demo.App' instead of 'demo.app'. This was because SolutionRenamer used ToCamelCase() on the entire string rather than on each dot-separated segment individually. The runtime JS proxy generator (JQueryProxyScriptGenerator.CamelCaseWithNamespace) applies camelCase to each segment, causing a mismatch. Added ToCamelCaseWithNamespace() helper to match runtime behavior. --- .../Building/Steps/SolutionRenamer.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenamer.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenamer.cs index 36006ecd18..e5c950f082 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenamer.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenamer.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Linq; using Volo.Abp.Cli.ProjectBuilding.Files; namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps; @@ -41,7 +42,7 @@ public class SolutionRenamer if (_companyName != null) { RenameHelper.RenameAll(_entries, _companyNamePlaceHolder, _companyName); - RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToCamelCase(), _companyName.ToCamelCase()); + RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToCamelCase(), ToCamelCaseWithNamespace(_companyName)); RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToKebabCase(), _companyName.ToKebabCase()); RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToLowerInvariant(), _companyName.ToLowerInvariant()); } @@ -55,9 +56,19 @@ public class SolutionRenamer } RenameHelper.RenameAll(_entries, _projectNamePlaceHolder, _projectName); - RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToCamelCase(), _projectName.ToCamelCase()); + RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToCamelCase(), ToCamelCaseWithNamespace(_projectName)); RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToKebabCase(), _projectName.ToKebabCase()); RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToLowerInvariant(), _projectName.ToLowerInvariant()); RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToSnakeCase().ToUpper(), _projectName.ToSnakeCase().ToUpper()); } + + private static string ToCamelCaseWithNamespace(string name) + { + if (name.Contains('.')) + { + return name.Split('.').Select(n => n.ToCamelCase()).JoinAsString("."); + } + + return name.ToCamelCase(); + } } \ No newline at end of file From 257574173e808a5df4f6c555b41828a2c4e29554 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Feb 2026 10:12:06 +0000 Subject: [PATCH 3/3] Add unit tests for ToCamelCaseWithNamespace method Co-authored-by: enisn <23705418+enisn@users.noreply.github.com> --- .../Building/Steps/SolutionRenamer_Tests.cs | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenamer_Tests.cs diff --git a/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenamer_Tests.cs b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenamer_Tests.cs new file mode 100644 index 0000000000..a3c5cee0d6 --- /dev/null +++ b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenamer_Tests.cs @@ -0,0 +1,87 @@ +using Shouldly; +using System.Collections.Generic; +using System.Reflection; +using Volo.Abp.Cli.ProjectBuilding.Files; +using Xunit; + +namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps; + +public class SolutionRenamer_Tests +{ + [Theory] + [InlineData("Demo", "demo")] + [InlineData("MyCompany", "myCompany")] + [InlineData("Acme", "acme")] + [InlineData("ABC", "aBC")] + public void ToCamelCaseWithNamespace_Should_Handle_Single_Segment_Names(string input, string expected) + { + // Act + var result = InvokeToCamelCaseWithNamespace(input); + + // Assert + result.ShouldBe(expected); + } + + [Theory] + [InlineData("Demo.App", "demo.app")] + [InlineData("MyCompany.MyProject", "myCompany.myProject")] + [InlineData("Acme.Bookstore", "acme.bookstore")] + [InlineData("ABC.XYZ", "aBC.xYZ")] + public void ToCamelCaseWithNamespace_Should_Handle_Two_Segment_Names(string input, string expected) + { + // Act + var result = InvokeToCamelCaseWithNamespace(input); + + // Assert + result.ShouldBe(expected); + } + + [Theory] + [InlineData("Demo.App.QoL", "demo.app.qoL")] + [InlineData("MyCompany.MyProject.Module", "myCompany.myProject.module")] + [InlineData("Acme.Bookstore.Application", "acme.bookstore.application")] + [InlineData("A.B.C.D", "a.b.c.d")] + public void ToCamelCaseWithNamespace_Should_Handle_Multi_Segment_Names(string input, string expected) + { + // Act + var result = InvokeToCamelCaseWithNamespace(input); + + // Assert + result.ShouldBe(expected); + } + + [Theory] + [InlineData("", "")] + [InlineData("A", "a")] + [InlineData(".", ".")] + [InlineData("...", "...")] + public void ToCamelCaseWithNamespace_Should_Handle_Edge_Cases(string input, string expected) + { + // Act + var result = InvokeToCamelCaseWithNamespace(input); + + // Assert + result.ShouldBe(expected); + } + + [Fact] + public void ToCamelCaseWithNamespace_Should_Throw_On_Null_Input() + { + // Act & Assert + var exception = Should.Throw(() => InvokeToCamelCaseWithNamespace(null)); + exception.InnerException.ShouldBeOfType(); + } + + /// + /// Helper method to invoke the private static ToCamelCaseWithNamespace method using reflection + /// + private static string InvokeToCamelCaseWithNamespace(string input) + { + var type = typeof(SolutionRenamer); + var method = type.GetMethod("ToCamelCaseWithNamespace", BindingFlags.NonPublic | BindingFlags.Static); + + method.ShouldNotBeNull("ToCamelCaseWithNamespace method should exist"); + + return (string)method.Invoke(null, new object[] { input }); + } +}