using FluentAssertions; using LCU.API.Internal.DocumentLib.Containers; using LCU.API.Internal.DocumentLibTest.TestDoubles; using LCU.Library.Internal.DocumentModels.Requests; using MongoDB.Bson.Serialization; using MongoDB.Driver; namespace LCU.API.Internal.DocumentLibTest.Containers; public class DocumentAuditDiscriminatorConventionTest : IDisposable { private readonly FakeMongoCollectionFactory _collectionFactory = new(); private readonly IMongoCollection _collection; public DocumentAuditDiscriminatorConventionTest() { _collection = _collectionFactory.GetCollection(); } private static bool _registered = false; [SetUp] public void Setup() { if (_registered) return; BsonSerializer.RegisterDiscriminatorConvention ( typeof(DocumentAudit), new DocumentAuditDiscriminatorConvention() ); _registered = true; } [Test] public async Task FindAuditDocuments_DocumentMissingDiscriminator_DeserializesAsFieldAudit() { var audit = FieldAuditFactory(); await _collection.InsertOneAsync(audit); await _collection.FindOneAndUpdateAsync ( a => a.DocumentId == audit.DocumentId, Builders.Update.Unset(DocumentAuditDiscriminatorConvention.Discriminator) ); var retrievedAudit = await (await _collection.FindAsync(a => a.DocumentId == audit.DocumentId)) .SingleOrDefaultAsync(); Assert.IsInstanceOf(retrievedAudit); retrievedAudit.Should().BeEquivalentTo(audit, a => a.Using(DateTimeComparison.Truncated)); } [Test] public async Task FindAuditDocuments_DiscriminatorIsFieldAudit_DeserializesAsFieldAudit() { var audit = FieldAuditFactory(); await _collection.InsertOneAsync(audit); await _collection.FindOneAndUpdateAsync ( a => a.DocumentId == audit.DocumentId, Builders.Update.Set ( DocumentAuditDiscriminatorConvention.Discriminator, nameof(DocumentFieldAudit) ) ); var retrievedAudit = await (await _collection.FindAsync(a => a.DocumentId == audit.DocumentId)) .SingleOrDefaultAsync(); Assert.IsInstanceOf(retrievedAudit); retrievedAudit.Should().BeEquivalentTo(audit, a => a.Using(DateTimeComparison.Truncated)); } [Test] public async Task InsertFieldAuditDocuments_NewDocumentWithConventionRegistered_DiscriminatorIsFieldAudit() { var audit = FieldAuditFactory(); await _collection.InsertOneAsync(audit); var audits = await (await _collection.FindAsync ( Builders.Filter.Eq ( DocumentAuditDiscriminatorConvention.Discriminator, nameof(DocumentFieldAudit) ) ) ) .ToListAsync(); audits.Should().ContainEquivalentOf(audit, a => a.Using(DateTimeComparison.Truncated)); } [Test] public async Task FindAuditDocuments_DiscriminatorIsActionAudit_DeserializesAsActionAudit() { var audit = ActionAuditFactory(); await _collection.InsertOneAsync(audit); await _collection.FindOneAndUpdateAsync ( a => a.DocumentId == audit.DocumentId, Builders.Update.Set ( DocumentAuditDiscriminatorConvention.Discriminator, nameof(DocumentActionAudit) ) ); var retrievedAudit = await (await _collection.FindAsync(a => a.DocumentId == audit.DocumentId)) .SingleOrDefaultAsync(); Assert.IsInstanceOf(retrievedAudit); retrievedAudit.Should().BeEquivalentTo(audit, a => a.Using(DateTimeComparison.Truncated)); } [Test] public async Task InsertActionAuditDocuments_NewDocumentWithConventionRegistered_DiscriminatorIsActionAudit() { var audit = ActionAuditFactory(); await _collection.InsertOneAsync(audit); var audits = await (await _collection.FindAsync ( Builders.Filter.Eq ( DocumentAuditDiscriminatorConvention.Discriminator, nameof(DocumentActionAudit) ) ) ) .ToListAsync(); audits.Should().ContainEquivalentOf(audit, a => a.Using(DateTimeComparison.Truncated)); } [Test] public async Task FindAuditDocuments_UnknownDiscriminator_ThrowsException() { var audit = FieldAuditFactory(); await _collection.InsertOneAsync(audit); await _collection.FindOneAndUpdateAsync ( a => a.DocumentId == audit.DocumentId, Builders.Update.Set ( DocumentAuditDiscriminatorConvention.Discriminator, Guid.NewGuid().ToString() ) ); Assert.ThrowsAsync(() => _collection.FindAsync(a => a.DocumentId == audit.DocumentId)); } private static DocumentFieldAudit FieldAuditFactory() => new ( Guid.NewGuid(), Guid.NewGuid().ToString(), DateTime.UtcNow, Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid(), Guid.NewGuid() ); private static DocumentActionAudit ActionAuditFactory() => new ( Guid.NewGuid(), Guid.NewGuid().ToString(), DateTime.UtcNow, Guid.NewGuid().ToString(), DocumentAction.Download, Guid.NewGuid().ToString() ); public void Dispose() { _collectionFactory.Dispose(); } }