too much for one commit
This commit is contained in:
232
tests/EntKube.Secrets.Tests/Domain/SecretScopeTests.cs
Normal file
232
tests/EntKube.Secrets.Tests/Domain/SecretScopeTests.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using EntKube.Secrets.Domain;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace EntKube.Secrets.Tests.Domain;
|
||||
|
||||
public class SecretScopeTests
|
||||
{
|
||||
// ─── Factory Method Tests ────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void ForCluster_CreatesInfrastructureScope()
|
||||
{
|
||||
// Arrange — Infrastructure secrets are scoped to Tenant + Environment + Cluster.
|
||||
// These are things like kubeconfig credentials, DNS tokens, cloud provider secrets.
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
Guid clusterId = Guid.NewGuid();
|
||||
|
||||
// Act
|
||||
|
||||
SecretScope scope = SecretScope.ForCluster(tenantId, environmentId, clusterId);
|
||||
|
||||
// Assert
|
||||
|
||||
scope.TenantId.Should().Be(tenantId);
|
||||
scope.EnvironmentId.Should().Be(environmentId);
|
||||
scope.ClusterId.Should().Be(clusterId);
|
||||
scope.CustomerId.Should().BeNull();
|
||||
scope.AppName.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ForApp_CreatesApplicationScope()
|
||||
{
|
||||
// Arrange — Application secrets are scoped to Tenant + Customer + App + Environment.
|
||||
// These are things like database connection strings, API keys for third-party services.
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid customerId = Guid.NewGuid();
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
|
||||
// Act
|
||||
|
||||
SecretScope scope = SecretScope.ForApp(tenantId, customerId, "my-api", environmentId);
|
||||
|
||||
// Assert
|
||||
|
||||
scope.TenantId.Should().Be(tenantId);
|
||||
scope.EnvironmentId.Should().Be(environmentId);
|
||||
scope.ClusterId.Should().BeNull();
|
||||
scope.CustomerId.Should().Be(customerId);
|
||||
scope.AppName.Should().Be("my-api");
|
||||
}
|
||||
|
||||
// ─── Record Construction Tests ───────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void Create_WithAllFields_StoresAllValues()
|
||||
{
|
||||
// Arrange — A fully-scoped secret with all fields populated.
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
Guid clusterId = Guid.NewGuid();
|
||||
Guid customerId = Guid.NewGuid();
|
||||
|
||||
// Act
|
||||
|
||||
SecretScope scope = new(tenantId, environmentId, clusterId, customerId, "my-api");
|
||||
|
||||
// Assert
|
||||
|
||||
scope.TenantId.Should().Be(tenantId);
|
||||
scope.EnvironmentId.Should().Be(environmentId);
|
||||
scope.ClusterId.Should().Be(clusterId);
|
||||
scope.CustomerId.Should().Be(customerId);
|
||||
scope.AppName.Should().Be("my-api");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_WithTenantOnly_AllowsNullOptionalFields()
|
||||
{
|
||||
// Arrange & Act — A tenant-wide secret (e.g. a shared API key)
|
||||
// that isn't scoped to a specific environment, cluster, customer, or app.
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
SecretScope scope = new(tenantId, null, null, null, null);
|
||||
|
||||
// Assert
|
||||
|
||||
scope.TenantId.Should().Be(tenantId);
|
||||
scope.EnvironmentId.Should().BeNull();
|
||||
scope.ClusterId.Should().BeNull();
|
||||
scope.CustomerId.Should().BeNull();
|
||||
scope.AppName.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_WithTenantAndEnvironment_ScopesToEnvironment()
|
||||
{
|
||||
// Arrange & Act — A secret scoped to a tenant + environment
|
||||
// (e.g. a dev database password shared across all customers in dev).
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
SecretScope scope = new(tenantId, environmentId, null, null, null);
|
||||
|
||||
// Assert
|
||||
|
||||
scope.TenantId.Should().Be(tenantId);
|
||||
scope.EnvironmentId.Should().Be(environmentId);
|
||||
scope.ClusterId.Should().BeNull();
|
||||
scope.CustomerId.Should().BeNull();
|
||||
scope.AppName.Should().BeNull();
|
||||
}
|
||||
|
||||
// ─── BuildPath Tests ─────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void BuildPath_TenantOnly_ReturnsPathWithTenantPrefix()
|
||||
{
|
||||
// Arrange — A tenant-scoped secret should have a path like
|
||||
// "tenants/{tenantId}/secrets/my-key".
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
SecretScope scope = new(tenantId, null, null, null, null);
|
||||
|
||||
// Act
|
||||
|
||||
string path = scope.BuildPath("my-key");
|
||||
|
||||
// Assert
|
||||
|
||||
path.Should().Be($"tenants/{tenantId}/secrets/my-key");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildPath_TenantAndEnvironment_ReturnsEnvironmentScopedPath()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
SecretScope scope = new(tenantId, environmentId, null, null, null);
|
||||
|
||||
// Act
|
||||
|
||||
string path = scope.BuildPath("db-password");
|
||||
|
||||
// Assert
|
||||
|
||||
path.Should().Be($"tenants/{tenantId}/environments/{environmentId}/secrets/db-password");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildPath_ClusterScope_ReturnsClusterScopedPath()
|
||||
{
|
||||
// Arrange — Infrastructure secret scoped to a specific cluster.
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
Guid clusterId = Guid.NewGuid();
|
||||
SecretScope scope = SecretScope.ForCluster(tenantId, environmentId, clusterId);
|
||||
|
||||
// Act
|
||||
|
||||
string path = scope.BuildPath("dns-credential");
|
||||
|
||||
// Assert — Path includes the cluster segment.
|
||||
|
||||
path.Should().Be(
|
||||
$"tenants/{tenantId}/environments/{environmentId}/clusters/{clusterId}/secrets/dns-credential");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildPath_AppScope_ReturnsFullAppScopedPath()
|
||||
{
|
||||
// Arrange — Application secret: tenant → environment → customer → app.
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid customerId = Guid.NewGuid();
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
SecretScope scope = SecretScope.ForApp(tenantId, customerId, "extract01", environmentId);
|
||||
|
||||
// Act
|
||||
|
||||
string path = scope.BuildPath("api-token");
|
||||
|
||||
// Assert
|
||||
|
||||
path.Should().Be(
|
||||
$"tenants/{tenantId}/environments/{environmentId}/customers/{customerId}/apps/extract01/secrets/api-token");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildPath_CustomerWithoutApp_IncludesCustomerScope()
|
||||
{
|
||||
// Arrange — Customer-scoped without a specific app.
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
Guid customerId = Guid.NewGuid();
|
||||
SecretScope scope = new(tenantId, environmentId, null, customerId, null);
|
||||
|
||||
// Act
|
||||
|
||||
string path = scope.BuildPath("shared-token");
|
||||
|
||||
// Assert
|
||||
|
||||
path.Should().Be(
|
||||
$"tenants/{tenantId}/environments/{environmentId}/customers/{customerId}/secrets/shared-token");
|
||||
}
|
||||
|
||||
// ─── Equality ────────────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void Equality_SameValues_AreEqual()
|
||||
{
|
||||
// Arrange — Records should have value-based equality.
|
||||
|
||||
Guid tenantId = Guid.NewGuid();
|
||||
Guid envId = Guid.NewGuid();
|
||||
SecretScope scope1 = new(tenantId, envId, null, null, null);
|
||||
SecretScope scope2 = new(tenantId, envId, null, null, null);
|
||||
|
||||
// Assert
|
||||
|
||||
scope1.Should().Be(scope2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user