using System.Collections;
using AyCode.Core.Enums;
using AyCode.Core.Extensions;
using AyCode.Core.Helpers;
using AyCode.Core.Serializers.Jsons;
using AyCode.Core.Tests.TestModels;
using AyCode.Services.Server.SignalRs;
using AyCode.Services.SignalRs;
namespace AyCode.Services.Server.Tests.SignalRs.SignalRDatasources;
#region Abstract Test Base
///
/// Base class for SignalR DataSource tests with full round-trip coverage.
/// Tests the complete path: DataSource -> SignalRClient -> SignalRHub -> Service -> Response -> SignalRClient -> DataSource
/// Derived classes specify the serializer type and collection type.
///
/// The concrete DataSource type
/// The inner list type (List or AcObservableCollection)
public abstract class SignalRDataSourceTestBase
where TDataSource : AcSignalRDataSource
where TIList : class, IList
{
protected abstract AcSerializerOptions SerializerOption { get; }
protected abstract TDataSource CreateDataSource(TestableSignalRClient2 client, SignalRCrudTags crudTags);
protected TestLogger _logger = null!;
protected TestableSignalRHub2 _hub = null!;
protected TestableSignalRClient2 _client = null!;
protected TestSignalRService2 _service = null!;
protected SignalRCrudTags _crudTags = null!;
[TestInitialize]
public void Setup()
{
_logger = new TestLogger();
_hub = new TestableSignalRHub2();
_service = new TestSignalRService2();
_client = new TestableSignalRClient2(_hub, _logger);
_hub.SetSerializerType(SerializerOption);
_hub.RegisterService(_service, _client);
_crudTags = new SignalRCrudTags(
TestSignalRTags.DataSourceGetAll,
TestSignalRTags.DataSourceGetItem,
TestSignalRTags.DataSourceAdd,
TestSignalRTags.DataSourceUpdate,
TestSignalRTags.DataSourceRemove
);
}
#region LoadDataSource Tests
[TestMethod]
public virtual async Task LoadDataSource_ReturnsAllItems()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
Assert.AreEqual(3, dataSource.Count);
Assert.AreEqual("Product A", dataSource[0].ProductName);
Assert.AreEqual("Product B", dataSource[1].ProductName);
Assert.AreEqual("Product C", dataSource[2].ProductName);
}
[TestMethod]
public virtual async Task LoadDataSource_ClearsChangeTracking_ByDefault()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 999, ProductName = "Tracked" });
Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
await dataSource.LoadDataSource();
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task LoadDataSource_PreservesChangeTracking_WhenFalse()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
dataSource.Add(new TestOrderItem { Id = 999, ProductName = "Tracked" });
await dataSource.LoadDataSource(clearChangeTracking: false);
Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task LoadDataSource_InvokesOnDataSourceLoaded()
{
var dataSource = CreateDataSource(_client, _crudTags);
var callbackInvoked = false;
dataSource.OnDataSourceLoaded = () => { callbackInvoked = true; return Task.CompletedTask; };
await dataSource.LoadDataSource();
Assert.IsTrue(callbackInvoked);
}
[TestMethod]
public virtual async Task LoadDataSource_MultipleCalls_RefreshesData()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var firstCount = dataSource.Count;
await dataSource.LoadDataSource();
var secondCount = dataSource.Count;
Assert.AreEqual(firstCount, secondCount);
Assert.AreEqual(3, secondCount);
}
#endregion
#region LoadDataSourceAsync Tests
[TestMethod]
public virtual async Task LoadDataSourceAsync_LoadsDataViaCallback()
{
var dataSource = CreateDataSource(_client, _crudTags);
var loadCompleted = false;
dataSource.OnDataSourceLoaded = () =>
{
loadCompleted = true;
return Task.CompletedTask;
};
await dataSource.LoadDataSourceAsync();
Assert.IsTrue(TaskHelper.WaitTo(() => loadCompleted, 5000));
Assert.AreEqual(3, dataSource.Count);
}
#endregion
#region LoadItem Tests
[TestMethod]
public virtual async Task LoadItem_ReturnsSingleItem()
{
var dataSource = CreateDataSource(_client, _crudTags);
var result = await dataSource.LoadItem(2);
Assert.IsNotNull(result);
Assert.AreEqual(2, result.Id);
Assert.AreEqual("Product B", result.ProductName);
}
[TestMethod]
public virtual async Task LoadItem_AddsToDataSource_WhenNotExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
Assert.AreEqual(0, dataSource.Count);
await dataSource.LoadItem(1);
Assert.AreEqual(1, dataSource.Count);
Assert.AreEqual("Product A", dataSource[0].ProductName);
}
[TestMethod]
public virtual async Task LoadItem_UpdatesExisting_WhenAlreadyLoaded()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var originalItem = dataSource[0];
var reloaded = await dataSource.LoadItem(originalItem.Id);
Assert.AreEqual(3, dataSource.Count);
Assert.IsNotNull(reloaded);
}
[TestMethod]
public virtual async Task LoadItem_InvokesOnDataSourceItemChanged()
{
var dataSource = CreateDataSource(_client, _crudTags);
ItemChangedEventArgs? eventArgs = null;
dataSource.OnDataSourceItemChanged = args => { eventArgs = args; return Task.CompletedTask; };
await dataSource.LoadItem(1);
Assert.IsNotNull(eventArgs);
Assert.AreEqual(TrackingState.Get, eventArgs.TrackingState);
Assert.AreEqual(1, eventArgs.Item.Id);
}
[TestMethod]
public virtual async Task LoadItem_ReturnsNull_WhenNotFound()
{
var dataSource = CreateDataSource(_client, _crudTags);
var result = await dataSource.LoadItem(9999);
Assert.IsNull(result);
}
#endregion
#region Add Tests
[TestMethod]
public virtual async Task Add_WithAutoSave_AddsItem()
{
var dataSource = CreateDataSource(_client, _crudTags);
var newItem = new TestOrderItem { Id = 100, ProductName = "New Product", Quantity = 5, UnitPrice = 50m };
var result = await dataSource.Add(newItem, autoSave: true);
Assert.AreEqual(1, dataSource.Count);
Assert.AreEqual("New Product", result.ProductName);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual void Add_WithoutAutoSave_AddsToTrackingOnly()
{
var dataSource = CreateDataSource(_client, _crudTags);
var newItem = new TestOrderItem { Id = 100, ProductName = "New Product" };
dataSource.Add(newItem);
Assert.AreEqual(1, dataSource.Count);
Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
Assert.AreEqual(TrackingState.Add, dataSource.GetTrackingItems()[0].TrackingState);
}
[TestMethod]
public virtual void Add_DuplicateId_ThrowsException()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 100, ProductName = "First" });
Assert.ThrowsExactly(() =>
{
dataSource.Add(new TestOrderItem { Id = 100, ProductName = "Duplicate" });
});
}
[TestMethod]
public virtual void Add_DefaultId_ThrowsException()
{
var dataSource = CreateDataSource(_client, _crudTags);
Assert.ThrowsExactly(() =>
{
dataSource.Add(new TestOrderItem { Id = 0, ProductName = "Invalid" });
});
}
[TestMethod]
public virtual void AddRange_AddsMultipleItems()
{
var dataSource = CreateDataSource(_client, _crudTags);
var items = new[]
{
new TestOrderItem { Id = 101, ProductName = "Item 1" },
new TestOrderItem { Id = 102, ProductName = "Item 2" },
new TestOrderItem { Id = 103, ProductName = "Item 3" }
};
dataSource.AddRange(items);
Assert.AreEqual(3, dataSource.Count);
}
#endregion
#region AddOrUpdate Tests
[TestMethod]
public virtual async Task AddOrUpdate_AddsNew_WhenNotExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
var newItem = new TestOrderItem { Id = 200, ProductName = "Brand New" };
var result = await dataSource.AddOrUpdate(newItem, autoSave: true);
Assert.AreEqual(1, dataSource.Count);
Assert.AreEqual("Brand New", result.ProductName);
}
[TestMethod]
public virtual async Task AddOrUpdate_UpdatesExisting_WhenExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var existingId = dataSource[0].Id;
var updatedItem = new TestOrderItem { Id = existingId, ProductName = "Updated Name", Quantity = 999 };
_ = await dataSource.AddOrUpdate(updatedItem, autoSave: true);
Assert.AreEqual(3, dataSource.Count);
Assert.AreEqual("Updated Name", dataSource[0].ProductName);
}
#endregion
#region Insert Tests
[TestMethod]
public virtual void Insert_AtIndex_InsertsCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "First" });
dataSource.Add(new TestOrderItem { Id = 3, ProductName = "Third" });
dataSource.Insert(1, new TestOrderItem { Id = 2, ProductName = "Second" });
Assert.AreEqual(3, dataSource.Count);
Assert.AreEqual("Second", dataSource[1].ProductName);
Assert.AreEqual(3, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task Insert_WithAutoSave_SavesImmediately()
{
var dataSource = CreateDataSource(_client, _crudTags);
var newItem = new TestOrderItem { Id = 500, ProductName = "Inserted" };
_ = await dataSource.Insert(0, newItem, autoSave: true);
Assert.AreEqual(1, dataSource.Count);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
#endregion
#region Update Tests
[TestMethod]
public virtual async Task Update_ByIndex_UpdatesCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var updatedItem = new TestOrderItem
{
Id = dataSource[0].Id,
ProductName = "Updated Product",
Quantity = 100
};
_ = await dataSource.Update(0, updatedItem, autoSave: true);
Assert.AreEqual("Updated Product", dataSource[0].ProductName);
Assert.AreEqual(100, dataSource[0].Quantity);
}
[TestMethod]
public virtual async Task Update_ByItem_UpdatesCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var updatedItem = new TestOrderItem
{
Id = dataSource[1].Id,
ProductName = "Updated B",
Quantity = 50
};
_ = await dataSource.Update(updatedItem, autoSave: true);
Assert.AreEqual("Updated B", dataSource[1].ProductName);
}
[TestMethod]
public virtual void Indexer_Set_TracksUpdate()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Original" });
dataSource[0] = new TestOrderItem { Id = 1, ProductName = "Modified" };
Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
Assert.AreEqual(TrackingState.Add, dataSource.GetTrackingItems()[0].TrackingState);
}
#endregion
#region Remove Tests
[TestMethod]
public virtual async Task Remove_ById_RemovesItem()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var idToRemove = dataSource[0].Id;
var result = await dataSource.Remove(idToRemove, autoSave: true);
Assert.IsTrue(result);
Assert.AreEqual(2, dataSource.Count);
}
[TestMethod]
public virtual async Task Remove_ByItem_RemovesItem()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var itemToRemove = dataSource[1];
var result = await dataSource.Remove(itemToRemove, autoSave: true);
Assert.IsTrue(result);
Assert.AreEqual(2, dataSource.Count);
}
[TestMethod]
public virtual void Remove_WithoutAutoSave_TracksRemoval()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "ToRemove" });
dataSource.GetTrackingItems().Clear();
dataSource.Remove(dataSource[0]);
Assert.AreEqual(0, dataSource.Count);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
Assert.AreEqual(TrackingState.Remove, dataSource.GetTrackingItems()[0].TrackingState);
}
[TestMethod]
public virtual void RemoveAt_RemovesCorrectItem()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "First" });
dataSource.Add(new TestOrderItem { Id = 2, ProductName = "Second" });
dataSource.Add(new TestOrderItem { Id = 3, ProductName = "Third" });
dataSource.GetTrackingItems().Clear();
dataSource.RemoveAt(1);
Assert.AreEqual(2, dataSource.Count);
Assert.AreEqual("First", dataSource[0].ProductName);
Assert.AreEqual("Third", dataSource[1].ProductName);
}
[TestMethod]
public virtual async Task RemoveAt_WithAutoSave_SavesImmediately()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
await dataSource.RemoveAt(0, autoSave: true);
Assert.AreEqual(2, dataSource.Count);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual void TryRemove_ReturnsTrue_WhenExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Test" });
var result = dataSource.TryRemove(1, out var removedItem);
Assert.IsTrue(result);
Assert.IsNotNull(removedItem);
Assert.AreEqual("Test", removedItem.ProductName);
}
[TestMethod]
public virtual void TryRemove_ReturnsFalse_WhenNotExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
var result = dataSource.TryRemove(9999, out var removedItem);
Assert.IsFalse(result);
Assert.IsNull(removedItem);
}
#endregion
#region SaveChanges Tests
[TestMethod]
public virtual async Task SaveChanges_SavesTrackedItems()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 101, ProductName = "Item 1" });
dataSource.Add(new TestOrderItem { Id = 102, ProductName = "Item 2" });
var unsaved = await dataSource.SaveChanges();
Assert.AreEqual(0, unsaved.Count);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task SaveChangesAsync_ClearsTracking()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 103, ProductName = "Item 3" });
await dataSource.SaveChangesAsync();
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task SaveItem_ById_SavesSpecificItem()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 201, ProductName = "Specific" });
var result = await dataSource.SaveItem(201);
Assert.AreEqual("Specific", result.ProductName);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task SaveItem_WithTrackingState_SavesCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var item = dataSource[0];
var result = await dataSource.SaveItem(item, TrackingState.Update);
Assert.IsNotNull(result);
}
#endregion
#region Tracking Tests
[TestMethod]
public virtual void SetTrackingStateToUpdate_MarksItemForUpdate()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Test" });
//await dataSource.SaveChanges(); // Előbb mentsük el, hogy ne Add legyen a tracking state
dataSource.SetTrackingStateToUpdate(dataSource[0]);
Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
Assert.AreEqual(TrackingState.Update, dataSource.GetTrackingItems()[0].TrackingState);
}
[TestMethod]
public virtual void SetTrackingStateToUpdate_DoesNotChangeAddState()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "New Item" });
dataSource.SetTrackingStateToUpdate(dataSource[0]);
Assert.AreEqual(TrackingState.Add, dataSource.GetTrackingItems()[0].TrackingState);
}
[TestMethod]
public virtual void TryGetTrackingItem_ReturnsTrue_WhenTracked()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Tracked" });
var result = dataSource.TryGetTrackingItem(1, out var trackingItem);
Assert.IsTrue(result);
Assert.IsNotNull(trackingItem);
Assert.AreEqual(TrackingState.Add, trackingItem.TrackingState);
}
[TestMethod]
public virtual void TryGetTrackingItem_ReturnsFalse_WhenNotTracked()
{
var dataSource = CreateDataSource(_client, _crudTags);
var result = dataSource.TryGetTrackingItem(9999, out var trackingItem);
Assert.IsFalse(result);
Assert.IsNull(trackingItem);
}
#endregion
#region Rollback Tests
[TestMethod]
public virtual void TryRollbackItem_RevertsAddedItem()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Added" });
var result = dataSource.TryRollbackItem(1, out var originalValue);
Assert.IsTrue(result);
Assert.AreEqual(0, dataSource.Count);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task TryRollbackItem_RevertsUpdatedItem()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var originalName = dataSource[0].ProductName;
dataSource[0] = new TestOrderItem { Id = dataSource[0].Id, ProductName = "Changed" };
var result = dataSource.TryRollbackItem(dataSource[0].Id, out var originalValue);
Assert.IsTrue(result);
Assert.IsNotNull(originalValue);
}
[TestMethod]
public virtual void Rollback_RevertsAllChanges()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Item1" });
dataSource.Add(new TestOrderItem { Id = 2, ProductName = "Item2" });
dataSource.Rollback();
Assert.AreEqual(0, dataSource.Count);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
#endregion
#region Collection Operations Tests
[TestMethod]
public virtual async Task Count_ReturnsCorrectValue()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
Assert.AreEqual(3, dataSource.Count);
}
[TestMethod]
public virtual void Clear_RemovesAllItems()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Item1" });
dataSource.Add(new TestOrderItem { Id = 2, ProductName = "Item2" });
dataSource.Clear();
Assert.AreEqual(0, dataSource.Count);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual void Clear_WithoutClearingTracking_PreservesTracking()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Item1" });
dataSource.Clear(clearChangeTracking: false);
Assert.AreEqual(0, dataSource.Count);
Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task Contains_ReturnsTrue_WhenItemExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
Assert.IsTrue(dataSource.Contains(dataSource[0]));
}
[TestMethod]
public virtual void Contains_ReturnsFalse_WhenItemNotExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
Assert.IsFalse(dataSource.Contains(new TestOrderItem { Id = 9999 }));
}
[TestMethod]
public virtual async Task IndexOf_ReturnsCorrectIndex()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
Assert.AreEqual(0, dataSource.IndexOf(dataSource[0]));
Assert.AreEqual(1, dataSource.IndexOf(dataSource[1]));
Assert.AreEqual(2, dataSource.IndexOf(dataSource[2]));
}
[TestMethod]
public virtual void IndexOf_ById_ReturnsCorrectIndex()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 5, ProductName = "Item5" });
Assert.AreEqual(0, dataSource.IndexOf(5));
}
[TestMethod]
public virtual void TryGetIndex_ReturnsTrue_WhenExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 10, ProductName = "Test" });
var result = dataSource.TryGetIndex(10, out var index);
Assert.IsTrue(result);
Assert.AreEqual(0, index);
}
[TestMethod]
public virtual async Task TryGetValue_ReturnsItem_WhenExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var result = dataSource.TryGetValue(1, out var item);
Assert.IsTrue(result);
Assert.IsNotNull(item);
Assert.AreEqual("Product A", item.ProductName);
}
[TestMethod]
public virtual void TryGetValue_ReturnsFalse_WhenNotExists()
{
var dataSource = CreateDataSource(_client, _crudTags);
var result = dataSource.TryGetValue(9999, out var item);
Assert.IsFalse(result);
Assert.IsNull(item);
}
[TestMethod]
public virtual async Task CopyTo_CopiesAllItems()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var array = new TestOrderItem[3];
dataSource.CopyTo(array);
Assert.AreEqual("Product A", array[0].ProductName);
Assert.AreEqual("Product B", array[1].ProductName);
Assert.AreEqual("Product C", array[2].ProductName);
}
[TestMethod]
public virtual async Task GetEnumerator_EnumeratesAllItems()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var count = dataSource.Count();
Assert.AreEqual(3, count);
}
[TestMethod]
public virtual async Task AsReadOnly_ReturnsReadOnlyCollection()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var readOnly = dataSource.AsReadOnly();
Assert.AreEqual(3, readOnly.Count);
Assert.IsInstanceOfType(readOnly, typeof(System.Collections.ObjectModel.ReadOnlyCollection));
}
#endregion
#region Working Reference List Tests
[TestMethod]
public virtual async Task SetWorkingReferenceList_SetsNewInnerList()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var externalList = Activator.CreateInstance();
dataSource.SetWorkingReferenceList(externalList);
Assert.IsTrue(dataSource.HasWorkingReferenceList);
Assert.AreEqual(3, dataSource.Count);
}
[TestMethod]
public virtual async Task GetReferenceInnerList_ReturnsInnerList()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
var innerList = dataSource.GetReferenceInnerList();
Assert.IsNotNull(innerList);
Assert.AreEqual(3, innerList.Count);
}
#endregion
#region Sync State Tests
[TestMethod]
public virtual void IsSyncing_IsFalse_Initially()
{
var dataSource = CreateDataSource(_client, _crudTags);
Assert.IsFalse(dataSource.IsSyncing);
}
[TestMethod]
public virtual async Task OnSyncingStateChanged_Fires_DuringLoad()
{
var dataSource = CreateDataSource(_client, _crudTags);
var syncStarted = false;
var syncEnded = false;
dataSource.OnSyncingStateChanged += isSyncing =>
{
if (isSyncing) syncStarted = true;
else syncEnded = true;
};
await dataSource.LoadDataSource();
Assert.IsTrue(syncStarted);
Assert.IsTrue(syncEnded);
}
#endregion
#region Context and Filter Tests
[TestMethod]
public virtual void ContextIds_CanBeSetAndRetrieved()
{
var dataSource = CreateDataSource(_client, _crudTags);
var contextIds = new object[] { 1, "test", Guid.NewGuid() };
dataSource.ContextIds = contextIds;
Assert.AreEqual(3, dataSource.ContextIds?.Length);
}
[TestMethod]
public virtual void FilterText_CanBeSetAndRetrieved()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.FilterText = "search term";
Assert.AreEqual("search term", dataSource.FilterText);
}
#endregion
#region IList Interface Tests
[TestMethod]
public virtual void IList_Add_ReturnsCorrectIndex()
{
var dataSource = CreateDataSource(_client, _crudTags);
var item = new TestOrderItem { Id = 1, ProductName = "Test" };
var index = ((IList)dataSource).Add(item);
Assert.AreEqual(0, index);
}
[TestMethod]
public virtual void IList_Contains_WorksCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
var item = new TestOrderItem { Id = 1, ProductName = "Test" };
dataSource.Add(item);
Assert.IsTrue(((IList)dataSource).Contains(item));
}
[TestMethod]
public virtual void IList_IndexOf_WorksCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
var item = new TestOrderItem { Id = 1, ProductName = "Test" };
dataSource.Add(item);
Assert.AreEqual(0, ((IList)dataSource).IndexOf(item));
}
[TestMethod]
public virtual void IList_Insert_WorksCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "First" });
var newItem = new TestOrderItem { Id = 2, ProductName = "Inserted" };
((IList)dataSource).Insert(0, newItem);
Assert.AreEqual("Inserted", dataSource[0].ProductName);
}
[TestMethod]
public virtual void IList_Remove_WorksCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
var item = new TestOrderItem { Id = 1, ProductName = "Test" };
dataSource.Add(item);
((IList)dataSource).Remove(item);
Assert.AreEqual(0, dataSource.Count);
}
[TestMethod]
public virtual void IList_Indexer_GetSet_WorksCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Original" });
((IList)dataSource)[0] = new TestOrderItem { Id = 1, ProductName = "Modified" };
Assert.AreEqual("Modified", dataSource[0].ProductName);
}
[TestMethod]
public virtual void ICollection_CopyTo_WorksCorrectly()
{
var dataSource = CreateDataSource(_client, _crudTags);
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Item1" });
dataSource.Add(new TestOrderItem { Id = 2, ProductName = "Item2" });
var array = new TestOrderItem[2];
((ICollection)dataSource).CopyTo(array, 0);
Assert.AreEqual("Item1", array[0].ProductName);
Assert.AreEqual("Item2", array[1].ProductName);
}
[TestMethod]
public virtual void IsSynchronized_ReturnsTrue()
{
var dataSource = CreateDataSource(_client, _crudTags);
Assert.IsTrue(dataSource.IsSynchronized);
}
[TestMethod]
public virtual void SyncRoot_IsNotNull()
{
var dataSource = CreateDataSource(_client, _crudTags);
Assert.IsNotNull(dataSource.SyncRoot);
}
[TestMethod]
public virtual void IsFixedSize_ReturnsFalse()
{
var dataSource = CreateDataSource(_client, _crudTags);
Assert.IsFalse(dataSource.IsFixedSize);
}
[TestMethod]
public virtual void IsReadOnly_ReturnsFalse()
{
var dataSource = CreateDataSource(_client, _crudTags);
Assert.IsFalse(((IList)dataSource).IsReadOnly);
}
#endregion
#region Edge Cases
[TestMethod]
public virtual async Task Indexer_OutOfRange_ThrowsException()
{
var dataSource = CreateDataSource(_client, _crudTags);
await dataSource.LoadDataSource();
Assert.ThrowsExactly(() => _ = dataSource[999]);
}
[TestMethod]
public virtual void Add_ThenRemove_ClearsTracking()
{
var dataSource = CreateDataSource(_client, _crudTags);
var item = new TestOrderItem { Id = 1, ProductName = "Temporary" };
dataSource.Add(item);
Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
dataSource.Remove(item);
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
}
[TestMethod]
public virtual async Task ComplexWorkflow_AddUpdateRemoveSave()
{
var dataSource = CreateDataSource(_client, _crudTags);
// Add items
dataSource.Add(new TestOrderItem { Id = 1, ProductName = "Item1", Quantity = 10 });
dataSource.Add(new TestOrderItem { Id = 2, ProductName = "Item2", Quantity = 20 });
Assert.AreEqual(2, dataSource.GetTrackingItems().Count);
// Save
await dataSource.SaveChanges();
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
// Update
dataSource[0] = new TestOrderItem { Id = 1, ProductName = "Updated1", Quantity = 100 };
Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
Assert.AreEqual(TrackingState.Update, dataSource.GetTrackingItems()[0].TrackingState);
// Remove
dataSource.Remove(dataSource[1]);
Assert.AreEqual(2, dataSource.GetTrackingItems().Count);
// Save all changes
await dataSource.SaveChanges();
Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
Assert.AreEqual(1, dataSource.Count);
}
#endregion
}
#endregion