@@ -242,9 +242,156 @@ public void RenderField_Should_Handle_Empty_Renderer_Collection()
242242 // Should return unsupported field type message
243243 }
244244
245+ [ Fact ]
246+ public void RenderField_Should_Detect_Correct_Type_For_Simple_MemberExpression ( )
247+ {
248+ // Arrange
249+ var model = new TestModel { Name = "Test" } ;
250+ var field = new FieldConfiguration < TestModel , string ? > ( x => x . Name ) ;
251+ var wrapper = new FieldConfigurationWrapper < TestModel , string ? > ( field ) ;
252+ Type ? detectedType = null ;
253+
254+ var mockRenderer = A . Fake < IFieldRenderer > ( ) ;
255+ A . CallTo ( ( ) => mockRenderer . CanRender ( A < Type > . _ , A < IFieldConfiguration < object , object > > . _ ) )
256+ . ReturnsLazily ( ( Type type , IFieldConfiguration < object , object > _ ) =>
257+ {
258+ detectedType = type ;
259+ return true ;
260+ } ) ;
261+ A . CallTo ( ( ) => mockRenderer . Render ( A < IFieldRenderContext < TestModel > > . _ ) )
262+ . Returns ( builder => builder . AddContent ( 0 , "Test" ) ) ;
263+
264+ var service = new FieldRendererService ( new [ ] { mockRenderer } , _serviceProvider ) ;
265+ var onValueChanged = EventCallback . Factory . Create < object ? > ( this , _ => { } ) ;
266+ var onDependencyChanged = EventCallback . Factory . Create ( this , ( ) => { } ) ;
267+
268+ // Act
269+ service . RenderField ( model , wrapper , onValueChanged , onDependencyChanged ) ;
270+
271+ // Assert
272+ // The GetActualFieldType method in FieldRendererService handles UnaryExpression
273+ // and returns the underlying property type
274+ detectedType . ShouldBe ( typeof ( string ) ) ;
275+ }
276+
277+
278+ [ Fact ]
279+ public void RenderField_Should_Detect_Correct_Type_For_Value_Type_MemberExpression ( )
280+ {
281+ // Arrange
282+ var model = new TestModel { Value = 42 } ;
283+ var field = new FieldConfiguration < TestModel , int > ( x => x . Value ) ;
284+ var wrapper = new FieldConfigurationWrapper < TestModel , int > ( field ) ;
285+ Type ? detectedType = null ;
286+
287+ var mockRenderer = A . Fake < IFieldRenderer > ( ) ;
288+ A . CallTo ( ( ) => mockRenderer . CanRender ( A < Type > . _ , A < IFieldConfiguration < object , object > > . _ ) )
289+ . ReturnsLazily ( ( Type type , IFieldConfiguration < object , object > _ ) =>
290+ {
291+ detectedType = type ;
292+ return true ;
293+ } ) ;
294+ A . CallTo ( ( ) => mockRenderer . Render ( A < IFieldRenderContext < TestModel > > . _ ) )
295+ . Returns ( builder => builder . AddContent ( 0 , "Test" ) ) ;
296+
297+ var service = new FieldRendererService ( new [ ] { mockRenderer } , _serviceProvider ) ;
298+ var onValueChanged = EventCallback . Factory . Create < object ? > ( this , _ => { } ) ;
299+ var onDependencyChanged = EventCallback . Factory . Create ( this , ( ) => { } ) ;
300+
301+ // Act
302+ service . RenderField ( model , wrapper , onValueChanged , onDependencyChanged ) ;
303+
304+ // Assert
305+ // The GetActualFieldType method detects int from the UnaryExpression
306+ detectedType . ShouldBe ( typeof ( int ) ) ;
307+ }
308+
309+ [ Fact ]
310+ public void RenderField_Should_Detect_Correct_Type_For_Nullable_Type ( )
311+ {
312+ // Arrange
313+ var model = new TestModel { NullableValue = 42 } ;
314+ var field = new FieldConfiguration < TestModel , int ? > ( x => x . NullableValue ) ;
315+ var wrapper = new FieldConfigurationWrapper < TestModel , int ? > ( field ) ;
316+ Type ? detectedType = null ;
317+
318+ var mockRenderer = A . Fake < IFieldRenderer > ( ) ;
319+ A . CallTo ( ( ) => mockRenderer . CanRender ( A < Type > . _ , A < IFieldConfiguration < object , object > > . _ ) )
320+ . ReturnsLazily ( ( Type type , IFieldConfiguration < object , object > _ ) =>
321+ {
322+ detectedType = type ;
323+ return true ;
324+ } ) ;
325+ A . CallTo ( ( ) => mockRenderer . Render ( A < IFieldRenderContext < TestModel > > . _ ) )
326+ . Returns ( builder => builder . AddContent ( 0 , "Test" ) ) ;
327+
328+ var service = new FieldRendererService ( new [ ] { mockRenderer } , _serviceProvider ) ;
329+ var onValueChanged = EventCallback . Factory . Create < object ? > ( this , _ => { } ) ;
330+ var onDependencyChanged = EventCallback . Factory . Create ( this , ( ) => { } ) ;
331+
332+ // Act
333+ service . RenderField ( model , wrapper , onValueChanged , onDependencyChanged ) ;
334+
335+ // Assert
336+ detectedType . ShouldBe ( typeof ( int ? ) ) ;
337+ }
338+
339+
340+ [ Fact ]
341+ public void RenderField_Should_Use_Correct_ActualFieldType_In_Context ( )
342+ {
343+ // Arrange
344+ var model = new TestModel { DateCreated = DateTime . Now } ;
345+ var field = new FieldConfiguration < TestModel , DateTime > ( x => x . DateCreated ) ;
346+ var wrapper = new FieldConfigurationWrapper < TestModel , DateTime > ( field ) ;
347+ IFieldRenderContext < TestModel > ? capturedContext = null ;
348+
349+ var mockRenderer = A . Fake < IFieldRenderer > ( ) ;
350+ A . CallTo ( ( ) => mockRenderer . CanRender ( typeof ( DateTime ) , A < IFieldConfiguration < object , object > > . _ ) )
351+ . Returns ( true ) ;
352+ A . CallTo ( ( ) => mockRenderer . Render ( A < IFieldRenderContext < TestModel > > . _ ) )
353+ . ReturnsLazily ( ( IFieldRenderContext < TestModel > ctx ) =>
354+ {
355+ capturedContext = ctx ;
356+ return builder => builder . AddContent ( 0 , "Test" ) ;
357+ } ) ;
358+
359+ var service = new FieldRendererService ( new [ ] { mockRenderer } , _serviceProvider ) ;
360+ var onValueChanged = EventCallback . Factory . Create < object ? > ( this , _ => { } ) ;
361+ var onDependencyChanged = EventCallback . Factory . Create ( this , ( ) => { } ) ;
362+
363+ // Act
364+ service . RenderField ( model , wrapper , onValueChanged , onDependencyChanged ) ;
365+
366+ // Assert
367+ capturedContext . ShouldNotBeNull ( ) ;
368+ capturedContext . ActualFieldType . ShouldBe ( typeof ( DateTime ) ) ;
369+ }
370+
371+
372+ public enum TestEnum
373+ {
374+ Active ,
375+ Inactive ,
376+ Pending
377+ }
378+
379+ public class NestedModel
380+ {
381+ public string NestedProperty { get ; set ; } = string . Empty ;
382+ }
383+
245384 public class TestModel
246385 {
247386 public string ? Name { get ; set ; }
248387 public int Value { get ; set ; }
388+ public int ? NullableValue { get ; set ; }
389+ public DateTime DateCreated { get ; set ; }
390+ public DateTime ? DateModified { get ; set ; }
391+ public TestEnum Status { get ; set ; }
392+ public bool IsActive { get ; set ; }
393+ public decimal Price { get ; set ; }
394+ public List < string > Tags { get ; set ; } = new ( ) ;
395+ public NestedModel NestedModel { get ; set ; } = new ( ) ;
249396 }
250397}
0 commit comments