using e_suite.Database.Audit.AuditEngine; using e_suite.Database.Audit.UnitTests.Helpers; using e_suite.Database.Audit.UnitTests.Helpers.Tables; using NUnit.Framework; namespace e_suite.Database.Audit.UnitTests.AuditEngineCore; [TestFixture] public class SoftDeleteUnitTests : AuditEngineCoreTestBase { [Test] public async Task AddRow_ItemEditedHasNotDeleted_AuditEntryShowsAsUpdate() { //Arrange var auditUserDetails = new AuditUserDetails { UserId = 1, UserDisplayName = "Testy McTester", Comment = "Test comment" }; var leafTreeValue = new DeletableTreeValue { Id = 2000, Name = "Leaf Level item", Deleted = false }; testDBContext.DeletableTreeValues.Add(leafTreeValue); await testDBContext.NoAuditSaveChangesAsync(); //Act var itemToEdit = testDBContext.DeletableTreeValues.Single(x => x.Id == leafTreeValue.Id); itemToEdit.Name = "Altered Name"; itemToEdit.Deleted = false; await testDBContext.SaveChangesAsync(auditUserDetails); //Assert Assert.That(testDBContext.AuditDetails.Count(), Is.EqualTo(1)); var auditDetail = testDBContext.AuditDetails.First(); Assert.That(auditDetail.Type, Is.EqualTo(AuditType.Update.ToString())); } [Test] public async Task AddRow_ItemIsUndeleted_AuditEntryShowsAsRestore() { //Arrange var auditUserDetails = new AuditUserDetails { UserId = 1, UserDisplayName = "Testy McTester", Comment = "Test comment" }; var leafTreeValue = new DeletableTreeValue { Id = 2000, Name = "Leaf Level item", Deleted = true }; testDBContext.DeletableTreeValues.Add(leafTreeValue); await testDBContext.NoAuditSaveChangesAsync(); //Act var itemToEdit = testDBContext.DeletableTreeValues.Single(x => x.Id == leafTreeValue.Id); itemToEdit.Name = "Altered Name"; itemToEdit.Deleted = false; await testDBContext.SaveChangesAsync(auditUserDetails); //Assert Assert.That(testDBContext.AuditDetails.Count(), Is.EqualTo(1)); var auditDetail = testDBContext.AuditDetails.First(); Assert.That(auditDetail.Type, Is.EqualTo(AuditType.Restore.ToString())); } [TestCase(true)] //Soft delete [TestCase(false)] //Undelete public async Task AddRow_TableHasSelfReferenceAndReferenceNull_AuditForSoftDeleteOrUndeleteRecorded(bool deleteRow) { //Arrange var auditUserDetails = new AuditUserDetails { UserId = 1, UserDisplayName = "Testy McTester", Comment = "Test comment" }; var leafTreeValue = new DeletableTreeValue { Id = 30000, Name = "Leaf Level item", Deleted = !deleteRow }; testDBContext.DeletableTreeValues.Add(leafTreeValue); await testDBContext.NoAuditSaveChangesAsync(); //Act var itemToEdit = testDBContext.DeletableTreeValues.Single(x => x.Id == leafTreeValue.Id); itemToEdit.Deleted = deleteRow; await testDBContext.SaveChangesAsync(auditUserDetails); //Assert Assert.That(testDBContext.AuditDetails.Count(), Is.EqualTo(1)); var auditDetail = testDBContext.AuditDetails.First(); Assert.That(auditDetail.UserDisplayName, Is.EqualTo(auditUserDetails.UserDisplayName)); Assert.That(auditDetail.UserId, Is.EqualTo(auditUserDetails.UserId)); Assert.That(auditDetail.Comment, Is.EqualTo(auditUserDetails.Comment)); Assert.That(auditDetail.Id, Is.EqualTo(1)); Assert.That(auditDetail.Type, Is.EqualTo(deleteRow ? AuditType.Delete.ToString() : AuditType.Restore.ToString())); Assert.That(auditDetail.Fields, Is.EqualTo( string.Empty)); Assert.That(testDBContext.AuditEntries.Count(), Is.EqualTo(1)); var auditEntries = testDBContext.AuditEntries.ToList(); var childAuditEntry = auditEntries[0]; Assert.That(childAuditEntry.Id, Is.EqualTo(1)); Assert.That(childAuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(childAuditEntry.DisplayName, Is.EqualTo(leafTreeValue.Name)); Assert.That(childAuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(childAuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{leafTreeValue.Id}}}")); Assert.That(childAuditEntry.IsPrimary, Is.True); Assert.That(testDBContext.AuditDrillHierarchies.Count(), Is.EqualTo(0)); } [TestCase(true)] //Soft delete [TestCase(false)] //Undelete public async Task AddRow_TableHasSingleParentItem_AuditForSoftDeleteOrUndeleteRecorded(bool deleteRow) { //Arrange var auditUserDetails = new AuditUserDetails { UserId = 1, UserDisplayName = "Testy McTester", Comment = "Test comment" }; var rootTreeValue = new DeletableTreeValue { Id = 3000, Name = "Root Level item", Deleted = !deleteRow }; var leafTreeValue = new DeletableTreeValue { Id = 30000, Name = "Leaf Level item", Deleted = !deleteRow, ParentId = rootTreeValue.Id }; testDBContext.DeletableTreeValues.Add(rootTreeValue); testDBContext.DeletableTreeValues.Add(leafTreeValue); await testDBContext.NoAuditSaveChangesAsync(); //Act var itemToEdit = testDBContext.DeletableTreeValues.Single(x => x.Id == leafTreeValue.Id); itemToEdit.Deleted = deleteRow; await testDBContext.SaveChangesAsync(auditUserDetails); //Assert Assert.That(testDBContext.AuditDetails.Count(), Is.EqualTo(1)); var auditDetail = testDBContext.AuditDetails.First(); Assert.That(auditDetail.UserDisplayName, Is.EqualTo(auditUserDetails.UserDisplayName)); Assert.That(auditDetail.UserId, Is.EqualTo(auditUserDetails.UserId)); Assert.That(auditDetail.Comment, Is.EqualTo(auditUserDetails.Comment)); Assert.That(auditDetail.Id, Is.EqualTo(1)); Assert.That(auditDetail.Type, Is.EqualTo(deleteRow ? AuditType.Delete.ToString() : AuditType.Restore.ToString())); Assert.That(testDBContext.DeletableTreeValues.Count(), Is.EqualTo(2)); Assert.That(testDBContext.AuditEntries.Count(), Is.EqualTo(2)); var auditEntries = testDBContext.AuditEntries.ToList(); var childAuditEntry = auditEntries[0]; Assert.That(childAuditEntry.Id, Is.EqualTo(1)); Assert.That(childAuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(childAuditEntry.DisplayName, Is.EqualTo(leafTreeValue.Name)); Assert.That(childAuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(childAuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{leafTreeValue.Id}}}")); Assert.That(childAuditEntry.IsPrimary, Is.True); var parentAuditEntry = auditEntries[1]; Assert.That(parentAuditEntry.Id, Is.EqualTo(2)); Assert.That(parentAuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(parentAuditEntry.DisplayName, Is.EqualTo(rootTreeValue.Name)); Assert.That(parentAuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(parentAuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{rootTreeValue.Id}}}")); Assert.That(parentAuditEntry.IsPrimary, Is.False); Assert.That(testDBContext.AuditDrillHierarchies.Count(), Is.EqualTo(1)); var auditDrillHierarchies = testDBContext.AuditDrillHierarchies.ToList(); Assert.That(auditDrillHierarchies[0].ChildAuditDrillDownEntityId, Is.EqualTo(1)); Assert.That(auditDrillHierarchies[0].ParentAuditDrillDownEntityId, Is.EqualTo(2)); } [TestCase(true)] //Soft delete [TestCase(false)] //Undelete public async Task AddRow_TableHasTwoParentLevels_AuditForSoftDeleteOrUndeleteRecorded(bool deleteRow) { //Arrange var auditUserDetails = new AuditUserDetails { UserId = 1, UserDisplayName = "Testy McTester", Comment = "Test comment" }; var rootTreeValue = new DeletableTreeValue { Id = 300, Name = "Root Level item", Deleted = !deleteRow }; var level1TreeValue = new DeletableTreeValue { Id = 3000, Name = "Level 1 item", Deleted = !deleteRow, ParentId = rootTreeValue.Id }; var leafTreeValue = new DeletableTreeValue { Id = 30000, Name = "Leaf Level item", Deleted = !deleteRow, ParentId = level1TreeValue.Id }; testDBContext.DeletableTreeValues.Add(rootTreeValue); testDBContext.DeletableTreeValues.Add(level1TreeValue); testDBContext.DeletableTreeValues.Add(leafTreeValue); await testDBContext.NoAuditSaveChangesAsync(); //Act var itemToEdit = testDBContext.DeletableTreeValues.Single(x => x.Id == leafTreeValue.Id); itemToEdit.Deleted = deleteRow; await testDBContext.SaveChangesAsync(auditUserDetails); //Assert Assert.That(testDBContext.AuditDetails.Count(), Is.EqualTo(1)); var auditDetail = testDBContext.AuditDetails.First(); Assert.That(auditDetail.UserDisplayName, Is.EqualTo(auditUserDetails.UserDisplayName)); Assert.That(auditDetail.UserId, Is.EqualTo(auditUserDetails.UserId)); Assert.That(auditDetail.Comment, Is.EqualTo(auditUserDetails.Comment)); Assert.That(auditDetail.Id, Is.EqualTo(1)); Assert.That(auditDetail.Type, Is.EqualTo(deleteRow ? AuditType.Delete.ToString() : AuditType.Restore.ToString())); Assert.That(testDBContext.DeletableTreeValues.Count(), Is.EqualTo(3)); Assert.That(testDBContext.AuditEntries.Count(), Is.EqualTo(3)); var auditEntries = testDBContext.AuditEntries.ToList(); var childAuditEntry = auditEntries[0]; Assert.That(childAuditEntry.Id, Is.EqualTo(1)); Assert.That(childAuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(childAuditEntry.DisplayName, Is.EqualTo(leafTreeValue.Name)); Assert.That(childAuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(childAuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{leafTreeValue.Id}}}")); Assert.That(childAuditEntry.IsPrimary, Is.True); var level1AuditEntry = auditEntries[1]; Assert.That(level1AuditEntry.Id, Is.EqualTo(2)); Assert.That(level1AuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(level1AuditEntry.DisplayName, Is.EqualTo(level1TreeValue.Name)); Assert.That(level1AuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(level1AuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{level1TreeValue.Id}}}")); Assert.That(level1AuditEntry.IsPrimary, Is.False); var parentAuditEntry = auditEntries[2]; Assert.That(parentAuditEntry.Id, Is.EqualTo(3)); Assert.That(parentAuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(parentAuditEntry.DisplayName, Is.EqualTo(rootTreeValue.Name)); Assert.That(parentAuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(parentAuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{rootTreeValue.Id}}}")); Assert.That(parentAuditEntry.IsPrimary, Is.False); Assert.That(testDBContext.AuditDrillHierarchies.Count(), Is.EqualTo(2)); var auditDrillHierarchies = testDBContext.AuditDrillHierarchies.ToList(); Assert.That(auditDrillHierarchies[0].ChildAuditDrillDownEntityId, Is.EqualTo(1)); Assert.That(auditDrillHierarchies[0].ParentAuditDrillDownEntityId, Is.EqualTo(2)); Assert.That(auditDrillHierarchies[1].ChildAuditDrillDownEntityId, Is.EqualTo(2)); Assert.That(auditDrillHierarchies[1].ParentAuditDrillDownEntityId, Is.EqualTo(3)); } [TestCase(true)] //Soft delete [TestCase(false)] //Undelete public async Task AddRow_TableHasThreeParentLevels_AuditForSoftDeleteOrUndeleteRecorded(bool deleteRow) { //Arrange var auditUserDetails = new AuditUserDetails { UserId = 1, UserDisplayName = "Testy McTester", Comment = "Test comment" }; var rootTreeValue = new DeletableTreeValue { Id = 30, Name = "Root Level item", Deleted = !deleteRow }; var level1TreeValue = new DeletableTreeValue { Id = 300, Name = "Level 1 item", Deleted = !deleteRow, ParentId = rootTreeValue.Id }; var level2TreeValue = new DeletableTreeValue { Id = 3000, Name = "Level 2 item", Deleted = !deleteRow, ParentId = level1TreeValue.Id }; var leafTreeValue = new DeletableTreeValue { Id = 30000, Name = "Leaf Level item", Deleted = !deleteRow, ParentId = level2TreeValue.Id }; testDBContext.DeletableTreeValues.Add(rootTreeValue); await testDBContext.NoAuditSaveChangesAsync(); testDBContext.DeletableTreeValues.Add(level1TreeValue); await testDBContext.NoAuditSaveChangesAsync(); testDBContext.DeletableTreeValues.Add(level2TreeValue); await testDBContext.NoAuditSaveChangesAsync(); testDBContext.DeletableTreeValues.Add(leafTreeValue); await testDBContext.NoAuditSaveChangesAsync(); //Act var itemToEdit = testDBContext.DeletableTreeValues.Single(x => x.Id == leafTreeValue.Id); itemToEdit.Deleted = deleteRow; await testDBContext.SaveChangesAsync(auditUserDetails); //Assert Assert.That(testDBContext.AuditDetails.Count(), Is.EqualTo(1)); var auditDetail = testDBContext.AuditDetails.First(); Assert.That(auditDetail.UserDisplayName, Is.EqualTo(auditUserDetails.UserDisplayName)); Assert.That(auditDetail.UserId, Is.EqualTo(auditUserDetails.UserId)); Assert.That(auditDetail.Comment, Is.EqualTo(auditUserDetails.Comment)); Assert.That(auditDetail.Id, Is.EqualTo(1)); Assert.That(auditDetail.Type, Is.EqualTo(deleteRow ? AuditType.Delete.ToString() : AuditType.Restore.ToString())); Assert.That(testDBContext.DeletableTreeValues.Count(), Is.EqualTo(4)); Assert.That(testDBContext.AuditEntries.Count(), Is.EqualTo(4)); var auditEntries = testDBContext.AuditEntries.ToList(); var childAuditEntry = auditEntries[0]; Assert.That(childAuditEntry.Id, Is.EqualTo(1)); Assert.That(childAuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(childAuditEntry.DisplayName, Is.EqualTo(leafTreeValue.Name)); Assert.That(childAuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(childAuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{leafTreeValue.Id}}}")); Assert.That(childAuditEntry.IsPrimary, Is.True); var level1AuditEntry = auditEntries[1]; Assert.That(level1AuditEntry.Id, Is.EqualTo(2)); Assert.That(level1AuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(level1AuditEntry.DisplayName, Is.EqualTo(level2TreeValue.Name)); Assert.That(level1AuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(level1AuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{level2TreeValue.Id}}}")); Assert.That(level1AuditEntry.IsPrimary, Is.False); var level2AuditEntry = auditEntries[2]; Assert.That(level2AuditEntry.Id, Is.EqualTo(3)); Assert.That(level2AuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(level2AuditEntry.DisplayName, Is.EqualTo(level1TreeValue.Name)); Assert.That(level2AuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(level2AuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{level1TreeValue.Id}}}")); Assert.That(level2AuditEntry.IsPrimary, Is.False); var parentAuditEntry = auditEntries[3]; Assert.That(parentAuditEntry.Id, Is.EqualTo(4)); Assert.That(parentAuditEntry.EntityName, Is.EqualTo(typeof(DeletableTreeValue).FullName)); Assert.That(parentAuditEntry.DisplayName, Is.EqualTo(rootTreeValue.Name)); Assert.That(parentAuditEntry.AuditLogId, Is.EqualTo(auditDetail.Id)); Assert.That(parentAuditEntry.PrimaryKey, Is.EqualTo($"{{\"Id\":{rootTreeValue.Id}}}")); Assert.That(parentAuditEntry.IsPrimary, Is.False); Assert.That(testDBContext.AuditDrillHierarchies.Count(), Is.EqualTo(3)); var auditDrillHierarchies = testDBContext.AuditDrillHierarchies.ToList(); Assert.That(auditDrillHierarchies[0].ChildAuditDrillDownEntityId, Is.EqualTo(1)); Assert.That(auditDrillHierarchies[0].ParentAuditDrillDownEntityId, Is.EqualTo(2)); Assert.That(auditDrillHierarchies[1].ChildAuditDrillDownEntityId, Is.EqualTo(2)); Assert.That(auditDrillHierarchies[1].ParentAuditDrillDownEntityId, Is.EqualTo(3)); Assert.That(auditDrillHierarchies[2].ChildAuditDrillDownEntityId, Is.EqualTo(3)); Assert.That(auditDrillHierarchies[2].ParentAuditDrillDownEntityId, Is.EqualTo(4)); } }