diff --git a/LICENSE.md b/LICENSE.md index 7ab9427..edbe7fe 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 Maksym Sadovnychyy (MAKS-IT) +Copyright (c) 2024 - 2025 Maksym Sadovnychyy (MAKS-IT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MaksIT.Results.Tests/UnitTest1.cs b/MaksIT.Results.Tests/UnitTest1.cs index c6ad5a7..17f3a4d 100644 --- a/MaksIT.Results.Tests/UnitTest1.cs +++ b/MaksIT.Results.Tests/UnitTest1.cs @@ -1,8 +1,137 @@ -namespace MaksIT.Results.Tests { - public class UnitTest1 { - [Fact] - public void Test1() { +using Xunit; +using System.Net; +using MaksIT.Results; +using MaksIT.Results.Mvc; +namespace MaksIT.Results.Tests { + public class ResultTests { + [Fact] + public void Result_Ok_ShouldReturnSuccess() { + // Arrange + var message = "Operation successful"; + + // Act + var result = Result.Ok(message); + + // Assert + Assert.True(result.IsSuccess); + Assert.Contains(message, result.Messages); + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + } + + [Fact] + public void Result_BadRequest_ShouldReturnFailure() { + // Arrange + var message = "Invalid request"; + + // Act + var result = Result.BadRequest(message); + + // Assert + Assert.False(result.IsSuccess); + Assert.Contains(message, result.Messages); + Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode); + } + + [Fact] + public void Result_Generic_Ok_ShouldReturnSuccessWithValue() { + // Arrange + var value = 42; + var message = "Operation successful"; + + // Act + var result = Result.Ok(value, message); + + // Assert + Assert.True(result.IsSuccess); + Assert.Equal(value, result.Value); + Assert.Contains(message, result.Messages); + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + } + + [Fact] + public void Result_Generic_NotFound_ShouldReturnFailureWithNullValue() { + // Arrange + var message = "Resource not found"; + + // Act + var result = Result.NotFound(null, message); + + // Assert + Assert.False(result.IsSuccess); + Assert.Null(result.Value); + Assert.Contains(message, result.Messages); + Assert.Equal(HttpStatusCode.NotFound, result.StatusCode); + } + + [Fact] + public void Result_ToResultOfType_ShouldTransformValue() { + // Arrange + var initialValue = 42; + var transformedValue = "42"; + var result = Result.Ok(initialValue); + + // Act + var transformedResult = result.ToResultOfType(value => value.ToString()); + + // Assert + Assert.True(transformedResult.IsSuccess); + Assert.Equal(transformedValue, transformedResult.Value); + Assert.Equal(result.StatusCode, transformedResult.StatusCode); + } + + [Fact] + public void Result_ToActionResult_ShouldReturnStatusCodeResult() { + // Arrange + var result = Result.Ok("Operation successful"); + + // Act + var actionResult = result.ToActionResult(); + + // Assert + Assert.IsType(actionResult); + var statusCodeResult = actionResult as StatusCodeResult; + Assert.NotNull(statusCodeResult); + Assert.Equal((int)HttpStatusCode.OK, statusCodeResult.StatusCode); + } + + [Fact] + public void Result_ToActionResult_ShouldReturnObjectResultForFailure() { + // Arrange + var errorMessage = "An error occurred"; + var result = Result.BadRequest(errorMessage); + + // Act + var actionResult = result.ToActionResult(); + + // Assert + Assert.IsType(actionResult); + var objectResult = actionResult as ObjectResult; + Assert.NotNull(objectResult); + Assert.Equal((int)HttpStatusCode.BadRequest, objectResult.StatusCode); + Assert.IsType(objectResult.Value); + var problemDetails = objectResult.Value as ProblemDetails; + Assert.NotNull(problemDetails); + Assert.Equal((int)HttpStatusCode.BadRequest, problemDetails.Status); + Assert.Equal("An error occurred", problemDetails.Title); + Assert.Equal(errorMessage, problemDetails.Detail); + } + + [Fact] + public void Result_Generic_ToActionResult_ShouldReturnObjectResultWithValue() { + // Arrange + var value = new { Id = 1, Name = "Test" }; + var result = Result.Ok(value); + + // Act + var actionResult = result.ToActionResult(); + + // Assert + Assert.IsType(actionResult); + var objectResult = actionResult as ObjectResult; + Assert.NotNull(objectResult); + Assert.Equal((int)HttpStatusCode.OK, objectResult.StatusCode); + Assert.Equal(value, objectResult.Value); } } } \ No newline at end of file diff --git a/src/MaksIT.Results/MaksIT.Results.csproj b/src/MaksIT.Results/MaksIT.Results.csproj index 1175c9f..cf3494f 100644 --- a/src/MaksIT.Results/MaksIT.Results.csproj +++ b/src/MaksIT.Results/MaksIT.Results.csproj @@ -4,11 +4,11 @@ net8.0 enable enable - MaksIT.$(MSBuildProjectName.Replace(" ", "_")) + $(MSBuildProjectName.Replace(" ", "_")) MaksIT.Results - 1.0.6 + 1.0.7 Maksym Sadovnychyy MAKS-IT MaksIT.Results @@ -18,10 +18,15 @@ MIT false README.md + LICENSE.md - + + + + + diff --git a/src/MaksIT.Results/Mvc/ObjectResult.cs b/src/MaksIT.Results/Mvc/ObjectResult.cs new file mode 100644 index 0000000..c3564b5 --- /dev/null +++ b/src/MaksIT.Results/Mvc/ObjectResult.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace MaksIT.Results.Mvc; + +public class ObjectResult : IActionResult { + public object? Value { get; } + public int? StatusCode { get; set; } + + public ObjectResult(object? value) { + Value = value; + } + + public async Task ExecuteResultAsync(ActionContext context) { + var response = context.HttpContext.Response; + if (StatusCode.HasValue) { + response.StatusCode = StatusCode.Value; + } + response.ContentType = "application/json"; + if (Value is not null) { + await JsonSerializer.SerializeAsync(response.Body, Value); + } + } +} \ No newline at end of file diff --git a/src/MaksIT.Results/Mvc/ProblemDetails.cs b/src/MaksIT.Results/Mvc/ProblemDetails.cs new file mode 100644 index 0000000..b90a11f --- /dev/null +++ b/src/MaksIT.Results/Mvc/ProblemDetails.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MaksIT.Results.Mvc; + +public class ProblemDetails { + public int? Status { get; set; } + public string? Title { get; set; } + public string? Detail { get; set; } + public string? Instance { get; set; } + public IDictionary Extensions { get; } = new Dictionary(); +} \ No newline at end of file diff --git a/src/MaksIT.Results/Mvc/StatusCodeResult.cs b/src/MaksIT.Results/Mvc/StatusCodeResult.cs new file mode 100644 index 0000000..302ec9f --- /dev/null +++ b/src/MaksIT.Results/Mvc/StatusCodeResult.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Mvc; + + +namespace MaksIT.Results.Mvc; + +public class StatusCodeResult : IActionResult { + public int StatusCode { get; } + + public StatusCodeResult(int statusCode) { + StatusCode = statusCode; + } + + public async Task ExecuteResultAsync(ActionContext context) { + context.HttpContext.Response.StatusCode = StatusCode; + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/MaksIT.Results/Result.cs b/src/MaksIT.Results/Result.cs index 8d14638..2f6b675 100644 --- a/src/MaksIT.Results/Result.cs +++ b/src/MaksIT.Results/Result.cs @@ -1,5 +1,7 @@ -using Microsoft.AspNetCore.Mvc; -using System.Net; +using System.Net; +using Microsoft.AspNetCore.Mvc; +using MaksIT.Results.Mvc; + namespace MaksIT.Results;