using Grpc.Core; using Mishima.Nexus.Wire.V1; using Robotico.Result.Errors; using Xunit; namespace Robotico.Nexus.Client.Tests; public class NexusWireStatusTests { [Fact] public void ToResult_Succeeds_WhenStatusIsOk() { Robotico.Result.Result result = NexusWireStatus.ToResult(new NexusStatus { Code = "OK" }); Assert.True(result.IsSuccess()); } [Fact] public void ToResult_Fails_WhenStatusIsNull() { Robotico.Result.Result result = NexusWireStatus.ToResult((NexusStatus?)null); Assert.True(result.IsError(out IError? error)); Assert.Equal(NexusErrors.WireFailed, error!.Code); } [Fact] public void ToResult_Fails_WithCodeAndMessage_FromStatus() { Robotico.Result.Result result = NexusWireStatus.ToResult(new NexusStatus { Code = "NXS_FOO", Message = "boom" }); Assert.True(result.IsError(out IError? error)); Assert.Equal("NXS_FOO", error!.Code); Assert.Equal("boom", error.Message); } [Fact] public void ToResult_Fails_WithFallbackCodeAndMessage_WhenBlank() { Robotico.Result.Result result = NexusWireStatus.ToResult(new NexusStatus { Code = string.Empty, Message = string.Empty }); Assert.True(result.IsError(out IError? error)); Assert.Equal(NexusErrors.WireFailed, error!.Code); Assert.Equal("Nexus call failed.", error.Message); } [Fact] public void ToResultGeneric_CarriesValue_OnSuccess() { Robotico.Result.Result result = NexusWireStatus.ToResult(new NexusStatus { Code = "OK" }, 42); Assert.True(result.IsSuccess(out int value, out _)); Assert.Equal(42, value); } [Fact] public void ToResultGeneric_PropagatesError_OnFailure() { Robotico.Result.Result result = NexusWireStatus.ToResult(new NexusStatus { Code = "NXS_BAD", Message = "bad" }, 42); Assert.True(result.IsError(out IError? error)); Assert.Equal("NXS_BAD", error!.Code); } [Fact] public void IsOk_True_ForOkStatus() { Assert.True(NexusWireStatus.IsOk(new NexusStatus { Code = "OK" })); } [Fact] public void IsOk_False_ForNullOrNonOkStatus() { Assert.False(NexusWireStatus.IsOk(null)); Assert.False(NexusWireStatus.IsOk(new NexusStatus { Code = "NXS_BAD" })); } [Theory] [InlineData(StatusCode.OK, NexusErrors.WireFailed)] [InlineData(StatusCode.Cancelled, NexusErrors.Unavailable)] [InlineData(StatusCode.Unknown, NexusErrors.WireFailed)] [InlineData(StatusCode.InvalidArgument, NexusErrors.InvalidArgument)] [InlineData(StatusCode.DeadlineExceeded, NexusErrors.Unavailable)] [InlineData(StatusCode.NotFound, NexusErrors.NotFound)] [InlineData(StatusCode.AlreadyExists, NexusErrors.AlreadyExists)] [InlineData(StatusCode.PermissionDenied, NexusErrors.WireFailed)] [InlineData(StatusCode.ResourceExhausted, NexusErrors.Unavailable)] [InlineData(StatusCode.FailedPrecondition, NexusErrors.InvalidArgument)] [InlineData(StatusCode.Aborted, NexusErrors.WireFailed)] [InlineData(StatusCode.OutOfRange, NexusErrors.InvalidArgument)] [InlineData(StatusCode.Unimplemented, NexusErrors.WireFailed)] [InlineData(StatusCode.Internal, NexusErrors.WireFailed)] [InlineData(StatusCode.Unavailable, NexusErrors.Unavailable)] [InlineData(StatusCode.DataLoss, NexusErrors.WireFailed)] [InlineData(StatusCode.Unauthenticated, NexusErrors.WireFailed)] public void FromException_MapsEveryGrpcStatusCode(StatusCode statusCode, string expectedCode) { RpcException exception = new(new Status(statusCode, "detail message")); IError error = NexusWireStatus.FromException(exception); Assert.Equal(expectedCode, error.Code); Assert.Contains("detail message", error.Message, StringComparison.Ordinal); } [Fact] public void FromException_FallsBackTo_ExceptionMessage_WhenDetailBlank() { RpcException exception = new(new Status(StatusCode.Internal, string.Empty)); IError error = NexusWireStatus.FromException(exception); Assert.Contains(exception.Message, error.Message, StringComparison.Ordinal); } }