feat(configmanager): add dedicated SQL Server port control

Add SqlServerPort property to connection string editor for explicit port
configuration, replacing the need to embed port in server name (e.g.,
localhost,1434). The port control generates the comma-separated format in
the connection string but does not parse it back when loading existing
connection strings.
This commit is contained in:
Joseph Doherty
2026-01-28 09:24:49 -05:00
parent daaeba2004
commit 5ee710d330
8 changed files with 334 additions and 108 deletions
@@ -34,7 +34,8 @@ public class ConnectionStringsSectionConverterTests
var lotFinder = section.Entries.First(e => e.Name == "LotFinder");
lotFinder.Provider.ShouldBe(ConnectionProvider.SqlServer);
lotFinder.Server.ShouldBe("localhost,1434");
lotFinder.Server.ShouldBe("localhost,1434"); // Port embedded in server, not parsed separately
lotFinder.SqlServerPort.ShouldBeNull();
lotFinder.Database.ShouldBe("ScopingTool");
lotFinder.UserId.ShouldBe("sa");
@@ -195,4 +196,83 @@ public class ConnectionStringsSectionConverterTests
secondary.Port.ShouldBe(1521);
secondary.ServiceName.ShouldBe("ORCL");
}
[Fact]
public void Deserialize_SqlServerWithEmbeddedPort_KeepsPortInServer()
{
// Arrange - connection string with port embedded in server name (legacy format)
var json = """
{
"TestDb": "Server=localhost,1434;Database=TestDB;User Id=testuser;Password=testpass"
}
""";
// Act
var section = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
// Assert - port is NOT parsed out, stays embedded in server name
section.ShouldNotBeNull();
section.Entries.Count.ShouldBe(1);
var entry = section.Entries[0];
entry.Name.ShouldBe("TestDb");
entry.Provider.ShouldBe(ConnectionProvider.SqlServer);
entry.Server.ShouldBe("localhost,1434"); // Port stays in server name
entry.SqlServerPort.ShouldBeNull(); // Port control not populated from parsing
entry.Database.ShouldBe("TestDB");
}
[Fact]
public void Deserialize_SqlServerWithoutPort_ServerHasNoPort()
{
// Arrange
var json = """
{
"TestDb": "Server=myserver;Database=TestDB;User Id=testuser;Password=testpass"
}
""";
// Act
var section = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
// Assert
section.ShouldNotBeNull();
section.Entries.Count.ShouldBe(1);
var entry = section.Entries[0];
entry.Server.ShouldBe("myserver");
entry.SqlServerPort.ShouldBeNull();
}
[Fact]
public void RoundTrip_SqlServerWithPort_EmbedsPortInServer()
{
// Arrange - entry with separate port control
var original = new ConnectionStringsSection
{
Entries = new List<ConnectionStringEntry>
{
new()
{
Name = "WithPort",
Provider = ConnectionProvider.SqlServer,
Server = "localhost",
SqlServerPort = 1434,
Database = "DB1",
UserId = "user1",
Password = "pass1"
}
}
};
// Act
var json = JsonSerializer.Serialize(original, JsonOptions);
var deserialized = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
// Assert - after round trip, port is embedded in server name (not parsed back out)
deserialized.ShouldNotBeNull();
var entry = deserialized.Entries.First();
entry.Server.ShouldBe("localhost,1434"); // Port embedded in server after round trip
entry.SqlServerPort.ShouldBeNull(); // Port control not populated from parsing
}
}