Files
jdescopingtool/NEW/tests/JdeScoping.ConfigManager.Tests/Models/ConnectionStringsSectionConverterTests.cs
T
Joseph Doherty 5ee710d330 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.
2026-01-28 09:24:49 -05:00

279 lines
9.2 KiB
C#

using System.Text.Json;
using JdeScoping.ConfigManager.Models;
using Shouldly;
using Xunit;
namespace JdeScoping.ConfigManager.Tests.Models;
public class ConnectionStringsSectionConverterTests
{
private static readonly JsonSerializerOptions JsonOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true
};
[Fact]
public void Deserialize_StandardDictionaryFormat_ParsesAllConnections()
{
// Arrange
var json = """
{
"LotFinder": "Server=localhost,1434;Database=ScopingTool;User Id=sa;Password=test",
"JDE": "Data Source=jde-server:1521/JDEPROD;User Id=jdeuser;Password=jdepass",
"CMS": "Data Source=cms-server:1521/CMSPROD;User Id=cmsuser;Password=cmspass"
}
""";
// Act
var section = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
// Assert
section.ShouldNotBeNull();
section.Entries.Count.ShouldBe(3);
var lotFinder = section.Entries.First(e => e.Name == "LotFinder");
lotFinder.Provider.ShouldBe(ConnectionProvider.SqlServer);
lotFinder.Server.ShouldBe("localhost,1434"); // Port embedded in server, not parsed separately
lotFinder.SqlServerPort.ShouldBeNull();
lotFinder.Database.ShouldBe("ScopingTool");
lotFinder.UserId.ShouldBe("sa");
var jde = section.Entries.First(e => e.Name == "JDE");
jde.Provider.ShouldBe(ConnectionProvider.Oracle);
jde.Host.ShouldBe("jde-server");
jde.Port.ShouldBe(1521);
jde.ServiceName.ShouldBe("JDEPROD");
}
[Fact]
public void Deserialize_SqlServerConnection_ParsesAllFields()
{
// Arrange
var json = """
{
"TestDb": "Server=myserver;Database=TestDB;User Id=testuser;Password=testpass;Encrypt=True;TrustServerCertificate=True;Connection Timeout=60;Application Name=TestApp"
}
""";
// Act
var section = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
// Assert
section.ShouldNotBeNull();
section.Entries.Count.ShouldBe(1);
var entry = section.Entries[0];
entry.Name.ShouldBe("TestDb");
entry.Provider.ShouldBe(ConnectionProvider.SqlServer);
entry.Server.ShouldBe("myserver");
entry.Database.ShouldBe("TestDB");
entry.UserId.ShouldBe("testuser");
entry.Password.ShouldBe("testpass");
entry.Encrypt.ShouldBe("True");
entry.TrustServerCertificate.ShouldBeTrue();
entry.ConnectionTimeout.ShouldBe(60);
entry.ApplicationName.ShouldBe("TestApp");
}
[Fact]
public void Deserialize_OracleConnection_ParsesHostPortService()
{
// Arrange
var json = """
{
"Oracle": "Data Source=//db-host:1523/PRODDB;User Id=orauser;Password=orapass"
}
""";
// Act
var section = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
// Assert
section.ShouldNotBeNull();
section.Entries.Count.ShouldBe(1);
var entry = section.Entries[0];
entry.Name.ShouldBe("Oracle");
entry.Provider.ShouldBe(ConnectionProvider.Oracle);
entry.Host.ShouldBe("db-host");
entry.Port.ShouldBe(1523);
entry.ServiceName.ShouldBe("PRODDB");
entry.UserId.ShouldBe("orauser");
entry.Password.ShouldBe("orapass");
}
[Fact]
public void Deserialize_EmptyObject_ReturnsEmptyEntries()
{
// Arrange
var json = "{}";
// Act
var section = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
// Assert
section.ShouldNotBeNull();
section.Entries.ShouldBeEmpty();
}
[Fact]
public void Serialize_ToStandardDictionaryFormat()
{
// Arrange
var section = new ConnectionStringsSection
{
Entries = new List<ConnectionStringEntry>
{
new()
{
Name = "TestDb",
Provider = ConnectionProvider.SqlServer,
Server = "myserver",
Database = "TestDB",
UserId = "testuser",
Password = "testpass"
}
}
};
// Act
var json = JsonSerializer.Serialize(section, JsonOptions);
// Assert
json.ShouldNotBeNull();
json.ShouldContain("\"TestDb\"");
json.ShouldContain("Server=myserver");
json.ShouldContain("Database=TestDB");
}
[Fact]
public void RoundTrip_PreservesConnections()
{
// Arrange
var original = new ConnectionStringsSection
{
Entries = new List<ConnectionStringEntry>
{
new()
{
Name = "Primary",
Provider = ConnectionProvider.SqlServer,
Server = "server1",
Database = "DB1",
UserId = "user1",
Password = "pass1"
},
new()
{
Name = "Secondary",
Provider = ConnectionProvider.Oracle,
Host = "oracle-host",
Port = 1521,
ServiceName = "ORCL",
UserId = "user2",
Password = "pass2"
}
}
};
// Act
var json = JsonSerializer.Serialize(original, JsonOptions);
var deserialized = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
// Assert
deserialized.ShouldNotBeNull();
deserialized.Entries.Count.ShouldBe(2);
var primary = deserialized.Entries.First(e => e.Name == "Primary");
primary.Provider.ShouldBe(ConnectionProvider.SqlServer);
primary.Server.ShouldBe("server1");
primary.Database.ShouldBe("DB1");
var secondary = deserialized.Entries.First(e => e.Name == "Secondary");
secondary.Provider.ShouldBe(ConnectionProvider.Oracle);
secondary.Host.ShouldBe("oracle-host");
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
}
}