using AyCode.Core.Tests.TestModels; using AyCode.Services.Server.Tests.SignalRs; using AyCode.Services.SignalRs; using Bunit; using DevExpress.Blazor; using Microsoft.Extensions.DependencyInjection; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace AyCode.Blazor.Components.Tests.Grids; /// /// Tests for MgGridBase layout persistence functionality. /// Tests that column width changes are persisted and loaded correctly. /// [TestClass] public class MgGridBaseTests : BunitTestContext { private TestLogger _logger = null!; private TestableSignalRHub2 _hub = null!; private TestableSignalRClient2 _client = null!; private TestSignalRService2 _service = null!; private SignalRCrudTags _crudTags = null!; private const string StorageKey = "TestGrid_Master_AutoSave_0"; [TestInitialize] public void TestSetup() { Context = new BunitContext(); Context.Services.AddDevExpressBlazor(); _logger = new TestLogger(); _hub = new TestableSignalRHub2(); _service = new TestSignalRService2(); _client = new TestableSignalRClient2(_hub, _logger); _hub.RegisterService(_service, _client); _crudTags = new SignalRCrudTags( TestSignalRTags.DataSourceGetAll, TestSignalRTags.DataSourceGetItem, TestSignalRTags.DataSourceAdd, TestSignalRTags.DataSourceUpdate, TestSignalRTags.DataSourceRemove ); TestMgGridOrderItem.ClearLayoutStorage(); Context.JSInterop.Mode = JSRuntimeMode.Loose; } [TestCleanup] public void TestTeardown() => Context?.Dispose(); private IRenderedComponent RenderTestGrid(string autoSaveLayoutName = "TestGrid") { var dataSource = new TestGridOrderItemDataSource(_client, _crudTags); return Context!.Render(parameters => parameters .Add(p => p.DataSource, dataSource) .Add(p => p.Logger, _logger) .Add(p => p.SignalRClient, _client) .Add(p => p.AutoSaveLayoutName, autoSaveLayoutName) .Add(p => p.GetAllMessageTag, _crudTags.GetAllMessageTag) .Add(p => p.AddMessageTag, _crudTags.AddMessageTag) .Add(p => p.UpdateMessageTag, _crudTags.UpdateMessageTag) .Add(p => p.RemoveMessageTag, _crudTags.RemoveMessageTag) ); } #region Layout Persistence Tests [TestMethod] public async Task MgGridBase_ColumnWidth_ShouldBePersisted_WhenNewGridIsRendered() { // Arrange - Render first grid var cut1 = RenderTestGrid(); // Wait for data source to load await cut1.Instance.WaitForDataSourceLoadedAsync(); // Get columns from first grid var columns1 = cut1.Instance.GetDataColumns(); Assert.IsTrue(columns1.Count > 0, "Grid should have columns after data source loaded"); // Set column width on first grid (must use BeginUpdate/EndUpdate on the dispatcher) var firstColumn = columns1[0]; var expectedWidth = "150px"; await cut1.InvokeAsync(() => { cut1.Instance.BeginUpdate(); firstColumn.Width = expectedWidth; cut1.Instance.EndUpdate(); }); // Trigger layout save by disposing await cut1.Instance.DisposeAsync(); // Act - Render second grid with same TDataItem var cut2 = RenderTestGrid(); // Wait for data source to load await cut2.Instance.WaitForDataSourceLoadedAsync(); // Assert - Second grid should have the same column width var columns2 = cut2.Instance.GetDataColumns(); Assert.IsTrue(columns2.Count > 0, "Second grid should have columns"); var secondGridFirstColumn = columns2[0]; Assert.AreEqual(expectedWidth, secondGridFirstColumn.Width, $"Column width should be persisted. Expected: {expectedWidth}, Actual: {secondGridFirstColumn.Width}"); } [TestMethod] public async Task MgGridBase_LayoutStorage_ShouldContainLayout_AfterGridRenders() { // Arrange & Act var cut = RenderTestGrid(); await cut.Instance.WaitForDataSourceLoadedAsync(); // Assert Assert.IsTrue(TestMgGridOrderItem.LayoutStorage.ContainsKey(StorageKey), "Layout should be saved to storage after grid renders"); Assert.IsNotNull(TestMgGridOrderItem.LayoutStorage[StorageKey]); } [TestMethod] public async Task MgGridBase_DifferentGridNames_ShouldHaveDifferentLayouts() { // Arrange - Render first grid with name "Grid1" var cut1 = RenderTestGrid("Grid1"); await cut1.Instance.WaitForDataSourceLoadedAsync(); // Render second grid with name "Grid2" var cut2 = RenderTestGrid("Grid2"); await cut2.Instance.WaitForDataSourceLoadedAsync(); // Assert - Different storage keys should exist var storageKeys = TestMgGridOrderItem.LayoutStorage.Keys.ToList(); // There should be at least 2 different keys Assert.IsTrue(storageKeys.Count >= 2, $"Should have at least 2 storage keys, found: {string.Join(", ", storageKeys)}"); // Keys should contain Grid1 and Grid2 Assert.IsTrue(storageKeys.Any(k => k.Contains("Grid1")), $"Should have Grid1 key. Keys: {string.Join(", ", storageKeys)}"); Assert.IsTrue(storageKeys.Any(k => k.Contains("Grid2")), $"Should have Grid2 key. Keys: {string.Join(", ", storageKeys)}"); } [TestMethod] public async Task MgGridBase_IsMasterGrid_ShouldBeTrueWhenNoParentDataItem() { // Act var cut = RenderTestGrid(); await cut.Instance.WaitForDataSourceLoadedAsync(); // Assert Assert.IsTrue(cut.Instance.IsMasterGrid); } [TestMethod] public async Task MgGridBase_Columns_ShouldBeBuiltFromReflection() { // Arrange & Act var cut = RenderTestGrid(); await cut.Instance.WaitForDataSourceLoadedAsync(); // Assert - Should have columns for TestOrderItem properties var columns = cut.Instance.GetDataColumns(); Assert.IsTrue(columns.Count > 0, "Grid should have columns built from TDataItem"); // Verify some expected column names exist var columnNames = columns.Select(c => c.FieldName).ToList(); Assert.IsTrue(columnNames.Contains(nameof(TestOrderItem.Id)), "Should have Id column"); Assert.IsTrue(columnNames.Contains(nameof(TestOrderItem.ProductName)), "Should have ProductName column"); Assert.IsTrue(columnNames.Contains(nameof(TestOrderItem.Quantity)), "Should have Quantity column"); } #endregion }