using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Persistence.Client; using Persistence.Client.Clients; using Persistence.Database.Model; using Persistence.Models; using Persistence.Models.Requests; using System.Net; using Xunit; namespace Persistence.IntegrationTests.Controllers; public class ChangeLogControllerTest : BaseIntegrationTest { private readonly IChangeLogClient client; private static readonly Random generatorRandomDigits = new(); public ChangeLogControllerTest(WebAppFactoryFixture factory) : base(factory) { var persistenceClientFactory = scope.ServiceProvider .GetRequiredService(); client = persistenceClientFactory.GetClient(); } [Fact] public async Task ClearAndInsertRange_InEmptyDb() { // arrange var idDiscriminator = Guid.NewGuid(); var dtos = Generate(2); // act var result = await client.ClearAndAddRange(idDiscriminator, dtos); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(2, result.Content); } [Fact] public async Task ClearAndInsertRange_InNotEmptyDb() { // arrange var insertedCount = 10; var createdResult = CreateChangeLogItems(insertedCount, (-15, 15)); var idDiscriminator = createdResult.Item1; var dtos = createdResult.Item2.Select(e => e.Adapt()); // act var result = await client.ClearAndAddRange(idDiscriminator, dtos); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(insertedCount * 2, result.Content); } [Fact] public async Task Add_returns_success() { // arrange var count = 1; var idDiscriminator = Guid.NewGuid(); var dtos = Generate(count); var dto = dtos.FirstOrDefault()!; // act var result = await client.Add(idDiscriminator, dto); // assert Assert.Equal(HttpStatusCode.Created, result.StatusCode); Assert.Equal(count, result.Content); } [Fact] public async Task AddRange_returns_success() { // arrange var count = 3; var idDiscriminator = Guid.NewGuid(); var dtos = Generate(count); // act var result = await client.AddRange(idDiscriminator, dtos); // assert Assert.Equal(HttpStatusCode.Created, result.StatusCode); Assert.Equal(count, result.Content); } [Fact] public async Task Update_returns_success() { // arrange var idDiscriminator = Guid.NewGuid(); var dtos = Generate(1); var dto = dtos.FirstOrDefault()!; var result = await client.Add(idDiscriminator, dto); Assert.Equal(HttpStatusCode.Created, result.StatusCode); var entity = dbContext.ChangeLog .Where(x => x.IdDiscriminator == idDiscriminator) .FirstOrDefault(); dto = entity.Adapt(); dto.DepthEnd += 10; // act result = await client.Update(dto); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(2, result.Content); var dateBegin = DateTimeOffset.UtcNow.AddDays(-1); var dateEnd = DateTimeOffset.UtcNow.AddDays(1); var changeLogResult = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd); Assert.Equal(HttpStatusCode.OK, changeLogResult.StatusCode); Assert.NotNull(changeLogResult.Content); var changeLogDtos = changeLogResult.Content; var obsoleteDto = changeLogDtos .Where(e => e.Obsolete.HasValue) .FirstOrDefault(); var activeDto = changeLogDtos .Where(e => !e.Obsolete.HasValue) .FirstOrDefault(); if (obsoleteDto == null || activeDto == null) { Assert.Fail(); return; } Assert.Equal(activeDto.Id, obsoleteDto.IdNext); } [Fact] public async Task UpdateRange_returns_success() { // arrange var count = 2; var dtos = Generate(count); var entities = dtos.Select(d => d.Adapt()).ToArray(); dbContext.ChangeLog.AddRange(entities); dbContext.SaveChanges(); dtos = entities.Select(c => new DataWithWellDepthAndSectionDto() { DepthEnd = c.DepthEnd + 10, DepthStart = c.DepthStart + 10, Id = c.Id, IdSection = c.IdSection, Value = c.Value }).ToArray(); // act var result = await client.UpdateRange(dtos); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(count * 2, result.Content); } [Fact] public async Task Delete_returns_success() { // arrange var dtos = Generate(1); var dto = dtos.FirstOrDefault()!; var entity = dto.Adapt(); dbContext.ChangeLog.Add(entity); dbContext.SaveChanges(); // act var result = await client.Delete(entity.Id); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(1, result.Content); } [Fact] public async Task DeleteRange_returns_success() { // arrange var count = 10; var dtos = Generate(count); var entities = dtos.Select(d => d.Adapt()).ToArray(); dbContext.ChangeLog.AddRange(entities); dbContext.SaveChanges(); // act var ids = entities.Select(e => e.Id); var result = await client.DeleteRange(ids); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(count, result.Content); } [Fact] public async Task GetDatesRange_returns_success() { // arrange var changeLogItems = CreateChangeLogItems(3, (-15, 15)); var idDiscriminator = changeLogItems.Item1; var entities = changeLogItems.Item2.OrderBy(e => e.Creation); // act var result = await client.GetDatesRange(idDiscriminator); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result.Content); var minDate = entities.First().Creation; var maxDate = entities.Last().Creation; var expectedMinDate = minDate.ToUniversalTime().ToString(); var actualMinDate = result.Content.From.ToUniversalTime().ToString(); Assert.Equal(expectedMinDate, actualMinDate); var expectedMaxDate = maxDate.ToUniversalTime().ToString(); var actualMaxDate = result.Content.To.ToUniversalTime().ToString(); Assert.Equal(expectedMaxDate, actualMaxDate); } [Fact] public async Task GetByDate_returns_success() { // arrange //создаем записи var count = 5; var changeLogItems = CreateChangeLogItems(count, (-15, 15)); var idDiscriminator = changeLogItems.Item1; var entities = changeLogItems.Item2; //удаляем все созданные записи за исключением первой и второй //даты 2-х оставшихся записей должны вернуться в методе GetByDate var ids = entities.Select(e => e.Id); var idsToDelete = ids.Skip(2); var deletedCount = await client.DeleteRange(idsToDelete); var filterRequest = new SectionPartRequest() { DepthStart = 0, DepthEnd = 1000, }; var paginationRequest = new PaginationRequest() { Skip = 0, Take = 10, SortSettings = String.Empty, }; var moment = DateTimeOffset.UtcNow.AddDays(16); var result = await client.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest); Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result.Content); var restEntities = entities.Where(e => !idsToDelete.Contains(e.Id)); Assert.Equal(restEntities.Count(), result.Content.Count); var actualIds = restEntities.Select(e => e.Id); var expectedIds = result.Content.Items.Select(e => e.Id); Assert.Equivalent(expectedIds, actualIds); } [Theory] [InlineData(5, -15, 15, -20, 20, 10)] [InlineData(5, -15, -10, -16, -9, 5)] public async Task GetChangeLogForInterval_returns_success( int insertedCount, int daysBeforeNowChangeLog, int daysAfterNowChangeLog, int daysBeforeNowFilter, int daysAfterNowFilter, int changeLogCount) { // arrange //создаем записи var count = insertedCount; var daysRange = (daysBeforeNowChangeLog, daysAfterNowChangeLog); var changeLogItems = CreateChangeLogItems(count, daysRange); var idDiscriminator = changeLogItems.Item1; var entities = changeLogItems.Item2; foreach (var entity in entities) { entity.DepthEnd += 10; } var dtos = entities.Select(e => e.Adapt()).ToArray(); await client.UpdateRange(dtos); //act var dateBegin = DateTimeOffset.UtcNow.AddDays(daysBeforeNowFilter); var dateEnd = DateTimeOffset.UtcNow.AddDays(daysAfterNowFilter); var result = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd); //assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result.Content); Assert.Equal(changeLogCount, result.Content.Count()); } private static IEnumerable Generate(int count) { for (int i = 0; i < count; i++) yield return new DataWithWellDepthAndSectionDto() { Value = new Dictionary() { { "Key", 1 } }, DepthStart = generatorRandomDigits.Next(1, 5), DepthEnd = generatorRandomDigits.Next(5, 15), Id = Guid.NewGuid(), IdSection = Guid.NewGuid() }; } private (Guid, ChangeLog[]) CreateChangeLogItems(int count, (int, int) daysRange) { var minDayCount = daysRange.Item1; var maxDayCount = daysRange.Item2; Guid idDiscriminator = Guid.NewGuid(); var dtos = Generate(count); var entities = dtos.Select(d => { var entity = d.Adapt(); entity.IdDiscriminator = idDiscriminator; entity.Creation = DateTimeOffset.UtcNow.AddDays(generatorRandomDigits.Next(minDayCount, maxDayCount)); return entity; }).ToArray(); dbContext.ChangeLog.AddRange(entities); dbContext.SaveChanges(); return (idDiscriminator, entities); } }