diff --git a/Persistence.API/Controllers/TechMessagesController.cs b/Persistence.API/Controllers/TechMessagesController.cs index 16db89c..47d79d5 100644 --- a/Persistence.API/Controllers/TechMessagesController.cs +++ b/Persistence.API/Controllers/TechMessagesController.cs @@ -1,10 +1,12 @@ -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using Persistence.Models; using Persistence.Repositories; namespace Persistence.API.Controllers { [ApiController] + [Authorize] [Route("api/[controller]")] public class TechMessagesController : ControllerBase, ITechMessages { @@ -44,7 +46,7 @@ namespace Persistence.API.Controllers { var result = await techMessagesRepository.InsertRange(dtos, token); - return Ok(result); + return CreatedAtAction(nameof(InsertRange), result); } } } diff --git a/Persistence.Client/Clients/ISetpointClient.cs b/Persistence.Client/Clients/ISetpointClient.cs index 49733f0..72d76e1 100644 --- a/Persistence.Client/Clients/ISetpointClient.cs +++ b/Persistence.Client/Clients/ISetpointClient.cs @@ -4,7 +4,7 @@ using Refit; namespace Persistence.Client.Clients; /// -/// Интерфейс для тестирования API, предназначенного для работы с уставками +/// Интерфейс клиента для работы с уставками /// public interface ISetpointClient { diff --git a/Persistence.Client/Clients/ITechMessagesClient.cs b/Persistence.Client/Clients/ITechMessagesClient.cs new file mode 100644 index 0000000..1426b54 --- /dev/null +++ b/Persistence.Client/Clients/ITechMessagesClient.cs @@ -0,0 +1,25 @@ +using Persistence.Models; +using Refit; + +namespace Persistence.Client.Clients +{ + /// + /// Интерфейс клиента для хранения технологических сообщений + /// + public interface ITechMessagesClient + { + private const string BaseRoute = "/api/techMessages"; + + [Get($"{BaseRoute}")] + Task>> GetPage([Query] RequestDto request, CancellationToken token); + + [Post($"{BaseRoute}")] + Task> InsertRange([Body] IEnumerable dtos, CancellationToken token); + + [Get($"{BaseRoute}/systems")] + Task>> GetSystems(CancellationToken token); + + [Get($"{BaseRoute}/statistics")] + Task> GetStatistics(int importantId, string autoDrillingSystem, CancellationToken token); + } +} diff --git a/Persistence.Client/Clients/ITimeSeriesClient.cs b/Persistence.Client/Clients/ITimeSeriesClient.cs index 8f7ef0e..349337b 100644 --- a/Persistence.Client/Clients/ITimeSeriesClient.cs +++ b/Persistence.Client/Clients/ITimeSeriesClient.cs @@ -1,5 +1,4 @@ -using Microsoft.AspNetCore.Mvc; -using Persistence.Models; +using Persistence.Models; using Refit; namespace Persistence.Client.Clients; diff --git a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs new file mode 100644 index 0000000..9eb0e9d --- /dev/null +++ b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs @@ -0,0 +1,178 @@ +using System.Net; +using Microsoft.Extensions.DependencyInjection; +using Persistence.Client; +using Persistence.Client.Clients; +using Persistence.Database.Entity; +using Persistence.Models; +using Xunit; + +namespace Persistence.IntegrationTests.Controllers +{ + public class TechMessagesControllerTest : BaseIntegrationTest + { + private readonly ITechMessagesClient techMessagesClient; + public TechMessagesControllerTest(WebAppFactoryFixture factory) : base(factory) + { + var scope = factory.Services.CreateScope(); + var persistenceClientFactory = scope.ServiceProvider + .GetRequiredService(); + + techMessagesClient = persistenceClientFactory.GetClient(); + } + + [Fact] + public async Task GetPage_returns_success() + { + //arrange + dbContext.CleanupDbSet(); + var requestDto = new RequestDto() + { + Skip = 1, + Take = 2, + SortSettings = nameof(TechMessageDto.ImportantId) + }; + + //act + var response = await techMessagesClient.GetPage(requestDto, new CancellationToken()); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.Empty(response.Content.Items); + Assert.Equal(requestDto.Skip, response.Content.Skip); + Assert.Equal(requestDto.Take, response.Content.Take); + } + + [Fact] + public async Task GetPage_AfterSave_returns_success() + { + //arrange + var dtos = await InsertRange(); + var dtosCount = dtos.Count(); + var requestDto = new RequestDto() + { + Skip = 0, + Take = 2, + SortSettings = nameof(TechMessageDto.ImportantId) + }; + + //act + var response = await techMessagesClient.GetPage(requestDto, new CancellationToken()); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.Equal(dtosCount, response.Content.Count); + } + + [Fact] + public async Task InsertRange_returns_success() + { + await InsertRange(); + } + + [Fact] + public async Task GetSystems_returns_success() + { + //act + dbContext.CleanupDbSet(); + var response = await techMessagesClient.GetSystems(new CancellationToken()); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.Empty(response.Content); + } + + [Fact] + public async Task GetSystems_AfterSave_returns_success() + { + //arrange + var dtos = await InsertRange(); + var systems = dtos + .Select(e => e.AutoDrillingSystem) + .Distinct() + .ToArray(); + + //act + var response = await techMessagesClient.GetSystems(new CancellationToken()); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + string?[]? content = response.Content?.ToArray(); + Assert.Equal(systems, content); + } + + [Fact] + public async Task GetStatistics_returns_success() + { + //arrange + dbContext.CleanupDbSet(); + var imortantId = 1; + var autoDrillingSystem = nameof(TechMessageDto.AutoDrillingSystem); + + //act + var response = await techMessagesClient.GetStatistics(imortantId, autoDrillingSystem, new CancellationToken()); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(0, response.Content); + } + + [Fact] + public async Task GetStatistics_AfterSave_returns_success() + { + //arrange + var imortantId = 1; + var autoDrillingSystem = nameof(TechMessageDto.AutoDrillingSystem); + var dtos = await InsertRange(); + var filteredDtos = dtos.Where(e => e.ImportantId == imortantId && e.AutoDrillingSystem == e.AutoDrillingSystem); + + //act + var response = await techMessagesClient.GetStatistics(imortantId, autoDrillingSystem, new CancellationToken()); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(filteredDtos.Count(), response.Content); + } + + public async Task> InsertRange() + { + //arrange + var dtos = new List() + { + new TechMessageDto() + { + EventId = Guid.NewGuid(), + ImportantId = 1, + OccurrenceDate = DateTimeOffset.UtcNow, + Depth = 1.11, + MessageText = nameof(TechMessageDto.MessageText), + AutoDrillingSystem = nameof(TechMessageDto.AutoDrillingSystem), + UserId = Guid.NewGuid() + }, + new TechMessageDto() + { + EventId = Guid.NewGuid(), + ImportantId = 2, + OccurrenceDate = DateTimeOffset.UtcNow, + Depth = 2.22, + MessageText = nameof(TechMessageDto.MessageText), + AutoDrillingSystem = nameof(TechMessageDto.AutoDrillingSystem), + UserId = Guid.NewGuid() + } + }; + + + //act + var response = await techMessagesClient.InsertRange(dtos, new CancellationToken()); + + //assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + Assert.Equal(dtos.Count, response.Content); + + return dtos; + } + } +} diff --git a/Persistence.IntegrationTests/Extensions/EFCoreExtensions.cs b/Persistence.IntegrationTests/Extensions/EFCoreExtensions.cs new file mode 100644 index 0000000..6b09587 --- /dev/null +++ b/Persistence.IntegrationTests/Extensions/EFCoreExtensions.cs @@ -0,0 +1,14 @@ +using Persistence.Database.Model; + +namespace Persistence.IntegrationTests.Extensions; + +public static class EFCoreExtensions +{ + public static void CleanupDbSet(this PersistenceDbContext dbContext) + where T : class + { + var dbset = dbContext.Set(); + dbset.RemoveRange(dbset); + dbContext.SaveChanges(); + } +} diff --git a/Persistence.Repository/Data/SetpointDto.cs b/Persistence.Repository/Data/SetpointDto.cs deleted file mode 100644 index 4a20aa4..0000000 --- a/Persistence.Repository/Data/SetpointDto.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Persistence.Repository.Data -{ - /// - /// Модель для работы с уставкой - /// - public class SetpointDto - { - /// - /// Идентификатор уставки - /// - public int Id { get; set; } - - /// - /// Значение уставки - /// - public required object Value { get; set; } - - /// - /// Дата сохранения уставки - /// - public DateTimeOffset Edit { get; set; } - - /// - /// Ключ пользователя - /// - public int IdUser { get; set; } - } -} diff --git a/Persistence.Repository/Repositories/TechMessagesRepository.cs b/Persistence.Repository/Repositories/TechMessagesRepository.cs index f5ddb35..9abda86 100644 --- a/Persistence.Repository/Repositories/TechMessagesRepository.cs +++ b/Persistence.Repository/Repositories/TechMessagesRepository.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using Persistence.Database.Entity; using Persistence.Models; using Persistence.Repositories; +using Persistence.Repository.Extensions; namespace Persistence.Repository.Repositories { diff --git a/Persistence/Models/TechMessageDto.cs b/Persistence/Models/TechMessageDto.cs index 274a1d5..625b22f 100644 --- a/Persistence/Models/TechMessageDto.cs +++ b/Persistence/Models/TechMessageDto.cs @@ -1,5 +1,8 @@ namespace Persistence.Models { + /// + /// Модель технологического сообщения + /// public class TechMessageDto { ///