Add unit tests for MicCheck.Api.Segments
Covers CreateSegmentRequestValidator, response mapping (incl. nested rules), SegmentsController, and gaps in SegmentService/SegmentEvaluator (FindByIdAsync, not-found paths, nested rules, modulo/percentage edge cases), raising the namespace from 66% to 98% coverage.
This commit is contained in:
@@ -0,0 +1,120 @@
|
|||||||
|
using MicCheck.Api.Segments;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace MicCheck.Api.Tests.Unit.Segments;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class CreateSegmentRequestValidatorTests
|
||||||
|
{
|
||||||
|
private CreateSegmentRequestValidator _validator = null!;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => _validator = new CreateSegmentRequestValidator();
|
||||||
|
|
||||||
|
private static CreateSegmentRequest ValidRequest() => new(
|
||||||
|
"Premium Users",
|
||||||
|
[new CreateSegmentRuleRequest("All", [new CreateSegmentConditionRequest("plan", "Equal", "premium")])]);
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenTheRequestIsValid_ThenValidationSucceeds()
|
||||||
|
{
|
||||||
|
var result = _validator.Validate(ValidRequest());
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenTheNameIsEmpty_ThenValidationFails()
|
||||||
|
{
|
||||||
|
var request = ValidRequest() with { Name = "" };
|
||||||
|
|
||||||
|
var result = _validator.Validate(request);
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.False);
|
||||||
|
Assert.That(result.Errors.Any(e => e.PropertyName == "Name"), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenTheNameExceedsMaximumLength_ThenValidationFails()
|
||||||
|
{
|
||||||
|
var request = ValidRequest() with { Name = new string('a', 201) };
|
||||||
|
|
||||||
|
var result = _validator.Validate(request);
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenRulesIsNull_ThenValidationFails()
|
||||||
|
{
|
||||||
|
var request = ValidRequest() with { Rules = null! };
|
||||||
|
|
||||||
|
var result = _validator.Validate(request);
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenARuleTypeIsInvalid_ThenValidationFails()
|
||||||
|
{
|
||||||
|
var request = new CreateSegmentRequest(
|
||||||
|
"Test",
|
||||||
|
[new CreateSegmentRuleRequest("NotAType", [new CreateSegmentConditionRequest("plan", "Equal", "premium")])]);
|
||||||
|
|
||||||
|
var result = _validator.Validate(request);
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("All")]
|
||||||
|
[TestCase("Any")]
|
||||||
|
[TestCase("None")]
|
||||||
|
[TestCase("all")]
|
||||||
|
public void WhenARuleTypeIsAValidCaseInsensitiveName_ThenValidationSucceeds(string type)
|
||||||
|
{
|
||||||
|
var request = new CreateSegmentRequest(
|
||||||
|
"Test",
|
||||||
|
[new CreateSegmentRuleRequest(type, [new CreateSegmentConditionRequest("plan", "Equal", "premium")])]);
|
||||||
|
|
||||||
|
var result = _validator.Validate(request);
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenAConditionPropertyIsEmpty_ThenValidationFails()
|
||||||
|
{
|
||||||
|
var request = new CreateSegmentRequest(
|
||||||
|
"Test",
|
||||||
|
[new CreateSegmentRuleRequest("All", [new CreateSegmentConditionRequest("", "Equal", "premium")])]);
|
||||||
|
|
||||||
|
var result = _validator.Validate(request);
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenAConditionOperatorIsInvalid_ThenValidationFails()
|
||||||
|
{
|
||||||
|
var request = new CreateSegmentRequest(
|
||||||
|
"Test",
|
||||||
|
[new CreateSegmentRuleRequest("All", [new CreateSegmentConditionRequest("plan", "NotAnOperator", "premium")])]);
|
||||||
|
|
||||||
|
var result = _validator.Validate(request);
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenANestedChildRuleHasAnInvalidOperator_ThenValidationStillSucceedsBecauseChildRulesAreNotValidatedRecursively()
|
||||||
|
{
|
||||||
|
var childRule = new CreateSegmentRuleRequest("All", [new CreateSegmentConditionRequest("plan", "NotAnOperator", "premium")]);
|
||||||
|
var request = new CreateSegmentRequest(
|
||||||
|
"Test",
|
||||||
|
[new CreateSegmentRuleRequest("All", [new CreateSegmentConditionRequest("plan", "Equal", "premium")], [childRule])]);
|
||||||
|
|
||||||
|
var result = _validator.Validate(request);
|
||||||
|
|
||||||
|
Assert.That(result.IsValid, Is.True);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -274,6 +274,51 @@ public class SegmentEvaluatorTests
|
|||||||
Assert.That(_evaluator.Evaluate(segment, [], "another-user"), Is.False);
|
Assert.That(_evaluator.Evaluate(segment, [], "another-user"), Is.False);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenModuloConditionValueIsMalformed_ThenSegmentDoesNotMatch()
|
||||||
|
{
|
||||||
|
var segment = BuildSegment(SegmentRuleType.All,
|
||||||
|
Condition("userId", SegmentConditionOperator.ModuloValueDivisorRemainder, "not-a-modulo-spec"));
|
||||||
|
var traits = new[] { Trait("userId", "9") };
|
||||||
|
|
||||||
|
Assert.That(_evaluator.Evaluate(segment, traits), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenModuloDivisorIsZero_ThenSegmentDoesNotMatch()
|
||||||
|
{
|
||||||
|
var segment = BuildSegment(SegmentRuleType.All,
|
||||||
|
Condition("userId", SegmentConditionOperator.ModuloValueDivisorRemainder, "0|0"));
|
||||||
|
var traits = new[] { Trait("userId", "9") };
|
||||||
|
|
||||||
|
Assert.That(_evaluator.Evaluate(segment, traits), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenPercentageSplitValueIsNotANumber_ThenSegmentDoesNotMatch()
|
||||||
|
{
|
||||||
|
var segment = BuildSegment(SegmentRuleType.All,
|
||||||
|
Condition("", SegmentConditionOperator.PercentageSplit, "not-a-number"));
|
||||||
|
|
||||||
|
Assert.That(_evaluator.Evaluate(segment, [], "any-user"), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenARuleHasAChildRuleThatFails_ThenTheParentRuleDoesNotMatchEvenIfItsOwnConditionsPass()
|
||||||
|
{
|
||||||
|
var segment = new Segment { Name = "Test", ProjectId = 1, CreatedAt = DateTimeOffset.UtcNow };
|
||||||
|
var parent = new SegmentRule { Type = SegmentRuleType.All };
|
||||||
|
parent.Conditions.Add(Condition("plan", SegmentConditionOperator.Equal, "premium"));
|
||||||
|
var child = new SegmentRule { Type = SegmentRuleType.All };
|
||||||
|
child.Conditions.Add(Condition("country", SegmentConditionOperator.Equal, "US"));
|
||||||
|
parent.ChildRules.Add(child);
|
||||||
|
segment.Rules.Add(parent);
|
||||||
|
|
||||||
|
var traits = new[] { Trait("plan", "premium"), Trait("country", "UK") };
|
||||||
|
|
||||||
|
Assert.That(_evaluator.Evaluate(segment, traits), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void WhenRuleTypeIsAny_ThenAtLeastOneConditionMustMatch()
|
public void WhenRuleTypeIsAny_ThenAtLeastOneConditionMustMatch()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
using MicCheck.Api.Segments;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace MicCheck.Api.Tests.Unit.Segments;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class SegmentResponseTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void WhenMappingASegmentWithNoRules_ThenTheResponseHasAnEmptyRulesList()
|
||||||
|
{
|
||||||
|
var segment = new Segment { Id = 1, Name = "Premium Users", ProjectId = 5, CreatedAt = DateTimeOffset.UtcNow };
|
||||||
|
|
||||||
|
var response = SegmentResponse.From(segment);
|
||||||
|
|
||||||
|
Assert.That(response.Id, Is.EqualTo(segment.Id));
|
||||||
|
Assert.That(response.Name, Is.EqualTo("Premium Users"));
|
||||||
|
Assert.That(response.ProjectId, Is.EqualTo(5));
|
||||||
|
Assert.That(response.Rules, Is.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenMappingASegmentWithTopLevelRules_ThenOnlyRulesWithoutAParentAreAtTheTopLevel()
|
||||||
|
{
|
||||||
|
var segment = new Segment { Id = 1, Name = "Test", ProjectId = 1, CreatedAt = DateTimeOffset.UtcNow };
|
||||||
|
var topLevelRule = new SegmentRule { Id = 1, SegmentId = 1, Type = SegmentRuleType.All };
|
||||||
|
var childRule = new SegmentRule { Id = 2, SegmentId = 1, ParentRuleId = 1, Type = SegmentRuleType.Any };
|
||||||
|
segment.Rules.Add(topLevelRule);
|
||||||
|
segment.Rules.Add(childRule);
|
||||||
|
|
||||||
|
var response = SegmentResponse.From(segment);
|
||||||
|
|
||||||
|
Assert.That(response.Rules, Has.Count.EqualTo(1));
|
||||||
|
Assert.That(response.Rules[0].Id, Is.EqualTo(topLevelRule.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenMappingARuleWithChildRules_ThenChildRulesAreNestedUnderTheParent()
|
||||||
|
{
|
||||||
|
var parent = new SegmentRule { Id = 1, SegmentId = 1, Type = SegmentRuleType.All };
|
||||||
|
var child = new SegmentRule { Id = 2, SegmentId = 1, ParentRuleId = 1, Type = SegmentRuleType.Any };
|
||||||
|
var allRules = new List<SegmentRule> { parent, child };
|
||||||
|
|
||||||
|
var response = SegmentRuleResponse.From(parent, allRules);
|
||||||
|
|
||||||
|
Assert.That(response.Type, Is.EqualTo(nameof(SegmentRuleType.All)));
|
||||||
|
Assert.That(response.ChildRules, Has.Count.EqualTo(1));
|
||||||
|
Assert.That(response.ChildRules[0].Id, Is.EqualTo(child.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenMappingARuleWithConditions_ThenEachConditionIsMapped()
|
||||||
|
{
|
||||||
|
var rule = new SegmentRule { Id = 1, SegmentId = 1, Type = SegmentRuleType.All };
|
||||||
|
rule.Conditions.Add(new SegmentCondition { Id = 1, RuleId = 1, Property = "plan", Operator = SegmentConditionOperator.Equal, Value = "premium" });
|
||||||
|
|
||||||
|
var response = SegmentRuleResponse.From(rule, [rule]);
|
||||||
|
|
||||||
|
Assert.That(response.Conditions, Has.Count.EqualTo(1));
|
||||||
|
Assert.That(response.Conditions[0].Property, Is.EqualTo("plan"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenMappingACondition_ThenIdPropertyOperatorAndValueAreCopied()
|
||||||
|
{
|
||||||
|
var condition = new SegmentCondition { Id = 7, RuleId = 1, Property = "plan", Operator = SegmentConditionOperator.Contains, Value = "premium" };
|
||||||
|
|
||||||
|
var response = SegmentConditionResponse.From(condition);
|
||||||
|
|
||||||
|
Assert.That(response.Id, Is.EqualTo(7));
|
||||||
|
Assert.That(response.Property, Is.EqualTo("plan"));
|
||||||
|
Assert.That(response.Operator, Is.EqualTo(nameof(SegmentConditionOperator.Contains)));
|
||||||
|
Assert.That(response.Value, Is.EqualTo("premium"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenCreatingASegmentSummaryResponse_ThenIdAndNameAreSet()
|
||||||
|
{
|
||||||
|
var response = new SegmentSummaryResponse(1, "Premium Users");
|
||||||
|
|
||||||
|
Assert.That(response.Id, Is.EqualTo(1));
|
||||||
|
Assert.That(response.Name, Is.EqualTo("Premium Users"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -136,4 +136,51 @@ public class SegmentServiceTests
|
|||||||
|
|
||||||
Assert.That(segments, Has.Count.EqualTo(2));
|
Assert.That(segments, Has.Count.EqualTo(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenFindingASegmentByIdThatExists_ThenTheSegmentIsReturned()
|
||||||
|
{
|
||||||
|
var segment = await _service.CreateAsync(ProjectId, "Segment", [SingleConditionRule()]);
|
||||||
|
|
||||||
|
var found = await _service.FindByIdAsync(segment.Id);
|
||||||
|
|
||||||
|
Assert.That(found, Is.Not.Null);
|
||||||
|
Assert.That(found!.Id, Is.EqualTo(segment.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenFindingASegmentByIdThatDoesNotExist_ThenNullIsReturned()
|
||||||
|
{
|
||||||
|
var found = await _service.FindByIdAsync(999);
|
||||||
|
|
||||||
|
Assert.That(found, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenUpdatingASegmentThatDoesNotExist_ThenKeyNotFoundExceptionIsThrown()
|
||||||
|
{
|
||||||
|
Assert.ThrowsAsync<KeyNotFoundException>(() =>
|
||||||
|
_service.UpdateAsync(999, "Renamed", [SingleConditionRule()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WhenDeletingASegmentThatDoesNotExist_ThenNoExceptionIsThrown()
|
||||||
|
{
|
||||||
|
Assert.DoesNotThrowAsync(() => _service.DeleteAsync(999));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenCreatingASegmentWithNestedChildRules_ThenChildRulesArePersistedWithTheParentAsTheirParent()
|
||||||
|
{
|
||||||
|
var childRule = new SegmentRuleDefinition(SegmentRuleType.Any, [new SegmentConditionDefinition("country", SegmentConditionOperator.Equal, "US")]);
|
||||||
|
var parentRule = new SegmentRuleDefinition(SegmentRuleType.All, [new SegmentConditionDefinition("plan", SegmentConditionOperator.Equal, "premium")], [childRule]);
|
||||||
|
|
||||||
|
var segment = await _service.CreateAsync(ProjectId, "Nested", [parentRule]);
|
||||||
|
|
||||||
|
var persistedRules = _segmentRules.Where(r => r.SegmentId == segment.Id).ToList();
|
||||||
|
var parent = persistedRules.Single(r => r.ParentRuleId == null);
|
||||||
|
var child = persistedRules.Single(r => r.ParentRuleId == parent.Id);
|
||||||
|
|
||||||
|
Assert.That(child.Conditions.Single().Property, Is.EqualTo("country"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,197 @@
|
|||||||
|
using MicCheck.Api.Audit;
|
||||||
|
using MicCheck.Api.Common;
|
||||||
|
using MicCheck.Api.Data;
|
||||||
|
using MicCheck.Api.Organizations;
|
||||||
|
using MicCheck.Api.Projects;
|
||||||
|
using MicCheck.Api.Segments;
|
||||||
|
using MicCheck.Api.Tests.Unit.TestSupport;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace MicCheck.Api.Tests.Unit.Segments;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class SegmentsControllerTests
|
||||||
|
{
|
||||||
|
private Mock<IMicCheckDbContext> _db = null!;
|
||||||
|
private List<Segment> _segments = null!;
|
||||||
|
private List<SegmentRule> _segmentRules = null!;
|
||||||
|
private List<SegmentCondition> _segmentConditions = null!;
|
||||||
|
private SegmentsController _controller = null!;
|
||||||
|
private const int OrganizationId = 1;
|
||||||
|
private const int ProjectId = 1;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
_db = new Mock<IMicCheckDbContext>();
|
||||||
|
|
||||||
|
_db.SetupDbSet(c => c.Organizations, [
|
||||||
|
new Organization { Id = OrganizationId, Name = "Test Org", CreatedAt = DateTimeOffset.UtcNow }
|
||||||
|
]);
|
||||||
|
_db.SetupDbSet(c => c.Projects, [
|
||||||
|
new Project { Id = ProjectId, Name = "Test Project", OrganizationId = OrganizationId, CreatedAt = DateTimeOffset.UtcNow }
|
||||||
|
]);
|
||||||
|
_segments = [];
|
||||||
|
_db.SetupDbSetWithGeneratedIds(c => c.Segments, _segments);
|
||||||
|
_segmentRules = [];
|
||||||
|
_db.SetupDbSetWithGeneratedIds(c => c.SegmentRules, _segmentRules);
|
||||||
|
_segmentConditions = [];
|
||||||
|
_db.SetupDbSetWithGeneratedIds(c => c.SegmentConditions, _segmentConditions);
|
||||||
|
|
||||||
|
var webhookQueue = new MicCheck.Api.Webhooks.WebhookQueue();
|
||||||
|
var auditService = new Mock<AuditService>(_db.Object, null!, webhookQueue);
|
||||||
|
auditService.Setup(a => a.LogAsync(
|
||||||
|
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
||||||
|
It.IsAny<int>(), It.IsAny<int?>(), It.IsAny<int?>(),
|
||||||
|
It.IsAny<string?>(), It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
var service = new SegmentService(_db.Object, auditService.Object);
|
||||||
|
_controller = new SegmentsController(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CreateSegmentRequest ValidRequest(string name = "Premium Users") => new(
|
||||||
|
name,
|
||||||
|
[new CreateSegmentRuleRequest("All", [new CreateSegmentConditionRequest("plan", "Equal", "premium")])]);
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenListingSegmentsForAProject_ThenAllSegmentsAreReturnedInAPage()
|
||||||
|
{
|
||||||
|
await _controller.Create(ProjectId, ValidRequest("Segment A"), CancellationToken.None);
|
||||||
|
await _controller.Create(ProjectId, ValidRequest("Segment B"), CancellationToken.None);
|
||||||
|
|
||||||
|
var result = await _controller.List(ProjectId);
|
||||||
|
|
||||||
|
var ok = result.Result as OkObjectResult;
|
||||||
|
var page = (PaginatedResponse<SegmentResponse>)ok!.Value!;
|
||||||
|
Assert.That(page.Count, Is.EqualTo(2));
|
||||||
|
Assert.That(page.Results, Has.Count.EqualTo(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenListingSegmentsWithAPageSizeAboveTheMaximum_ThenThePageSizeIsClampedTo100()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
await _controller.Create(ProjectId, ValidRequest($"Segment {i}"), CancellationToken.None);
|
||||||
|
|
||||||
|
var result = await _controller.List(ProjectId, page: 1, pageSize: 1000);
|
||||||
|
|
||||||
|
var ok = result.Result as OkObjectResult;
|
||||||
|
var page = (PaginatedResponse<SegmentResponse>)ok!.Value!;
|
||||||
|
Assert.That(page.Results, Has.Count.EqualTo(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenCreatingASegmentWithValidData_ThenACreatedResultWithTheSegmentIsReturned()
|
||||||
|
{
|
||||||
|
var result = await _controller.Create(ProjectId, ValidRequest(), CancellationToken.None);
|
||||||
|
|
||||||
|
var created = result.Result as CreatedAtActionResult;
|
||||||
|
Assert.That(created, Is.Not.Null);
|
||||||
|
Assert.That(((SegmentResponse)created!.Value!).Name, Is.EqualTo("Premium Users"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenCreatingASegmentThatExceedsTheProjectLimit_ThenBadRequestIsReturned()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
_segments.Add(new Segment { Id = i + 1, Name = $"segment_{i}", ProjectId = ProjectId, CreatedAt = DateTimeOffset.UtcNow });
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _controller.Create(ProjectId, ValidRequest("overflow"), CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.That(result.Result, Is.InstanceOf<BadRequestObjectResult>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenGettingASegmentByIdInTheCorrectProject_ThenTheSegmentIsReturned()
|
||||||
|
{
|
||||||
|
var created = await _controller.Create(ProjectId, ValidRequest(), CancellationToken.None);
|
||||||
|
var segmentId = ((SegmentResponse)((CreatedAtActionResult)created.Result!).Value!).Id;
|
||||||
|
|
||||||
|
var result = await _controller.GetById(ProjectId, segmentId, CancellationToken.None);
|
||||||
|
|
||||||
|
var ok = result.Result as OkObjectResult;
|
||||||
|
Assert.That(ok, Is.Not.Null);
|
||||||
|
Assert.That(((SegmentResponse)ok!.Value!).Id, Is.EqualTo(segmentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenGettingASegmentThatDoesNotExist_ThenNotFoundIsReturned()
|
||||||
|
{
|
||||||
|
var result = await _controller.GetById(ProjectId, 999, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.That(result.Result, Is.InstanceOf<NotFoundResult>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenGettingASegmentThatBelongsToADifferentProject_ThenNotFoundIsReturned()
|
||||||
|
{
|
||||||
|
var created = await _controller.Create(ProjectId, ValidRequest(), CancellationToken.None);
|
||||||
|
var segmentId = ((SegmentResponse)((CreatedAtActionResult)created.Result!).Value!).Id;
|
||||||
|
|
||||||
|
var result = await _controller.GetById(999, segmentId, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.That(result.Result, Is.InstanceOf<NotFoundResult>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenUpdatingASegmentThatDoesNotExist_ThenNotFoundIsReturned()
|
||||||
|
{
|
||||||
|
var result = await _controller.Update(ProjectId, 999, ValidRequest(), CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.That(result.Result, Is.InstanceOf<NotFoundResult>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenUpdatingASegmentInTheCorrectProject_ThenTheUpdatedSegmentIsReturned()
|
||||||
|
{
|
||||||
|
var created = await _controller.Create(ProjectId, ValidRequest(), CancellationToken.None);
|
||||||
|
var segmentId = ((SegmentResponse)((CreatedAtActionResult)created.Result!).Value!).Id;
|
||||||
|
|
||||||
|
var result = await _controller.Update(ProjectId, segmentId, ValidRequest("Renamed"), CancellationToken.None);
|
||||||
|
|
||||||
|
var ok = result.Result as OkObjectResult;
|
||||||
|
Assert.That(ok, Is.Not.Null);
|
||||||
|
Assert.That(((SegmentResponse)ok!.Value!).Name, Is.EqualTo("Renamed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenUpdatingASegmentWithTooManyConditions_ThenBadRequestIsReturned()
|
||||||
|
{
|
||||||
|
var created = await _controller.Create(ProjectId, ValidRequest(), CancellationToken.None);
|
||||||
|
var segmentId = ((SegmentResponse)((CreatedAtActionResult)created.Result!).Value!).Id;
|
||||||
|
|
||||||
|
var conditions = Enumerable.Range(0, 101)
|
||||||
|
.Select(i => new CreateSegmentConditionRequest($"prop_{i}", "Equal", "val"))
|
||||||
|
.ToList();
|
||||||
|
var overflowRequest = new CreateSegmentRequest("Too Many", [new CreateSegmentRuleRequest("All", conditions)]);
|
||||||
|
|
||||||
|
var result = await _controller.Update(ProjectId, segmentId, overflowRequest, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.That(result.Result, Is.InstanceOf<BadRequestObjectResult>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenDeletingASegmentThatDoesNotExist_ThenNotFoundIsReturned()
|
||||||
|
{
|
||||||
|
var result = await _controller.Delete(ProjectId, 999, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<NotFoundResult>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task WhenDeletingASegmentInTheCorrectProject_ThenNoContentIsReturnedAndTheSegmentIsRemoved()
|
||||||
|
{
|
||||||
|
var created = await _controller.Create(ProjectId, ValidRequest(), CancellationToken.None);
|
||||||
|
var segmentId = ((SegmentResponse)((CreatedAtActionResult)created.Result!).Value!).Id;
|
||||||
|
|
||||||
|
var result = await _controller.Delete(ProjectId, segmentId, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<NoContentResult>());
|
||||||
|
Assert.That(_segments.Any(s => s.Id == segmentId), Is.False);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user