Initial commit, project structure and domain models
This commit is contained in:
53
tests/api/MicCheck.Api.Tests.Unit/ApiKeys/ApiKeyTests.cs
Normal file
53
tests/api/MicCheck.Api.Tests.Unit/ApiKeys/ApiKeyTests.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.ApiKeys;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.ApiKeys;
|
||||
|
||||
[TestFixture]
|
||||
public class ApiKeyTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAnApiKeyIsCreated_ThenRequiredFieldsAreSet()
|
||||
{
|
||||
var apiKey = new ApiKey
|
||||
{
|
||||
Key = "hashed-value",
|
||||
Prefix = "abc12345",
|
||||
Name = "CI Pipeline Key",
|
||||
OrganizationId = 1
|
||||
};
|
||||
|
||||
Assert.That(apiKey.Key, Is.EqualTo("hashed-value"));
|
||||
Assert.That(apiKey.Prefix, Is.EqualTo("hashed-value".Substring(0, 8)).Or.EqualTo("abc12345"));
|
||||
Assert.That(apiKey.Name, Is.EqualTo("CI Pipeline Key"));
|
||||
Assert.That(apiKey.OrganizationId, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnApiKeyIsCreated_ThenIsActiveDefaultsToFalse()
|
||||
{
|
||||
var apiKey = new ApiKey
|
||||
{
|
||||
Key = "hashed-value",
|
||||
Prefix = "abc12345",
|
||||
Name = "Test Key",
|
||||
OrganizationId = 1
|
||||
};
|
||||
|
||||
Assert.That(apiKey.IsActive, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnApiKeyIsCreated_ThenExpiresAtDefaultsToNull()
|
||||
{
|
||||
var apiKey = new ApiKey
|
||||
{
|
||||
Key = "hashed-value",
|
||||
Prefix = "abc12345",
|
||||
Name = "Test Key",
|
||||
OrganizationId = 1
|
||||
};
|
||||
|
||||
Assert.That(apiKey.ExpiresAt, Is.Null);
|
||||
}
|
||||
}
|
||||
42
tests/api/MicCheck.Api.Tests.Unit/Audit/AuditLogTests.cs
Normal file
42
tests/api/MicCheck.Api.Tests.Unit/Audit/AuditLogTests.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.Audit;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Audit;
|
||||
|
||||
[TestFixture]
|
||||
public class AuditLogTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAnAuditLogIsCreated_ThenRequiredFieldsAreSet()
|
||||
{
|
||||
var log = new AuditLog
|
||||
{
|
||||
ResourceType = "Feature",
|
||||
ResourceId = "42",
|
||||
Action = "Created",
|
||||
OrganizationId = 1
|
||||
};
|
||||
|
||||
Assert.That(log.ResourceType, Is.EqualTo("Feature"));
|
||||
Assert.That(log.ResourceId, Is.EqualTo("42"));
|
||||
Assert.That(log.Action, Is.EqualTo("Created"));
|
||||
Assert.That(log.OrganizationId, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnAuditLogIsCreated_ThenOptionalFieldsDefaultToNull()
|
||||
{
|
||||
var log = new AuditLog
|
||||
{
|
||||
ResourceType = "Feature",
|
||||
ResourceId = "1",
|
||||
Action = "Deleted",
|
||||
OrganizationId = 1
|
||||
};
|
||||
|
||||
Assert.That(log.Changes, Is.Null);
|
||||
Assert.That(log.ProjectId, Is.Null);
|
||||
Assert.That(log.EnvironmentId, Is.Null);
|
||||
Assert.That(log.ActorUserId, Is.Null);
|
||||
}
|
||||
}
|
||||
75
tests/api/MicCheck.Api.Tests.Unit/Auth/AuthEndpointsTests.cs
Normal file
75
tests/api/MicCheck.Api.Tests.Unit/Auth/AuthEndpointsTests.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.Auth;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Auth;
|
||||
|
||||
[TestFixture]
|
||||
public class AuthEndpointsTests
|
||||
{
|
||||
private WebApplicationFactory<Program> _factory = null!;
|
||||
private Mock<ITokenService> _tokenService = null!;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_tokenService = new Mock<ITokenService>();
|
||||
|
||||
_factory = new WebApplicationFactory<Program>()
|
||||
.WithWebHostBuilder(host =>
|
||||
{
|
||||
host.ConfigureServices(services =>
|
||||
{
|
||||
services.AddScoped<ITokenService>(_ => _tokenService.Object);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() => _factory.Dispose();
|
||||
|
||||
[Test]
|
||||
public async Task WhenUsernameIsEmpty_ThenBadRequestIsReturned()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
var response = await client.PostAsJsonAsync("/auth/token",
|
||||
new TokenRequest("", "password123"));
|
||||
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task WhenPasswordIsEmpty_ThenBadRequestIsReturned()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
var response = await client.PostAsJsonAsync("/auth/token",
|
||||
new TokenRequest("testuser", ""));
|
||||
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task WhenValidCredentialsAreProvided_ThenOkIsReturnedWithToken()
|
||||
{
|
||||
var expectedResponse = new TokenResponse("signed.jwt.token", DateTime.UtcNow.AddHours(1));
|
||||
_tokenService
|
||||
.Setup(s => s.GenerateToken("testuser"))
|
||||
.Returns(expectedResponse);
|
||||
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
var response = await client.PostAsJsonAsync("/auth/token",
|
||||
new TokenRequest("testuser", "password123"));
|
||||
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
|
||||
|
||||
var body = await response.Content.ReadFromJsonAsync<TokenResponse>();
|
||||
Assert.That(body?.Token, Is.EqualTo(expectedResponse.Token));
|
||||
}
|
||||
}
|
||||
67
tests/api/MicCheck.Api.Tests.Unit/Auth/TokenServiceTests.cs
Normal file
67
tests/api/MicCheck.Api.Tests.Unit/Auth/TokenServiceTests.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using MicCheck.Api.Auth;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Auth;
|
||||
|
||||
[TestFixture]
|
||||
public class TokenServiceTests
|
||||
{
|
||||
private IConfiguration _configuration = null!;
|
||||
private TokenService _tokenService = null!;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Jwt:SecretKey"] = "test-secret-key-that-is-long-enough-32c",
|
||||
["Jwt:Issuer"] = "MicCheck",
|
||||
["Jwt:Audience"] = "MicCheck",
|
||||
["Jwt:ExpiryMinutes"] = "60",
|
||||
})
|
||||
.Build();
|
||||
|
||||
_tokenService = new TokenService(_configuration);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAUsernameIsProvided_ThenATokenIsReturned()
|
||||
{
|
||||
var result = _tokenService.GenerateToken("testuser");
|
||||
|
||||
Assert.That(result.Token, Is.Not.Null.And.Not.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenATokenIsGenerated_ThenItContainsTheUsernameAsSubjectClaim()
|
||||
{
|
||||
var result = _tokenService.GenerateToken("testuser");
|
||||
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var jwt = handler.ReadJwtToken(result.Token);
|
||||
|
||||
Assert.That(jwt.Subject, Is.EqualTo("testuser"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenATokenIsGenerated_ThenItHasAFutureExpiry()
|
||||
{
|
||||
var result = _tokenService.GenerateToken("testuser");
|
||||
|
||||
Assert.That(result.ExpiresAt, Is.GreaterThan(DateTime.UtcNow));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenATokenIsGenerated_ThenItHasTheConfiguredIssuer()
|
||||
{
|
||||
var result = _tokenService.GenerateToken("testuser");
|
||||
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var jwt = handler.ReadJwtToken(result.Token);
|
||||
|
||||
Assert.That(jwt.Issuer, Is.EqualTo("MicCheck"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using NUnit.Framework;
|
||||
using AppEnvironment = MicCheck.Api.Environments.Environment;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Environments;
|
||||
|
||||
[TestFixture]
|
||||
public class EnvironmentTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAnEnvironmentIsCreated_ThenFeatureStatesCollectionIsInitializedEmpty()
|
||||
{
|
||||
var environment = new AppEnvironment { Name = "Production", ApiKey = "env-key-abc" };
|
||||
|
||||
Assert.That(environment.FeatureStates, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnEnvironmentIsCreated_ThenNameAndApiKeyAreSet()
|
||||
{
|
||||
var environment = new AppEnvironment { Name = "Staging", ApiKey = "env-key-xyz" };
|
||||
|
||||
Assert.That(environment.Name, Is.EqualTo("Staging"));
|
||||
Assert.That(environment.ApiKey, Is.EqualTo("env-key-xyz"));
|
||||
}
|
||||
}
|
||||
110
tests/api/MicCheck.Api.Tests.Unit/Features/FeatureTests.cs
Normal file
110
tests/api/MicCheck.Api.Tests.Unit/Features/FeatureTests.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.Features;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Features;
|
||||
|
||||
[TestFixture]
|
||||
public class FeatureTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAFeatureIsCreated_ThenCollectionsAreInitializedEmpty()
|
||||
{
|
||||
var feature = new Feature { Name = "dark_mode", ProjectId = 1 };
|
||||
|
||||
Assert.That(feature.FeatureStates, Is.Empty);
|
||||
Assert.That(feature.Tags, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAFeatureIsCreated_ThenTypeDefaultsToStandard()
|
||||
{
|
||||
var feature = new Feature { Name = "dark_mode", ProjectId = 1 };
|
||||
|
||||
Assert.That(feature.Type, Is.EqualTo(FeatureType.Standard));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAFeatureIsCreated_ThenDefaultEnabledIsFalse()
|
||||
{
|
||||
var feature = new Feature { Name = "dark_mode", ProjectId = 1 };
|
||||
|
||||
Assert.That(feature.DefaultEnabled, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAFeatureTypeIsSetToMultiVariate_ThenThePropertyReflectsTheChange()
|
||||
{
|
||||
var feature = new Feature { Name = "experiment", ProjectId = 1, Type = FeatureType.MultiVariate };
|
||||
|
||||
Assert.That(feature.Type, Is.EqualTo(FeatureType.MultiVariate));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class FeatureStateTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAFeatureStateIsCreated_ThenEnabledDefaultsToFalse()
|
||||
{
|
||||
var state = new FeatureState { FeatureId = 1, EnvironmentId = 1 };
|
||||
|
||||
Assert.That(state.Enabled, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAFeatureStateIdentityIdIsNull_ThenItRepresentsAnEnvironmentLevelState()
|
||||
{
|
||||
var state = new FeatureState { FeatureId = 1, EnvironmentId = 1 };
|
||||
|
||||
Assert.That(state.IdentityId, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAFeatureStateFeatureSegmentIdIsNull_ThenItIsNotASegmentOverride()
|
||||
{
|
||||
var state = new FeatureState { FeatureId = 1, EnvironmentId = 1 };
|
||||
|
||||
Assert.That(state.FeatureSegmentId, Is.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class FeatureStateResultTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAFeatureStateResultIsCreated_ThenFeatureAndEnabledAreSet()
|
||||
{
|
||||
var feature = new Feature { Name = "dark_mode", ProjectId = 1 };
|
||||
var result = new FeatureStateResult { Feature = feature, Enabled = true };
|
||||
|
||||
Assert.That(result.Feature, Is.SameAs(feature));
|
||||
Assert.That(result.Enabled, Is.True);
|
||||
Assert.That(result.Value, Is.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class FeatureSegmentTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAFeatureSegmentIsCreated_ThenFeatureStateIsNull()
|
||||
{
|
||||
var segment = new FeatureSegment { FeatureId = 1, SegmentId = 2, EnvironmentId = 3 };
|
||||
|
||||
Assert.That(segment.FeatureState, Is.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class TagTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenATagIsCreated_ThenLabelColorAndProjectIdAreSet()
|
||||
{
|
||||
var tag = new Tag { Label = "Beta", Color = "#FF0000", ProjectId = 1 };
|
||||
|
||||
Assert.That(tag.Label, Is.EqualTo("Beta"));
|
||||
Assert.That(tag.Color, Is.EqualTo("#FF0000"));
|
||||
Assert.That(tag.ProjectId, Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.Identities;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Identities;
|
||||
|
||||
[TestFixture]
|
||||
public class IdentityTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAnIdentityIsCreated_ThenCollectionsAreInitializedEmpty()
|
||||
{
|
||||
var identity = new Identity { Identifier = "user-123", EnvironmentId = 1 };
|
||||
|
||||
Assert.That(identity.Traits, Is.Empty);
|
||||
Assert.That(identity.FeatureStateOverrides, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnIdentityIsCreated_ThenIdentifierAndEnvironmentIdAreSet()
|
||||
{
|
||||
var identity = new Identity { Identifier = "user-123", EnvironmentId = 5 };
|
||||
|
||||
Assert.That(identity.Identifier, Is.EqualTo("user-123"));
|
||||
Assert.That(identity.EnvironmentId, Is.EqualTo(5));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class IdentityTraitTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAnIdentityTraitIsCreated_ThenKeyAndValueAreSet()
|
||||
{
|
||||
var trait = new IdentityTrait { IdentityId = 1, Key = "plan", Value = "premium" };
|
||||
|
||||
Assert.That(trait.Key, Is.EqualTo("plan"));
|
||||
Assert.That(trait.Value, Is.EqualTo("premium"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnIdentityTraitValueTypeIsSet_ThenTheTypeIsStored()
|
||||
{
|
||||
var trait = new IdentityTrait
|
||||
{
|
||||
IdentityId = 1,
|
||||
Key = "age",
|
||||
Value = "30",
|
||||
ValueType = TraitValueType.Integer
|
||||
};
|
||||
|
||||
Assert.That(trait.ValueType, Is.EqualTo(TraitValueType.Integer));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAllTraitValueTypesAreChecked_ThenAllExpectedValuesExist()
|
||||
{
|
||||
var types = Enum.GetValues<TraitValueType>();
|
||||
|
||||
Assert.That(types, Contains.Item(TraitValueType.String));
|
||||
Assert.That(types, Contains.Item(TraitValueType.Integer));
|
||||
Assert.That(types, Contains.Item(TraitValueType.Float));
|
||||
Assert.That(types, Contains.Item(TraitValueType.Boolean));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.5" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="NUnit" Version="4.5.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../../src/api/MicCheck.Api/MicCheck.Api.csproj" />
|
||||
<ProjectReference Include="../../../src/infrastructure/MicCheck.Infrastructure/MicCheck.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,70 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.ApiKeys;
|
||||
using MicCheck.Api.Organizations;
|
||||
using MicCheck.Api.Projects;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Organizations;
|
||||
|
||||
[TestFixture]
|
||||
public class OrganizationTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAnOrganizationIsCreated_ThenCollectionsAreInitializedEmpty()
|
||||
{
|
||||
var organization = new Organization { Name = "Acme" };
|
||||
|
||||
Assert.That(organization.Projects, Is.Empty);
|
||||
Assert.That(organization.Members, Is.Empty);
|
||||
Assert.That(organization.ApiKeys, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnOrganizationIsCreated_ThenNameIsSet()
|
||||
{
|
||||
var organization = new Organization { Name = "Acme" };
|
||||
|
||||
Assert.That(organization.Name, Is.EqualTo("Acme"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAProjectIsAddedToAnOrganization_ThenItAppearsInTheProjectsCollection()
|
||||
{
|
||||
var organization = new Organization { Name = "Acme" };
|
||||
var project = new Project { Name = "My Project", OrganizationId = organization.Id };
|
||||
|
||||
organization.Projects.Add(project);
|
||||
|
||||
Assert.That(organization.Projects, Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnApiKeyIsAddedToAnOrganization_ThenItAppearsInTheApiKeysCollection()
|
||||
{
|
||||
var organization = new Organization { Name = "Acme" };
|
||||
var apiKey = new ApiKey { Key = "hashed-key", Prefix = "abc12345", Name = "CI Key", OrganizationId = organization.Id };
|
||||
|
||||
organization.ApiKeys.Add(apiKey);
|
||||
|
||||
Assert.That(organization.ApiKeys, Has.Count.EqualTo(1));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class OrganizationUserTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAnOrganizationUserIsCreated_ThenRoleDefaultsToUser()
|
||||
{
|
||||
var member = new OrganizationUser { OrganizationId = 1, UserId = 1 };
|
||||
|
||||
Assert.That(member.Role, Is.EqualTo(OrganizationRole.User));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnOrganizationUserRoleIsSetToAdmin_ThenRoleIsAdmin()
|
||||
{
|
||||
var member = new OrganizationUser { OrganizationId = 1, UserId = 1, Role = OrganizationRole.Admin };
|
||||
|
||||
Assert.That(member.Role, Is.EqualTo(OrganizationRole.Admin));
|
||||
}
|
||||
}
|
||||
36
tests/api/MicCheck.Api.Tests.Unit/Projects/ProjectTests.cs
Normal file
36
tests/api/MicCheck.Api.Tests.Unit/Projects/ProjectTests.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.Projects;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Projects;
|
||||
|
||||
[TestFixture]
|
||||
public class ProjectTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAProjectIsCreated_ThenCollectionsAreInitializedEmpty()
|
||||
{
|
||||
var project = new Project { Name = "My Project", OrganizationId = 1 };
|
||||
|
||||
Assert.That(project.Environments, Is.Empty);
|
||||
Assert.That(project.Features, Is.Empty);
|
||||
Assert.That(project.Segments, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAProjectIsCreated_ThenHideDisabledFlagsDefaultsToFalse()
|
||||
{
|
||||
var project = new Project { Name = "My Project", OrganizationId = 1 };
|
||||
|
||||
Assert.That(project.HideDisabledFlags, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAProjectHideDisabledFlagsIsEnabled_ThenThePropertyReflectsTheChange()
|
||||
{
|
||||
var project = new Project { Name = "My Project", OrganizationId = 1 };
|
||||
|
||||
project.HideDisabledFlags = true;
|
||||
|
||||
Assert.That(project.HideDisabledFlags, Is.True);
|
||||
}
|
||||
}
|
||||
100
tests/api/MicCheck.Api.Tests.Unit/Segments/SegmentTests.cs
Normal file
100
tests/api/MicCheck.Api.Tests.Unit/Segments/SegmentTests.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.Segments;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Segments;
|
||||
|
||||
[TestFixture]
|
||||
public class SegmentTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenASegmentIsCreated_ThenRulesCollectionIsInitializedEmpty()
|
||||
{
|
||||
var segment = new Segment { Name = "Premium Users", ProjectId = 1 };
|
||||
|
||||
Assert.That(segment.Rules, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenASegmentIsCreated_ThenNameAndProjectIdAreSet()
|
||||
{
|
||||
var segment = new Segment { Name = "Beta Testers", ProjectId = 5 };
|
||||
|
||||
Assert.That(segment.Name, Is.EqualTo("Beta Testers"));
|
||||
Assert.That(segment.ProjectId, Is.EqualTo(5));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class SegmentRuleTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenASegmentRuleIsCreated_ThenConditionsAndChildRulesAreInitializedEmpty()
|
||||
{
|
||||
var rule = new SegmentRule { SegmentId = 1 };
|
||||
|
||||
Assert.That(rule.Conditions, Is.Empty);
|
||||
Assert.That(rule.ChildRules, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenASegmentRuleIsCreated_ThenParentRuleIdIsNull()
|
||||
{
|
||||
var rule = new SegmentRule { SegmentId = 1 };
|
||||
|
||||
Assert.That(rule.ParentRuleId, Is.Null);
|
||||
}
|
||||
|
||||
[TestCase(SegmentRuleType.All)]
|
||||
[TestCase(SegmentRuleType.Any)]
|
||||
[TestCase(SegmentRuleType.None)]
|
||||
public void WhenASegmentRuleTypeIsSet_ThenTheTypeIsStored(SegmentRuleType type)
|
||||
{
|
||||
var rule = new SegmentRule { SegmentId = 1, Type = type };
|
||||
|
||||
Assert.That(rule.Type, Is.EqualTo(type));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class SegmentConditionTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenASegmentConditionIsCreated_ThenPropertyAndValueAreSet()
|
||||
{
|
||||
var condition = new SegmentCondition
|
||||
{
|
||||
RuleId = 1,
|
||||
Property = "plan",
|
||||
Operator = SegmentConditionOperator.Equal,
|
||||
Value = "premium"
|
||||
};
|
||||
|
||||
Assert.That(condition.Property, Is.EqualTo("plan"));
|
||||
Assert.That(condition.Value, Is.EqualTo("premium"));
|
||||
Assert.That(condition.Operator, Is.EqualTo(SegmentConditionOperator.Equal));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAllSegmentConditionOperatorsAreChecked_ThenAllExpectedValuesExist()
|
||||
{
|
||||
var operators = Enum.GetValues<SegmentConditionOperator>();
|
||||
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.Equal));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.NotEqual));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.GreaterThan));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.GreaterThanOrEqual));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.LessThan));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.LessThanOrEqual));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.Contains));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.NotContains));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.Regex));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.IsSet));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.IsNotSet));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.In));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.NotIn));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.PercentageSplit));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.ModuloValueDivisorRemainder));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.IsTrue));
|
||||
Assert.That(operators, Contains.Item(SegmentConditionOperator.IsFalse));
|
||||
}
|
||||
}
|
||||
64
tests/api/MicCheck.Api.Tests.Unit/Users/UserTests.cs
Normal file
64
tests/api/MicCheck.Api.Tests.Unit/Users/UserTests.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.Users;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Users;
|
||||
|
||||
[TestFixture]
|
||||
public class UserTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAUserIsCreated_ThenOrganizationsCollectionIsInitializedEmpty()
|
||||
{
|
||||
var user = new User
|
||||
{
|
||||
Email = "alice@example.com",
|
||||
PasswordHash = "hashed",
|
||||
FirstName = "Alice",
|
||||
LastName = "Smith"
|
||||
};
|
||||
|
||||
Assert.That(user.Organizations, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAUserIsCreated_ThenIsActiveDefaultsToFalse()
|
||||
{
|
||||
var user = new User
|
||||
{
|
||||
Email = "alice@example.com",
|
||||
PasswordHash = "hashed",
|
||||
FirstName = "Alice",
|
||||
LastName = "Smith"
|
||||
};
|
||||
|
||||
Assert.That(user.IsActive, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAUserIsCreated_ThenIsTwoFactorEnabledDefaultsToFalse()
|
||||
{
|
||||
var user = new User
|
||||
{
|
||||
Email = "alice@example.com",
|
||||
PasswordHash = "hashed",
|
||||
FirstName = "Alice",
|
||||
LastName = "Smith"
|
||||
};
|
||||
|
||||
Assert.That(user.IsTwoFactorEnabled, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAUserIsCreated_ThenLastLoginAtDefaultsToNull()
|
||||
{
|
||||
var user = new User
|
||||
{
|
||||
Email = "alice@example.com",
|
||||
PasswordHash = "hashed",
|
||||
FirstName = "Alice",
|
||||
LastName = "Smith"
|
||||
};
|
||||
|
||||
Assert.That(user.LastLoginAt, Is.Null);
|
||||
}
|
||||
}
|
||||
89
tests/api/MicCheck.Api.Tests.Unit/Webhooks/WebhookTests.cs
Normal file
89
tests/api/MicCheck.Api.Tests.Unit/Webhooks/WebhookTests.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using NUnit.Framework;
|
||||
using MicCheck.Api.Webhooks;
|
||||
|
||||
namespace MicCheck.Api.Tests.Unit.Webhooks;
|
||||
|
||||
[TestFixture]
|
||||
public class WebhookTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAWebhookIsCreated_ThenUrlAndScopeAreSet()
|
||||
{
|
||||
var webhook = new Webhook { Url = "https://example.com/hook", Scope = WebhookScope.Environment };
|
||||
|
||||
Assert.That(webhook.Url, Is.EqualTo("https://example.com/hook"));
|
||||
Assert.That(webhook.Scope, Is.EqualTo(WebhookScope.Environment));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAWebhookIsCreated_ThenSecretDefaultsToNull()
|
||||
{
|
||||
var webhook = new Webhook { Url = "https://example.com/hook", Scope = WebhookScope.Organization };
|
||||
|
||||
Assert.That(webhook.Secret, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAWebhookIsCreated_ThenEnabledDefaultsToFalse()
|
||||
{
|
||||
var webhook = new Webhook { Url = "https://example.com/hook", Scope = WebhookScope.Environment };
|
||||
|
||||
Assert.That(webhook.Enabled, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAllWebhookScopesAreChecked_ThenAllExpectedValuesExist()
|
||||
{
|
||||
var scopes = Enum.GetValues<WebhookScope>();
|
||||
|
||||
Assert.That(scopes, Contains.Item(WebhookScope.Environment));
|
||||
Assert.That(scopes, Contains.Item(WebhookScope.Organization));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class WebhookDeliveryLogTests
|
||||
{
|
||||
[Test]
|
||||
public void WhenAWebhookDeliveryLogIsCreated_ThenRequiredFieldsAreSet()
|
||||
{
|
||||
var log = new WebhookDeliveryLog
|
||||
{
|
||||
WebhookId = 1,
|
||||
EventType = "FLAG_UPDATED",
|
||||
PayloadJson = "{}"
|
||||
};
|
||||
|
||||
Assert.That(log.WebhookId, Is.EqualTo(1));
|
||||
Assert.That(log.EventType, Is.EqualTo("FLAG_UPDATED"));
|
||||
Assert.That(log.PayloadJson, Is.EqualTo("{}"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAWebhookDeliveryLogIsCreated_ThenOptionalFieldsDefaultToNull()
|
||||
{
|
||||
var log = new WebhookDeliveryLog
|
||||
{
|
||||
WebhookId = 1,
|
||||
EventType = "FLAG_UPDATED",
|
||||
PayloadJson = "{}"
|
||||
};
|
||||
|
||||
Assert.That(log.ResponseStatusCode, Is.Null);
|
||||
Assert.That(log.ResponseBody, Is.Null);
|
||||
Assert.That(log.ErrorMessage, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAWebhookDeliveryLogIsCreated_ThenSuccessDefaultsToFalse()
|
||||
{
|
||||
var log = new WebhookDeliveryLog
|
||||
{
|
||||
WebhookId = 1,
|
||||
EventType = "FLAG_UPDATED",
|
||||
PayloadJson = "{}"
|
||||
};
|
||||
|
||||
Assert.That(log.Success, Is.False);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user