821 lines
25 KiB
C#
821 lines
25 KiB
C#
using FluentAssertions;
|
|
using LCU.API.Internal.DocumentIngestorLib.Persistence;
|
|
using LCU.API.Internal.DocumentIngestorLib.Repositories;
|
|
using LCU.API.Internal.DocumentIngestorLibTests;
|
|
using LCU.Library.Internal.DocumentIngestorModels.Constants;
|
|
using LCU.Library.Internal.DocumentIngestorModels.Entities;
|
|
using LCU.Library.Internal.DocumentIngestorModels.Enums;
|
|
using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Newtonsoft.Json.Linq;
|
|
using System;
|
|
|
|
namespace LCU.API.Internal.DocumentIngestorLibTests.Repositories;
|
|
|
|
public class DocumentProcessingInfoRepositoryTest : IDisposable
|
|
{
|
|
private IDocumentProcessingInfoRepository _repository;
|
|
|
|
private readonly SqliteAppDbContextFactory _contextFactory = new();
|
|
private AppDbContext _context;
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
_context = _contextFactory.CreateContext();
|
|
_repository = new DocumentProcessingInfoRepository(_context);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindAsync_AllCases_ReturnsAllDocumentProcessingInfoRecords()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infos = await _repository.FindAsync();
|
|
|
|
infos.Should().BeEquivalentTo(records);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByIdAsync_RecordExists_ReturnsRecord()
|
|
{
|
|
var matchedRecord = DocumentProcessingInfoFactory();
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
matchedRecord,
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var info = await _repository.FindByIdAsync(matchedRecord.DocumentProcessingInfoId);
|
|
|
|
info.Should().BeEquivalentTo(matchedRecord);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByIdAsync_RecordDoesNotExist_ReturnsNull()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var info = await _repository.FindByIdAsync(_idSeries.Next());
|
|
|
|
Assert.That(info, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindListByIdAsync_RecordsMatchedById_ReturnsMatched()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray();
|
|
var ids = matchedRecords
|
|
.Select(r => r.DocumentProcessingInfoId)
|
|
.Concat(new[] { _idSeries.Next() })
|
|
.ToList();
|
|
|
|
var infos = await _repository.FindListByIdAsync(ids);
|
|
|
|
infos.Should().BeEquivalentTo(matchedRecords);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByIngestorRunInfoIdAsync_RecordsMatchedByRunInfo_ReturnsMatched()
|
|
{
|
|
var runInfo = IngestorRunInfoFactory();
|
|
var matchedRecords = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(runInfo),
|
|
DocumentProcessingInfoFactory(runInfo),
|
|
DocumentProcessingInfoFactory(runInfo),
|
|
};
|
|
await _context.DocumentProcessingInfos.AddRangeAsync
|
|
(
|
|
DocumentProcessingInfoFactory(IngestorRunInfoFactory()),
|
|
DocumentProcessingInfoFactory(IngestorRunInfoFactory())
|
|
);
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(matchedRecords);
|
|
await _context.DocumentProcessingInfos.AddRangeAsync
|
|
(
|
|
DocumentProcessingInfoFactory(IngestorRunInfoFactory()),
|
|
DocumentProcessingInfoFactory(IngestorRunInfoFactory())
|
|
);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infos = await _repository.FindByIngestorRunInfoIdAsync(runInfo.IngestorRunInfoId);
|
|
|
|
infos.Should().BeEquivalentTo(matchedRecords);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByProcessStatusTypeAsync_RecordsMatchingType_ReturnsMatched()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
|
|
var type = records[1].StatusType;
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infoByType = await _repository.FindByProcessStatusTypeAsync(type, null);
|
|
|
|
infoByType.Where(documentProcessingInfo => documentProcessingInfo.StatusType.Equals(type));
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByProcessStatusTypeListAsync_RecordsMatchingType_ReturnsMatched()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
|
|
var types = records.Select(u => u.StatusType).ToList();
|
|
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infoByType = await _repository.FindByProcessStatusTypeListAsync(types, null);
|
|
|
|
infoByType.Where(documentProcessingInfo => documentProcessingInfo.StatusType.Equals(types));
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByProcessStatusTypeAsync_RecordsMatchingType_IsUnknown_ReturnsMatched()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
records[0].EntityUnknown = true;
|
|
records[2].EntityUnknown = true;
|
|
var type = records[1].StatusType;
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infoByType = await _repository.FindByProcessStatusTypeAsync(type, true);
|
|
|
|
infoByType.Should().BeEquivalentTo(records.Where(r => r.StatusType == type && r.EntityUnknown));
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByProcessStatusTypeListAsync_RecordsMatchingType_IsUnknown_ReturnsMatched()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
|
|
records[0].EntityUnknown = true;
|
|
records[2].EntityUnknown = true;
|
|
|
|
var types = new List<ProcessStatusTypes> { records[1].StatusType };
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infoByType = await _repository.FindByProcessStatusTypeListAsync(types, true);
|
|
|
|
infoByType.Should().BeEquivalentTo(records.Where(r => r.StatusType.Equals(types) && r.EntityUnknown));
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindCompletedFirstPassByIngestorRunInfoIdAsync_MatchedByRunInfoAndProcessedAtLeastOnce_ReturnsMatched()
|
|
{
|
|
var runInfo = IngestorRunInfoFactory();
|
|
var matchedRecords = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(runInfo),
|
|
DocumentProcessingInfoFactory(runInfo),
|
|
DocumentProcessingInfoFactory(runInfo),
|
|
DocumentProcessingInfoFactory(runInfo),
|
|
DocumentProcessingInfoFactory(runInfo),
|
|
};
|
|
var matchedProcessedRecords = matchedRecords
|
|
.Where((_, i) => i % 2 == 0)
|
|
.ToArray();
|
|
foreach (var record in matchedProcessedRecords)
|
|
{
|
|
record.ProcessCount = Math.Max(1, DateTime.Now.Millisecond);
|
|
}
|
|
await _context.DocumentProcessingInfos.AddRangeAsync
|
|
(
|
|
DocumentProcessingInfoFactory(IngestorRunInfoFactory()),
|
|
DocumentProcessingInfoFactory(IngestorRunInfoFactory())
|
|
);
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(matchedRecords);
|
|
await _context.DocumentProcessingInfos.AddRangeAsync
|
|
(
|
|
DocumentProcessingInfoFactory(IngestorRunInfoFactory()),
|
|
DocumentProcessingInfoFactory(IngestorRunInfoFactory())
|
|
);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var runCompleted = await _repository.FindCompletedFirstPassByIngestorRunInfoIdAsync(runInfo.IngestorRunInfoId);
|
|
|
|
runCompleted.Should().BeEquivalentTo(matchedProcessedRecords);
|
|
}
|
|
|
|
[Test]
|
|
public async Task AddAsync_AllCases_TracksAndDoesntSave()
|
|
{
|
|
var info = DocumentProcessingInfoFactory();
|
|
|
|
var added = await _repository.AddAsync(info);
|
|
|
|
var tracked = _context.ChangeTracker.Entries<DocumentProcessingInfo>()
|
|
.Select(e => e.Entity);
|
|
var id = info.DocumentProcessingInfoId;
|
|
var committed = _context.Database.SqlQuery<int>
|
|
(
|
|
@$"
|
|
SELECT count(1)
|
|
FROM DocumentProcessingInfo i
|
|
WHERE i.DocumentProcessingInfoId = {id}
|
|
"
|
|
).ToArray()
|
|
.Single();
|
|
added.Should().BeEquivalentTo(info);
|
|
tracked.Should().Contain(info);
|
|
committed.Should().Be(0);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Update_InfoAlreadyExists_TracksAndDoesntSave()
|
|
{
|
|
var info = DocumentProcessingInfoFactory();
|
|
await _context.DocumentProcessingInfos.AddAsync(info);
|
|
await _context.SaveChangesAsync();
|
|
info.ProcessCount++;
|
|
|
|
_repository.Update(info);
|
|
|
|
var tracked = _context.ChangeTracker.Entries<DocumentProcessingInfo>()
|
|
.Where(e => e.State == EntityState.Modified)
|
|
.Select(e => e.Entity);
|
|
var id = info.DocumentProcessingInfoId;
|
|
var count = info.ProcessCount;
|
|
var updated = _context.Database.SqlQuery<int>
|
|
(
|
|
@$"
|
|
SELECT count(1)
|
|
FROM DocumentProcessingInfo i
|
|
WHERE i.DocumentProcessingInfoId = {id}
|
|
AND i.ProcessCount = {count}
|
|
"
|
|
).ToArray()
|
|
.Single();
|
|
tracked.Should().Contain(info);
|
|
updated.Should().Be(0);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Remove_InfoAlreadyExists_TracksRemovalAndDoesntSave()
|
|
{
|
|
var info = DocumentProcessingInfoFactory();
|
|
await _context.DocumentProcessingInfos.AddAsync(info);
|
|
await _context.SaveChangesAsync();
|
|
|
|
_repository.Remove(info);
|
|
|
|
var tracked = _context.ChangeTracker.Entries<DocumentProcessingInfo>()
|
|
.Where(e => e.State == EntityState.Deleted)
|
|
.Select(e => e.Entity);
|
|
var id = info.DocumentProcessingInfoId;
|
|
var stored = _context.Database.SqlQuery<int>
|
|
(
|
|
@$"
|
|
SELECT count(1)
|
|
FROM DocumentProcessingInfo i
|
|
WHERE i.DocumentProcessingInfoId = {id}
|
|
"
|
|
).ToArray()
|
|
.Single();
|
|
tracked.Should().Contain(info);
|
|
stored.Should().Be(1);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FilteredListAsync_ByDocType_CountsAndFiltersByDocType()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray();
|
|
var docType = matchedRecords.First().DocumentType;
|
|
foreach (var record in matchedRecords)
|
|
{
|
|
record.DocumentType = docType;
|
|
}
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
var filter = new Filter
|
|
{
|
|
DocType = docType,
|
|
Page = 2,
|
|
Limit = 2
|
|
};
|
|
|
|
var filteredDocuments = await _repository.FilteredListAsync(filter);
|
|
|
|
filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit));
|
|
filteredDocuments.Total.Should().Be(matchedRecords.Length);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FilteredListAsync_ByBusinessName_CountsAndFiltersByBusinessName()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray();
|
|
var businessName = matchedRecords.First().DocumentBusinessName;
|
|
foreach (var record in matchedRecords)
|
|
{
|
|
record.DocumentBusinessName = businessName;
|
|
}
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
var filter = new Filter
|
|
{
|
|
DocBusinessName = businessName,
|
|
Page = 2,
|
|
Limit = 2
|
|
};
|
|
|
|
var filteredDocuments = await _repository.FilteredListAsync(filter);
|
|
|
|
filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit));
|
|
filteredDocuments.Total.Should().Be(matchedRecords.Length);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FilteredListAsync_ByStatusType_CountsAndFiltersByStatusType()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray();
|
|
var statusType = (ProcessStatusTypes)int.MinValue;
|
|
foreach (var record in matchedRecords)
|
|
{
|
|
record.StatusType = statusType;
|
|
}
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
var filter = new Filter
|
|
{
|
|
StatusFilters = records
|
|
.Select(i => i.StatusType)
|
|
.Distinct()
|
|
.Select(s => new StatusFilter { IsEnabled = s == statusType, StatusType = s })
|
|
.ToList(),
|
|
Page = 2,
|
|
Limit = 2
|
|
};
|
|
|
|
var filteredDocuments = await _repository.FilteredListAsync(filter);
|
|
|
|
filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit));
|
|
filteredDocuments.Total.Should().Be(matchedRecords.Length);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FilteredListAsync_ByCreatedDate_CountsAndFiltersByCreatedDate()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray();
|
|
var createdDate = matchedRecords.First().CreatedDate;
|
|
foreach (var record in matchedRecords)
|
|
{
|
|
record.CreatedDate = createdDate;
|
|
}
|
|
foreach (var record in records.Where(r => !matchedRecords.Contains(r)))
|
|
{
|
|
record.CreatedDate = createdDate.AddDays(1);
|
|
}
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
var filter = new Filter
|
|
{
|
|
CreatedDateStart = createdDate.AddMinutes(-1),
|
|
CreatedDateEnd = createdDate.AddMinutes(1),
|
|
Page = 2,
|
|
Limit = 2
|
|
};
|
|
|
|
var filteredDocuments = await _repository.FilteredListAsync(filter);
|
|
|
|
filteredDocuments.Items.Should().HaveCount(filter.Limit);
|
|
filteredDocuments.Items.Should().BeSubsetOf(matchedRecords);
|
|
filteredDocuments.Total.Should().Be(matchedRecords.Length);
|
|
}
|
|
|
|
|
|
[Test]
|
|
public async Task FilteredListAsync_ByIngestorRunInfoId_CountsAndFiltersByCreatedDate()
|
|
{
|
|
var runInfo = IngestorRunInfoFactory();
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray();
|
|
foreach (var record in matchedRecords)
|
|
{
|
|
record.IngestorRunInfo = runInfo;
|
|
}
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
var filter = new Filter
|
|
{
|
|
IngestorRunInfoId = runInfo.IngestorRunInfoId,
|
|
Page = 2,
|
|
Limit = 2
|
|
};
|
|
|
|
var filteredDocuments = await _repository.FilteredListAsync(filter);
|
|
|
|
filteredDocuments.Items.Should().HaveCount(filter.Limit);
|
|
filteredDocuments.Items.Should().BeSubsetOf(matchedRecords);
|
|
filteredDocuments.Total.Should().Be(matchedRecords.Length);
|
|
}
|
|
|
|
[Test]
|
|
[Ignore("a real SQL server connection in EF is required for the json filter to work\nthe filter is tested on its own in an integration test")]
|
|
public async Task FilteredListAsync_ByIndexFileJsonKeyValue_CountsAndFiltersByDocumentValuePayloadContainingJson()
|
|
{
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray();
|
|
var property = JObject.Parse(matchedRecords.First().DocumentValuePayload)
|
|
.Properties()
|
|
.First();
|
|
foreach (var record in matchedRecords)
|
|
{
|
|
var payload = JObject.Parse(record.DocumentValuePayload);
|
|
payload[property.Name] = property.Value;
|
|
|
|
record.DocumentValuePayload = payload.ToString().Replace(" ", string.Empty);
|
|
}
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
var filter = new Filter
|
|
{
|
|
CustomIndexFileFiltersEquals = new Dictionary<string, string>
|
|
{
|
|
[property.Name] = property.Value.ToString()
|
|
},
|
|
Page = 2,
|
|
Limit = 2
|
|
};
|
|
|
|
var filteredDocuments = await _repository.FilteredListAsync(filter);
|
|
|
|
filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit));
|
|
filteredDocuments.Total.Should().Be(matchedRecords.Length);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FilteredListAsync_ByNotificationStatus_CountsAndFiltersByMemberNotificationInfoStatusType()
|
|
{
|
|
var notificationStatus = NotificationStatusTypesFactory();
|
|
var records = new[]
|
|
{
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory(),
|
|
DocumentProcessingInfoFactory()
|
|
};
|
|
var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray();
|
|
foreach (var record in matchedRecords)
|
|
{
|
|
if (!record.MemberNotificationInfos.Any()) continue;
|
|
foreach (var notification in record.MemberNotificationInfos)
|
|
{
|
|
notification.NotificationStatusType = notificationStatus;
|
|
}
|
|
}
|
|
foreach (var record in records.Except(matchedRecords))
|
|
{
|
|
if (!record.MemberNotificationInfos.Any()) continue;
|
|
foreach (var notification in record.MemberNotificationInfos)
|
|
{
|
|
notification.NotificationStatusType = NotificationStatusTypesFactory(not: notificationStatus);
|
|
}
|
|
|
|
}
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(records);
|
|
await _context.SaveChangesAsync();
|
|
var filter = new Filter
|
|
{
|
|
NotificationStatusFilters = new List<NotificationStatusTypes> { notificationStatus },
|
|
Page = 2,
|
|
Limit = 2
|
|
};
|
|
|
|
var filteredDocuments = await _repository.FilteredListAsync(filter);
|
|
|
|
filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit));
|
|
filteredDocuments.Total.Should().Be(matchedRecords.Length);
|
|
}
|
|
|
|
[Test]
|
|
public async Task CountCompletedFirstPassByIngestorRunInfoIdAsync_AllCases_ReturnsCountOfDocumentProcessingInfoWithIngestorRunInfoIdAndProcessCountMoreThanOne()
|
|
{
|
|
var ingestorRunInfo = IngestorRunInfoFactory();
|
|
var runInfos = new List<IngestorRunInfo> { ingestorRunInfo };
|
|
var documents = Enumerable.Repeat
|
|
(
|
|
() => DocumentProcessingInfoFactory(ingestorRunInfo),
|
|
100
|
|
).Select(f => f())
|
|
.ToArray();
|
|
var expectedCount = 0;
|
|
foreach (var (document, index) in documents.Select((d, i) => (d, i)))
|
|
{
|
|
document.ProcessCount = index % 2 == 0 ? 0 : 1;
|
|
|
|
if (index % 3 == 0)
|
|
{
|
|
document.IngestorRunInfoId = ingestorRunInfo.IngestorRunInfoId;
|
|
document.IngestorRunInfo = ingestorRunInfo;
|
|
}
|
|
else
|
|
{
|
|
var run = IngestorRunInfoFactory();
|
|
runInfos.Add(run);
|
|
|
|
document.IngestorRunInfoId = run.IngestorRunInfoId;
|
|
document.IngestorRunInfo = run;
|
|
}
|
|
|
|
expectedCount += index % 2 == 0 && index % 3 == 0 ? 1 : 0;
|
|
}
|
|
await _context.IngestorRunInfos.AddRangeAsync(runInfos);
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(documents);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var count = await _repository.CountCompletedFirstPassByIngestorRunInfoIdAsync(ingestorRunInfo.IngestorRunInfoId);
|
|
|
|
Assert.That(count, Is.EqualTo(expectedCount));
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByDocumentIdsAsync_NullDocumentId_NotReturned()
|
|
{
|
|
var info = DocumentProcessingInfoFactory();
|
|
info.DocumentId = null;
|
|
var ids = Enumerable.Repeat(Guid.NewGuid, 5)
|
|
.Select(f => f())
|
|
.ToArray();
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(info);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infos = await _repository.FindByDocumentIdsAsync(ids);
|
|
|
|
CollectionAssert.DoesNotContain(infos, info);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByDocumentIdsAsync_DocumentIdNotInIds_NotReturned()
|
|
{
|
|
var info = DocumentProcessingInfoFactory();
|
|
info.DocumentId = Guid.NewGuid();
|
|
var ids = Enumerable.Repeat(Guid.NewGuid, 5)
|
|
.Select(f => f())
|
|
.ToArray();
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(info);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infos = await _repository.FindByDocumentIdsAsync(ids);
|
|
|
|
CollectionAssert.DoesNotContain(infos, info);
|
|
}
|
|
|
|
[Test]
|
|
public async Task FindByDocumentIdsAsync_DocumentIdsInIds_ReturnsAllMatched()
|
|
{
|
|
var expectedInfos = Enumerable.Repeat(DocumentProcessingInfoFactory, 5)
|
|
.Select(f =>
|
|
{
|
|
var info = f(null);
|
|
info.DocumentId = Guid.NewGuid();
|
|
|
|
return info;
|
|
})
|
|
.ToArray();
|
|
var ids = Enumerable.Repeat(Guid.NewGuid, expectedInfos.Length)
|
|
.Select(f => f())
|
|
.Concat(expectedInfos.Select(i => i.DocumentId.Value))
|
|
.Concat
|
|
(
|
|
Enumerable.Repeat(Guid.NewGuid, expectedInfos.Length)
|
|
.Select(f => f())
|
|
)
|
|
.ToArray();
|
|
await _context.DocumentProcessingInfos.AddRangeAsync(expectedInfos);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var infos = await _repository.FindByDocumentIdsAsync(ids);
|
|
|
|
infos.Should().Contain(expectedInfos);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_contextFactory.Dispose();
|
|
}
|
|
|
|
private readonly Random _idSeries = new(DateTime.Now.Millisecond);
|
|
|
|
private readonly IngestorRunInfo _runInfo = IngestorRunInfoFactory();
|
|
|
|
private static IngestorRunInfo IngestorRunInfoFactory()
|
|
{
|
|
return new()
|
|
{
|
|
EndTimeStamp = DateTime.Now,
|
|
IngestorType = IngestorTypes.FosDnaDocument,
|
|
IngestorRunInfoId = Guid.NewGuid(),
|
|
IndexTotal = DateTime.Now.Millisecond,
|
|
IndexFileName = Guid.NewGuid().ToString(),
|
|
IndexFilePath = Guid.NewGuid().ToString(),
|
|
StartTimeStamp = DateTime.Now
|
|
};
|
|
}
|
|
|
|
private ProcessStatusTypes ProcessStatusTypesFactory()
|
|
=> EnumValueFactory<ProcessStatusTypes>();
|
|
|
|
private NotificationStatusTypes NotificationStatusTypesFactory(NotificationStatusTypes? not = null)
|
|
=> EnumValueFactory(not);
|
|
|
|
private T EnumValueFactory<T>(T? not = null) where T : struct, Enum
|
|
{
|
|
var availableValues = Enum.GetValues<T>().Where(t => not == null || !t.Equals(not.Value)).ToArray();
|
|
|
|
return availableValues[_idSeries.Next() % availableValues.Length];
|
|
}
|
|
|
|
private DocumentProcessingInfo DocumentProcessingInfoFactory(IngestorRunInfo? runInfo = null)
|
|
=> new()
|
|
{
|
|
CreatedDate = DateTime.Now,
|
|
DocumentFileName = Guid.NewGuid().ToString(),
|
|
DocumentId = Guid.NewGuid(),
|
|
DocumentType = Guid.NewGuid().ToString(),
|
|
DocumentBusinessName = Guid.NewGuid().ToString(),
|
|
DocumentValuePayload = @$"
|
|
{{
|
|
""{Guid.NewGuid()}"":""{Guid.NewGuid().ToString()}"",
|
|
""{Guid.NewGuid()}"":""{Guid.NewGuid().ToString()}"",
|
|
""{Guid.NewGuid()}"":""{Guid.NewGuid().ToString()}""
|
|
}}
|
|
",
|
|
DocumentProcessingInfoId = _idSeries.Next(),
|
|
IngestorRunInfoId = (runInfo ?? _runInfo).IngestorRunInfoId,
|
|
IngestorRunInfo = runInfo ?? _runInfo,
|
|
ProcessCount = 0,
|
|
StatusType = ProcessStatusTypesFactory(),
|
|
MemberNotificationInfos = NotificationInfoFactory()
|
|
};
|
|
|
|
private List<MemberNotificationInfo> NotificationInfoFactory()
|
|
=> new() {
|
|
new MemberNotificationInfo
|
|
{
|
|
NotificationStatusType = NotificationStatusTypesFactory()
|
|
},
|
|
new MemberNotificationInfo
|
|
{
|
|
NotificationStatusType = NotificationStatusTypesFactory()
|
|
},
|
|
new MemberNotificationInfo
|
|
{
|
|
NotificationStatusType = NotificationStatusTypesFactory()
|
|
}
|
|
};
|
|
} |