Skip to content

Commit

Permalink
Fix/issue#193 (#198)
Browse files Browse the repository at this point in the history
* refactor(DAL): remove obsolete services

Remove entity model services where the models will be maintained via
a parent object service.

* test(DAL): remove tests for obsolete entity model services

* refactor(Controller): remove obsolete entity model controllers

* refactor(Blazor): remove unnecessary lock object

* feat(DAL): add class for tracking add/remove operations on an ICollection<T>

Add CollectionCommand and CollectionCommandHistory tracking for working forwards
and backwards through 'undo' and 'redo' operations. Supports changes to entity model
services responsible for adding/removing/updating multiple entities at once.

Related #193

* test(DAL): add tests for CollectionCommandHistory class

* refactor(DAL): remove obsolete CountryBatchWriterService

* refactor(DAL): refactor ICollectionCommandHistory and CommandHistoryEntry

Rename ICollectionCommandHistory to ICommandHistory.
Move CommandHistoryEntry to separate file.

* feat(DAL): add Clear method to ICommandHistory interface

* test(DAL): add test for ICommandHistory.Clear method

* feat(DAL): make ICommandHistory generic

Convert ICommandHistory to generic interface and update implementation.
Rename CollectionCommandHistory to CommandHistory.

* feat(DAL): add IChangeTracker implementation ot CommandHistory

Update CommandHistory to implement IChangeTracker. Class features are not exactly
aligned, but this approach was most expedient. Opportunity to refactor later.

* test(DAL): fix test name add tests for IChangeTracker methods

Rename CollectionCommandHistoryTest to CommandHistoryTest to mirror tested class.
Add tests for IChangeTracker methods implemented in CommandHistory<T>.

* feat(DAL): consolidate methods in IChangeTracker and ModelCollectionService

Add ModelCollectionService to replace ModelWriterBatchService and ModeBatchService
class. ModelCollectionServices implements add/remove change tracking for a disconnected entity set.

* fix(DAL): add missing resource file

* test(DAL): update IChangeTracker tests to use new GetChanges method

* feat(EntityModel): change DatabaseKey to a public extension method

* fix(DAL) remove shared and persisted DbContext classes from entity services

Remove the persisted DbContext classes in the entity model service layer and replace with
correct short-lived used of DbContext-derived classes. Introduces ChangeTracking for a
disconnected collection of  entities to be worked in batches of not more than a single page size.
Update tracking is not available.

Related #193

* test(DAL): fix tests related to removed IModelBatchService interface

* fix(Controllers): fix controller referneces to IModelBatchController

* refactor(DAL): move IModelCollectionService to separate file

* fix(DAL): resolve errors in service registration

* fix(Blazor): update collection pages to inherit ModelListPage

Changes pages that work with collections of entities to inherit from ModelListPage and
use the updated controller interface ICollectionController. Completes work necessary to
support pagination without crashing due to multi-threaded access to DbContext classes.

Resolves #193

* refactor(Blazor): move most page initialization methods to base class

Move majority of page initialization logic to base classes ModelListPage, ModelIndex,
and ModelPagedIndex. Prepares the UI layer for application of Paginator control.

* fix(DAL): fix missing constructor arguments for SecurityExchangeBatchService

* refactor(DAL): standardize names for ModelCollectionService classes

* feat(Blazor): add paginator control to base index pages

* design(Blazor): fix form-control.button rule to preserve size of button icons

* feat(Blazor): add paginator control to remaining collection pages
  • Loading branch information
hoeyi authored Jun 10, 2023
1 parent d32b703 commit 0901469
Show file tree
Hide file tree
Showing 125 changed files with 3,372 additions and 3,655 deletions.
111 changes: 111 additions & 0 deletions NjordinSight.DAL.Test/ChangeTracking/ChangeTrackerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NjordinSight.EntityModelService.ChangeTracking;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;

namespace NjordinSight.Test.ChangeTracking
{
[TestClass]
[TestCategory("Unit")]
public class ChangeTrackerTest
{
[TestMethod]
public void Collection_AddThenExecute_GetChangesAdded_ReturnsObject()
{
var changeTracker = new CommandHistory<int>();
var collection = new List<int>();

changeTracker.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));

var changes = changeTracker.GetChanges();

var expected = 5;
var observed = changes.Added.FirstOrDefault();

Assert.AreEqual(expected, observed);
}

[TestMethod]
public void Collection_WhenNotEmpty_ItemRemoved_GetChangesRemoved_ReturnsObject()
{
var changeTracker = new CommandHistory<int>();
var collection = new List<int>() { 5 };

changeTracker.AddThenExecute(new RemoveCommand<int>(collection, 5, "Remove 5"));

var changes = changeTracker.GetChanges();

var expected = 5;
var observed = changes.Removed.FirstOrDefault();

Assert.AreEqual(expected, observed);
}

[TestMethod]
public void Collection_WhenItemAddedThenUndone_GetChangesAdded_ReturnsEmptyCollection()
{
var changeTracker = new CommandHistory<int>();
var collection = new List<int>();

changeTracker.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
changeTracker.UndoCommand();

var changes = changeTracker.GetChanges();

Assert.IsFalse(changes.Added.Any());
}

[TestMethod]
public void Collection_WhenItemRemovedThenUndone_GetChangesAdded_ReturnsEmptyCollection()
{
var changeTracker = new CommandHistory<int>();
var collection = new List<int>() { 5 };

changeTracker.AddThenExecute(new RemoveCommand<int>(collection, 5, "Remove 5"));
changeTracker.UndoCommand();

var changes = changeTracker.GetChanges();

Assert.IsFalse(changes.Added.Any());
}

[TestMethod]
public void Collection_WhenItemAddedThenRemoved_GetChanges_ReturnsEmptyCollections()
{
var changeTracker = new CommandHistory<int>();
var collection = new List<int>();

changeTracker.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
changeTracker.AddThenExecute(new RemoveCommand<int>(collection, 5, "Remove 5"));

var changes = changeTracker.GetChanges();

var observedAdds = changes.Added;
var observedRemoves = changes.Removed;

Assert.IsFalse(observedAdds.Any() && observedRemoves.Any());
}

[TestMethod]
public void Collection_WhenOneItemAdded_OneItemRemoved_GetChanges_ReturnsTwoChanges()
{
var changeTracker = new CommandHistory<int>();
var collection = new List<int>() { 4 };

changeTracker.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
changeTracker.AddThenExecute(new RemoveCommand<int>(collection, 4, "Remove 4"));

var changes = changeTracker.GetChanges();

var observedAdds = changes.Added;
var observedRemoves = changes.Removed;

Assert.IsTrue(observedAdds.Count == 1 && observedRemoves.Count == 1);
}
}
}
190 changes: 190 additions & 0 deletions NjordinSight.DAL.Test/ChangeTracking/CommandHistoryTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NjordinSight.EntityModelService.ChangeTracking;
using Microsoft.Extensions.Logging;

namespace NjordinSight.Test.ChangeTracking
{
[TestClass]
[TestCategory("Unit")]
public class CommandHistoryTest
{
[TestMethod]
public void Collection_AddThenExecute_CurrentEntry_IsAddedValue()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));

var expected = new CommandHistoryEntry
{
Index = 0,
Description = "Add 5"
};

var observed = commandHistory.Current;

Assert.AreEqual(expected, observed);
}

[TestMethod]
public void Collection_AddThenExecute_CanUndo_IsTrue_CanRedo_IsFalse()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));

Assert.IsTrue(commandHistory.CanUndo);
Assert.IsFalse(commandHistory.CanRedo);
}

[TestMethod]
public void Collection_AddThenUndo_CurrentEntry_IsNull()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
commandHistory.UndoCommand();

Assert.IsNull(commandHistory.Current);
}

[TestMethod]
public void Collection_AddThenUndo_CanUndo_IsFalse()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
commandHistory.UndoCommand();

Assert.IsFalse(commandHistory.CanUndo);
Assert.IsTrue(commandHistory.CanRedo);
}

[TestMethod]
public void Collection_AddThenUndoThenRedo_CurrentEntry_IsAddedValue()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
commandHistory.UndoCommand();
commandHistory.RedoCommand();

var expected = new CommandHistoryEntry
{
Index = 0,
Description = "Add 5"
};

var observed = commandHistory.Current;

Assert.AreEqual(expected, observed);
}

[TestMethod]
public void Collection_AddThenRemoveThenUndo_CurrentEntry_IsLastValueAdded()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
commandHistory.AddThenExecute(new RemoveCommand<int>(collection, 5, "Remove 5"));
commandHistory.UndoCommand();

var expected = new CommandHistoryEntry
{
Index = 0,
Description = "Add 5"
};

var observed = commandHistory.Current;

Assert.AreEqual(expected, observed);
}

[TestMethod]
public void Collection_AddThenRemoveThenUndo_Count_EqualsTwo()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
commandHistory.AddThenExecute(new RemoveCommand<int>(collection, 5, "Remove 5"));

// Every command added is recorded.
Assert.AreEqual(2, commandHistory.Count);

commandHistory.UndoCommand();

// When a command is undone, the collection is unmodified.
Assert.AreEqual(2, commandHistory.Count);
}

[TestMethod]
public void Collection_WhenIsEmpty_WhenCanUndoIsFalse_UndoCommand_ThrowsInvalidOperationException()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

Assert.IsFalse(commandHistory.CanUndo);
Assert.ThrowsException<InvalidOperationException>(() => commandHistory.UndoCommand());
}

[TestMethod]
public void Collection_WhenIsEmpty_And_WhenCanRedoIsFalse_RedoCommand_ThrowsInvalidOperationException()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

Assert.IsFalse(commandHistory.CanRedo);
Assert.ThrowsException<InvalidOperationException>(() => commandHistory.RedoCommand());
}

[TestMethod]
public void Collection_WhenNotEmpty_And_WhenCanUndoIsFalse_UndoCommand_ThrowsInvalidOperationException()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));
commandHistory.UndoCommand();

Assert.IsFalse(commandHistory.CanUndo);
Assert.ThrowsException<InvalidOperationException>(() => commandHistory.UndoCommand());
}

[TestMethod]
public void Collection_WhenNotEmpty_And_WhenCanRedoIsFalse_RedoCommand_ThrowsInvalidOperationException()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));

Assert.IsFalse(commandHistory.CanRedo);
Assert.ThrowsException<InvalidOperationException>(() => commandHistory.RedoCommand());
}

[TestMethod]
public void Collection_WhenNotEmpty_After_Clear_CountEqualsZero()
{
var commandHistory = new CommandHistory<int>();
var collection = new List<int>();

commandHistory.AddThenExecute(new AddCommand<int>(collection, 5, "Add 5"));

commandHistory.Clear();

Assert.AreEqual(0, commandHistory.Count);
}
}
}

This file was deleted.

Loading

0 comments on commit 0901469

Please sign in to comment.