diff --git a/tests/ScadaLink.ManagementService.Tests/ManagementActorTests.cs b/tests/ScadaLink.ManagementService.Tests/ManagementActorTests.cs new file mode 100644 index 0000000..1411032 --- /dev/null +++ b/tests/ScadaLink.ManagementService.Tests/ManagementActorTests.cs @@ -0,0 +1,300 @@ +using Akka.Actor; +using Akka.TestKit.Xunit2; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; +using NSubstitute; +using NSubstitute.ExceptionExtensions; +using ScadaLink.Commons.Entities.Instances; +using ScadaLink.Commons.Entities.Templates; +using ScadaLink.Commons.Interfaces.Repositories; +using ScadaLink.Commons.Interfaces.Services; +using ScadaLink.Commons.Messages.Management; +using ScadaLink.Commons.Types; +using ScadaLink.ManagementService; +using ScadaLink.TemplateEngine.Services; + +namespace ScadaLink.ManagementService.Tests; + +public class ManagementActorTests : TestKit, IDisposable +{ + private readonly ITemplateEngineRepository _templateRepo; + private readonly IAuditService _auditService; + private readonly ServiceCollection _services; + + public ManagementActorTests() + { + _templateRepo = Substitute.For(); + _auditService = Substitute.For(); + + _services = new ServiceCollection(); + _services.AddScoped(_ => _templateRepo); + _services.AddScoped(_ => _auditService); + _services.AddScoped(); + } + + private IActorRef CreateActor() + { + var sp = _services.BuildServiceProvider(); + return Sys.ActorOf(Props.Create(() => new ManagementActor( + sp, NullLogger.Instance))); + } + + private static ManagementEnvelope Envelope(object command, params string[] roles) => + new(new AuthenticatedUser("testuser", "Test User", roles, Array.Empty()), + command, Guid.NewGuid().ToString("N")); + + void IDisposable.Dispose() + { + Shutdown(); + } + + // ======================================================================== + // 1. Authorization test -- admin command with wrong role + // ======================================================================== + + [Fact] + public void CreateSiteCommand_WithDesignRole_ReturnsUnauthorized() + { + var actor = CreateActor(); + var envelope = Envelope(new CreateSiteCommand("Site1", "SITE1", "Desc"), "Design"); + + actor.Tell(envelope); + + var response = ExpectMsg(TimeSpan.FromSeconds(5)); + Assert.Contains("Admin", response.Message); + Assert.Equal(envelope.CorrelationId, response.CorrelationId); + } + + [Fact] + public void CreateSiteCommand_WithNoRoles_ReturnsUnauthorized() + { + var actor = CreateActor(); + var envelope = Envelope(new CreateSiteCommand("Site1", "SITE1", null)); + + actor.Tell(envelope); + + var response = ExpectMsg(TimeSpan.FromSeconds(5)); + Assert.Contains("Admin", response.Message); + } + + [Fact] + public void DeploymentCommand_WithDesignRole_ReturnsUnauthorized() + { + var actor = CreateActor(); + var envelope = Envelope(new CreateInstanceCommand("Inst1", 1, 1), "Design"); + + actor.Tell(envelope); + + var response = ExpectMsg(TimeSpan.FromSeconds(5)); + Assert.Contains("Deployment", response.Message); + } + + // ======================================================================== + // 2. Read-only query passes without special role + // ======================================================================== + + [Fact] + public void ListTemplatesCommand_WithNoRoles_ReturnsSuccess() + { + var templates = new List