55using EventLogExpert . UI . Store . EventTable ;
66using Fluxor ;
77using NSubstitute ;
8+ using System . Collections . Immutable ;
89
910namespace EventLogExpert . UI . Tests . Store . EventTable ;
1011
@@ -27,8 +28,29 @@ public async Task HandleLoadColumns_ShouldLoadAllColumnsFromPreferences()
2728 await effects . HandleLoadColumns ( mockDispatcher ) ;
2829
2930 // Assert
30- mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( a =>
31- a . LoadedColumns . Count == Enum . GetValues < ColumnName > ( ) . Length ) ) ;
31+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
32+ action . LoadedColumns . Count == Enum . GetValues < ColumnName > ( ) . Length ) ) ;
33+ }
34+
35+ [ Fact ]
36+ public async Task HandleLoadColumns_ShouldLoadWidthsFromPreferences ( )
37+ {
38+ // Arrange
39+ var enabledColumns = new List < ColumnName > { ColumnName . Level } ;
40+ var savedWidths = new Dictionary < ColumnName , int >
41+ {
42+ { ColumnName . Level , 150 }
43+ } ;
44+
45+ var ( effects , mockDispatcher , mockPreferencesProvider ) = CreateEffects ( enabledColumns ) ;
46+ mockPreferencesProvider . ColumnWidthsPreference . Returns ( savedWidths ) ;
47+
48+ // Act
49+ await effects . HandleLoadColumns ( mockDispatcher ) ;
50+
51+ // Assert
52+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
53+ action . ColumnWidths [ ColumnName . Level ] == 150 ) ) ;
3254 }
3355
3456 [ Fact ]
@@ -46,9 +68,9 @@ public async Task HandleLoadColumns_ShouldMarkDisabledColumnsAsFalse()
4668 await effects . HandleLoadColumns ( mockDispatcher ) ;
4769
4870 // Assert
49- mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( a =>
50- a . LoadedColumns [ ColumnName . Source ] == false &&
51- a . LoadedColumns [ ColumnName . EventId ] == false ) ) ;
71+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
72+ action . LoadedColumns [ ColumnName . Source ] == false &&
73+ action . LoadedColumns [ ColumnName . EventId ] == false ) ) ;
5274 }
5375
5476 [ Fact ]
@@ -67,9 +89,60 @@ public async Task HandleLoadColumns_ShouldMarkEnabledColumnsAsTrue()
6789 await effects . HandleLoadColumns ( mockDispatcher ) ;
6890
6991 // Assert
70- mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( a =>
71- a . LoadedColumns [ ColumnName . Level ] == true &&
72- a . LoadedColumns [ ColumnName . DateAndTime ] == true ) ) ;
92+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
93+ action . LoadedColumns [ ColumnName . Level ] == true &&
94+ action . LoadedColumns [ ColumnName . DateAndTime ] == true ) ) ;
95+ }
96+
97+ [ Fact ]
98+ public async Task HandleLoadColumns_ShouldUseDefaultOrderWhenNotSaved ( )
99+ {
100+ // Arrange
101+ var enabledColumns = new List < ColumnName > { ColumnName . Level } ;
102+
103+ var ( effects , mockDispatcher , _) = CreateEffects ( enabledColumns ) ;
104+
105+ // Act
106+ await effects . HandleLoadColumns ( mockDispatcher ) ;
107+
108+ // Assert
109+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
110+ action . ColumnOrder . SequenceEqual ( ColumnDefaults . Order ) ) ) ;
111+ }
112+
113+ [ Fact ]
114+ public async Task HandleLoadColumns_ShouldUseDefaultWidthsWhenNotSaved ( )
115+ {
116+ // Arrange
117+ var enabledColumns = new List < ColumnName > { ColumnName . Level } ;
118+
119+ var ( effects , mockDispatcher , _) = CreateEffects ( enabledColumns ) ;
120+
121+ // Act
122+ await effects . HandleLoadColumns ( mockDispatcher ) ;
123+
124+ // Assert
125+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
126+ action . ColumnWidths [ ColumnName . Level ] == ColumnDefaults . GetWidth ( ColumnName . Level ) ) ) ;
127+ }
128+
129+ [ Fact ]
130+ public async Task HandleLoadColumns_ShouldUseSavedOrderWhenPresent ( )
131+ {
132+ // Arrange
133+ var enabledColumns = new List < ColumnName > { ColumnName . Source , ColumnName . Level } ;
134+ var savedOrder = new List < ColumnName > { ColumnName . Source , ColumnName . Level } ;
135+
136+ var ( effects , mockDispatcher , mockPreferencesProvider ) = CreateEffects ( enabledColumns ) ;
137+ mockPreferencesProvider . ColumnOrderPreference . Returns ( savedOrder ) ;
138+
139+ // Act
140+ await effects . HandleLoadColumns ( mockDispatcher ) ;
141+
142+ // Assert
143+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
144+ action . ColumnOrder [ 0 ] == ColumnName . Source &&
145+ action . ColumnOrder [ 1 ] == ColumnName . Level ) ) ;
73146 }
74147
75148 [ Fact ]
@@ -84,8 +157,82 @@ public async Task HandleLoadColumns_WhenNoColumnsEnabled_ShouldMarkAllAsFalse()
84157 await effects . HandleLoadColumns ( mockDispatcher ) ;
85158
86159 // Assert
87- mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( a =>
88- a . LoadedColumns . All ( kvp => kvp . Value == false ) ) ) ;
160+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
161+ action . LoadedColumns . All ( kvp => kvp . Value == false ) ) ) ;
162+ }
163+
164+ [ Fact ]
165+ public async Task HandleReorderColumn_ShouldPersistToPreferences ( )
166+ {
167+ // Arrange - state reflects post-reducer result (Source moved to index 0)
168+ var postReducerState = new EventTableState
169+ {
170+ ColumnOrder = [ ColumnName . Source , ColumnName . Level , ColumnName . DateAndTime ]
171+ } ;
172+
173+ var ( effects , mockDispatcher , mockPreferencesProvider ) = CreateEffects ( state : postReducerState ) ;
174+
175+ var action = new EventTableAction . ReorderColumn ( ColumnName . Source , ColumnName . Level , false ) ;
176+
177+ // Act
178+ await effects . HandleReorderColumn ( action , mockDispatcher ) ;
179+
180+ // Assert
181+ _ = mockPreferencesProvider . Received ( 1 ) . ColumnOrderPreference =
182+ Arg . Is < IEnumerable < ColumnName > > ( order => order . First ( ) == ColumnName . Source ) ;
183+ }
184+
185+ [ Fact ]
186+ public async Task HandleResetColumnDefaults_ShouldResetAllColumnSettingsToDefaults ( )
187+ {
188+ // Arrange
189+ var enabledColumns = new List < ColumnName > { ColumnName . Level , ColumnName . Source } ;
190+ var ( effects , mockDispatcher , mockPreferencesProvider ) = CreateEffects ( enabledColumns ) ;
191+
192+ // Act
193+ await effects . HandleResetColumnDefaults ( mockDispatcher ) ;
194+
195+ // Assert
196+ _ = mockPreferencesProvider . Received ( 1 ) . EnabledEventTableColumnsPreference =
197+ Arg . Is < IEnumerable < ColumnName > > ( c => c . SequenceEqual ( ColumnDefaults . EnabledColumns ) ) ;
198+ _ = mockPreferencesProvider . Received ( 1 ) . ColumnWidthsPreference =
199+ Arg . Is < IDictionary < ColumnName , int > > ( w => w . Count == 0 ) ;
200+ _ = mockPreferencesProvider . Received ( 1 ) . ColumnOrderPreference =
201+ Arg . Is < IEnumerable < ColumnName > > ( o => ! o . Any ( ) ) ;
202+
203+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
204+ action . ColumnWidths . SequenceEqual ( ColumnDefaults . Widths ) &&
205+ action . ColumnOrder . SequenceEqual ( ColumnDefaults . Order ) &&
206+ action . LoadedColumns [ ColumnName . Level ] == true &&
207+ action . LoadedColumns [ ColumnName . DateAndTime ] == true &&
208+ action . LoadedColumns [ ColumnName . Source ] == true &&
209+ action . LoadedColumns [ ColumnName . EventId ] == true &&
210+ action . LoadedColumns [ ColumnName . TaskCategory ] == true &&
211+ action . LoadedColumns [ ColumnName . ActivityId ] == false ) ) ;
212+ }
213+
214+ [ Fact ]
215+ public async Task HandleSetColumnWidth_ShouldPersistToPreferences ( )
216+ {
217+ // Arrange
218+ var postReducerState = new EventTableState
219+ {
220+ ColumnWidths = new Dictionary < ColumnName , int >
221+ {
222+ { ColumnName . Level , 200 }
223+ } . ToImmutableDictionary ( )
224+ } ;
225+
226+ var ( effects , mockDispatcher , mockPreferencesProvider ) = CreateEffects ( state : postReducerState ) ;
227+
228+ var action = new EventTableAction . SetColumnWidth ( ColumnName . Level , 200 ) ;
229+
230+ // Act
231+ await effects . HandleSetColumnWidth ( action , mockDispatcher ) ;
232+
233+ // Assert
234+ _ = mockPreferencesProvider . Received ( 1 ) . ColumnWidthsPreference =
235+ Arg . Is < IDictionary < ColumnName , int > > ( width => width [ ColumnName . Level ] == 200 ) ;
89236 }
90237
91238 [ Fact ]
@@ -107,11 +254,11 @@ public async Task HandleToggleColumn_ShouldOnlyChangeToggledColumn()
107254 await effects . HandleToggleColumn ( action , mockDispatcher ) ;
108255
109256 // Assert
110- mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( a =>
111- a . LoadedColumns [ ColumnName . Level ] == true &&
112- a . LoadedColumns [ ColumnName . DateAndTime ] == false &&
113- a . LoadedColumns [ ColumnName . Source ] == true &&
114- a . LoadedColumns [ ColumnName . EventId ] == true ) ) ;
257+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
258+ action . LoadedColumns [ ColumnName . Level ] == true &&
259+ action . LoadedColumns [ ColumnName . DateAndTime ] == false &&
260+ action . LoadedColumns [ ColumnName . Source ] == true &&
261+ action . LoadedColumns [ ColumnName . EventId ] == true ) ) ;
115262 }
116263
117264 [ Fact ]
@@ -132,8 +279,8 @@ public async Task HandleToggleColumn_ShouldUpdatePreferences()
132279
133280 // Assert
134281 _ = mockPreferencesProvider . Received ( 1 ) . EnabledEventTableColumnsPreference =
135- Arg . Is < IEnumerable < ColumnName > > ( cols =>
136- cols . Contains ( ColumnName . Source ) ) ;
282+ Arg . Is < IEnumerable < ColumnName > > ( columns =>
283+ columns . Contains ( ColumnName . Source ) ) ;
137284 }
138285
139286 [ Fact ]
@@ -153,10 +300,10 @@ public async Task HandleToggleColumn_WhenColumnDisabled_ShouldEnableIt()
153300 await effects . HandleToggleColumn ( action , mockDispatcher ) ;
154301
155302 // Assert
156- mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( a =>
157- a . LoadedColumns [ ColumnName . Level ] == true &&
158- a . LoadedColumns [ ColumnName . DateAndTime ] == true &&
159- a . LoadedColumns [ ColumnName . Source ] == true ) ) ;
303+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
304+ action . LoadedColumns [ ColumnName . Level ] == true &&
305+ action . LoadedColumns [ ColumnName . DateAndTime ] == true &&
306+ action . LoadedColumns [ ColumnName . Source ] == true ) ) ;
160307 }
161308
162309 [ Fact ]
@@ -177,10 +324,10 @@ public async Task HandleToggleColumn_WhenColumnEnabled_ShouldDisableIt()
177324 await effects . HandleToggleColumn ( action , mockDispatcher ) ;
178325
179326 // Assert
180- mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( a =>
181- a . LoadedColumns [ ColumnName . Level ] == false &&
182- a . LoadedColumns [ ColumnName . DateAndTime ] == true &&
183- a . LoadedColumns [ ColumnName . Source ] == true ) ) ;
327+ mockDispatcher . Received ( 1 ) . Dispatch ( Arg . Is < EventTableAction . LoadColumnsCompleted > ( action =>
328+ action . LoadedColumns [ ColumnName . Level ] == false &&
329+ action . LoadedColumns [ ColumnName . DateAndTime ] == true &&
330+ action . LoadedColumns [ ColumnName . Source ] == true ) ) ;
184331 }
185332
186333 [ Fact ]
@@ -202,11 +349,11 @@ public async Task HandleToggleColumn_WhenDisabling_ShouldRemoveFromPreferences()
202349
203350 // Assert
204351 var _ = mockPreferencesProvider . Received ( 1 ) . EnabledEventTableColumnsPreference =
205- Arg . Is < IEnumerable < ColumnName > > ( cols =>
206- cols . Contains ( ColumnName . Level ) &&
207- cols . Contains ( ColumnName . DateAndTime ) &&
208- ! cols . Contains ( ColumnName . Source ) &&
209- cols . Count ( ) == 2 ) ;
352+ Arg . Is < IEnumerable < ColumnName > > ( columns =>
353+ columns . Contains ( ColumnName . Level ) &&
354+ columns . Contains ( ColumnName . DateAndTime ) &&
355+ ! columns . Contains ( ColumnName . Source ) &&
356+ columns . Count ( ) == 2 ) ;
210357 }
211358
212359 [ Fact ]
@@ -226,10 +373,10 @@ public async Task HandleToggleColumn_WhenEnabling_ShouldPersistToPreferences()
226373
227374 // Assert
228375 _ = mockPreferencesProvider . Received ( 1 ) . EnabledEventTableColumnsPreference =
229- Arg . Is < IEnumerable < ColumnName > > ( cols =>
230- cols . Contains ( ColumnName . Level ) &&
231- cols . Contains ( ColumnName . Source ) &&
232- cols . Count ( ) == 2 ) ;
376+ Arg . Is < IEnumerable < ColumnName > > ( columns =>
377+ columns . Contains ( ColumnName . Level ) &&
378+ columns . Contains ( ColumnName . Source ) &&
379+ columns . Count ( ) == 2 ) ;
233380 }
234381
235382 [ Fact ]
@@ -259,12 +406,17 @@ public async Task HandleUpdateTable_ShouldDispatchUpdateCombinedEvents()
259406 }
260407
261408 private static ( EventTableEffects effects , IDispatcher mockDispatcher , IPreferencesProvider mockPreferencesProvider )
262- CreateEffects ( List < ColumnName > ? enabledColumns = null )
409+ CreateEffects ( List < ColumnName > ? enabledColumns = null , EventTableState ? state = null )
263410 {
264411 var mockPreferencesProvider = Substitute . For < IPreferencesProvider > ( ) ;
265412 mockPreferencesProvider . EnabledEventTableColumnsPreference . Returns ( enabledColumns ?? [ ] ) ;
413+ mockPreferencesProvider . ColumnWidthsPreference . Returns ( new Dictionary < ColumnName , int > ( ) ) ;
414+ mockPreferencesProvider . ColumnOrderPreference . Returns ( [ ] ) ;
415+
416+ var mockState = Substitute . For < IState < EventTableState > > ( ) ;
417+ mockState . Value . Returns ( state ?? new EventTableState ( ) ) ;
266418
267- var effects = new EventTableEffects ( mockPreferencesProvider ) ;
419+ var effects = new EventTableEffects ( mockPreferencesProvider , mockState ) ;
268420 var mockDispatcher = Substitute . For < IDispatcher > ( ) ;
269421
270422 return ( effects , mockDispatcher , mockPreferencesProvider ) ;
0 commit comments