@@ -267,6 +267,43 @@ await _renderer.Dispatcher.InvokeAsync(() =>
267
267
Assert . Equal ( "Not found" , renderedFrame . TextContent ) ;
268
268
}
269
269
270
+ [ Fact ]
271
+ public async Task LogsWarningWhenBothNotFoundAndNotFoundPageAreSet ( )
272
+ {
273
+ // Arrange
274
+ var logger = new TestLogger < Router > ( ) ;
275
+ var services = new ServiceCollection ( ) ;
276
+ services . AddSingleton < ILoggerFactory > ( new TestLoggerFactory ( logger ) ) ;
277
+ services . AddSingleton < NavigationManager > ( _navigationManager ) ;
278
+ services . AddSingleton < INavigationInterception , TestNavigationInterception > ( ) ;
279
+ services . AddSingleton < IScrollToLocationHash , TestScrollToLocationHash > ( ) ;
280
+ var serviceProvider = services . BuildServiceProvider ( ) ;
281
+
282
+ var renderer = new TestRenderer ( serviceProvider ) ;
283
+ renderer . ShouldHandleExceptions = true ;
284
+ var router = ( Router ) renderer . InstantiateComponent < Router > ( ) ;
285
+ router . AppAssembly = Assembly . GetExecutingAssembly ( ) ;
286
+ router . Found = routeData => ( builder ) => builder . AddContent ( 0 , $ "Rendering route matching { routeData . PageType } ") ;
287
+ renderer . AssignRootComponentId ( router ) ;
288
+
289
+ var parameters = new Dictionary < string , object >
290
+ {
291
+ { nameof ( Router . AppAssembly ) , typeof ( RouterTest ) . Assembly } ,
292
+ { nameof ( Router . NotFound ) , ( RenderFragment ) ( builder => builder . AddContent ( 0 , "Custom not found" ) ) } ,
293
+ { nameof ( Router . NotFoundPage ) , typeof ( NotFoundTestComponent ) }
294
+ } ;
295
+
296
+ // Act
297
+ await renderer . Dispatcher . InvokeAsync ( ( ) =>
298
+ router . SetParametersAsync ( ParameterView . FromDictionary ( parameters ) ) ) ;
299
+
300
+ // Assert
301
+ var warningLogs = logger . LogEntries . Where ( entry => entry . LogLevel == LogLevel . Warning ) . ToList ( ) ;
302
+ Assert . Single ( warningLogs ) ;
303
+ Assert . Contains ( "Both NotFound and NotFoundPage parameters are set on Router component" , warningLogs [ 0 ] . Message ) ;
304
+ Assert . Contains ( "NotFoundPage is preferred and NotFound will be deprecated" , warningLogs [ 0 ] . Message ) ;
305
+ }
306
+
270
307
internal class TestNavigationManager : NavigationManager
271
308
{
272
309
public TestNavigationManager ( ) =>
@@ -308,4 +345,51 @@ public class MatchAnythingComponent : ComponentBase { }
308
345
309
346
[ Route ( "a/b/c" ) ]
310
347
public class MultiSegmentRouteComponent : ComponentBase { }
348
+
349
+ [ Route ( "not-found" ) ]
350
+ public class NotFoundTestComponent : ComponentBase { }
351
+
352
+ public class TestLogger < T > : ILogger < T >
353
+ {
354
+ public List < LogEntry > LogEntries { get ; } = new List < LogEntry > ( ) ;
355
+
356
+ public IDisposable BeginScope < TState > ( TState state ) => null ;
357
+
358
+ public bool IsEnabled ( LogLevel logLevel ) => true ;
359
+
360
+ public void Log < TState > ( LogLevel logLevel , EventId eventId , TState state , Exception exception , Func < TState , Exception , string > formatter )
361
+ {
362
+ LogEntries . Add ( new LogEntry
363
+ {
364
+ LogLevel = logLevel ,
365
+ EventId = eventId ,
366
+ Message = formatter ( state , exception ) ,
367
+ Exception = exception
368
+ } ) ;
369
+ }
370
+ }
371
+
372
+ public class LogEntry
373
+ {
374
+ public LogLevel LogLevel { get ; set ; }
375
+ public EventId EventId { get ; set ; }
376
+ public string Message { get ; set ; }
377
+ public Exception Exception { get ; set ; }
378
+ }
379
+
380
+ public class TestLoggerFactory : ILoggerFactory
381
+ {
382
+ private readonly ILogger _logger ;
383
+
384
+ public TestLoggerFactory ( ILogger logger )
385
+ {
386
+ _logger = logger ;
387
+ }
388
+
389
+ public void AddProvider ( ILoggerProvider provider ) { }
390
+
391
+ public ILogger CreateLogger ( string categoryName ) => _logger ;
392
+
393
+ public void Dispose ( ) { }
394
+ }
311
395
}
0 commit comments