using NSubstitute; using PnvPanel.Application.Admin.Nodes; using PnvPanel.Application.Common.Interfaces; using PnvPanel.Application.Common.Models; using PnvPanel.Application.Tests.TestSupport; using Xunit; namespace PnvPanel.Application.Tests.Admin.Nodes; public class RegisterNodeCommandHandlerTests { private readonly IXuiPanelGateway _gateway = Substitute.For(); private readonly ISecretProtector _secretProtector = Substitute.For(); private readonly ICurrentUser _currentUser = Substitute.For(); [Fact] public async Task Handle_WithValidAddress_RegistersNodeWithProtectedPassword() { using var dbContext = InMemoryDbContextFactory.Create(); _gateway.ValidateBaseAddress(Arg.Any()).Returns(Result.Success()); _secretProtector.Protect("secret-password").Returns("protected-secret-password"); var handler = new RegisterNodeCommandHandler( dbContext, _gateway, _secretProtector, _currentUser ); var command = new RegisterNodeCommand( "node-1", "https://node1.example.com", "admin", "secret-password", "eu-west" ); var result = await handler.Handle(command, CancellationToken.None); Assert.True(result.IsSuccess); Assert.Equal("node-1", result.Value.Name); Assert.Equal("admin", result.Value.Username); Assert.Single(dbContext.Nodes.Local); Assert.Equal( "protected-secret-password", dbContext.Nodes.Local.Single().Credentials.ProtectedPassword ); } [Fact] public async Task Handle_WithInvalidBaseAddress_ReturnsValidationErrorWithoutTouchingGateway() { using var dbContext = InMemoryDbContextFactory.Create(); var handler = new RegisterNodeCommandHandler( dbContext, _gateway, _secretProtector, _currentUser ); var command = new RegisterNodeCommand( "node-1", "not-a-uri", "admin", "secret-password", null ); var result = await handler.Handle(command, CancellationToken.None); Assert.False(result.IsSuccess); Assert.Equal(NodeErrors.InvalidBaseAddress, result.Error); _gateway.DidNotReceive().ValidateBaseAddress(Arg.Any()); Assert.Empty(dbContext.Nodes.Local); } [Fact] public async Task Handle_WhenGatewayRejectsBaseAddress_ReturnsFailureWithoutRegisteringNode() { using var dbContext = InMemoryDbContextFactory.Create(); var error = Error.Validation("Nodes.SchemeNotAllowed", "Разрешён только HTTPS."); _gateway.ValidateBaseAddress(Arg.Any()).Returns(Result.Failure(error)); var handler = new RegisterNodeCommandHandler( dbContext, _gateway, _secretProtector, _currentUser ); var command = new RegisterNodeCommand( "node-1", "http://node1.example.com", "admin", "secret-password", null ); var result = await handler.Handle(command, CancellationToken.None); Assert.False(result.IsSuccess); Assert.Equal(error, result.Error); Assert.Empty(dbContext.Nodes.Local); } }