@@ -527,4 +527,115 @@ public async Task FindTrainConnectionsAsync_WithInvalidStationB_ReturnsError()
527527 // Assert
528528 Assert . Contains ( "Could not find station 'InvalidStation'" , result ) ;
529529 }
530+
531+ [ Fact ]
532+ public async Task FindTrainConnectionsAsync_WhenNoChangesAvailable_ReturnsWarning ( )
533+ {
534+ // Arrange
535+ var stationXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
536+ <stations>
537+ <station name=""Frankfurt Hbf"" eva=""8000105"" ds100=""FF""/>
538+ </stations>" ;
539+
540+ var timetableXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
541+ <timetable station=""Frankfurt Hbf"">
542+ <s id=""123456"">
543+ <tl c=""ICE"" n=""123"" f=""Berlin Hbf""/>
544+ <dp pt=""2511061430"" pp=""7"" ppth=""Frankfurt Hbf|Mannheim|Berlin Hbf""/>
545+ </s>
546+ </timetable>" ;
547+
548+ var mockHandler = new Mock < HttpMessageHandler > ( ) ;
549+ var requestCount = 0 ;
550+ mockHandler . Protected ( )
551+ . Setup < Task < HttpResponseMessage > > (
552+ "SendAsync" ,
553+ ItExpr . IsAny < HttpRequestMessage > ( ) ,
554+ ItExpr . IsAny < CancellationToken > ( ) )
555+ . ReturnsAsync ( ( ) =>
556+ {
557+ requestCount ++ ;
558+ // First two calls are station lookups
559+ if ( requestCount <= 2 )
560+ return new HttpResponseMessage { StatusCode = HttpStatusCode . OK , Content = new StringContent ( stationXml ) } ;
561+ // Third is timetable
562+ if ( requestCount == 3 )
563+ return new HttpResponseMessage { StatusCode = HttpStatusCode . OK , Content = new StringContent ( timetableXml ) } ;
564+ // Fourth is full changes - simulate failure
565+ return new HttpResponseMessage { StatusCode = HttpStatusCode . InternalServerError , Content = new StringContent ( "Server Error" ) } ;
566+ } ) ;
567+
568+ var httpClient = new HttpClient ( mockHandler . Object ) { BaseAddress = new Uri ( _config . BaseUrl ) } ;
569+ var service = new TimeTableService ( httpClient , _mockOptions . Object ) ;
570+
571+ // Act
572+ var result = await service . FindTrainConnectionsAsync ( "Frankfurt" , "Berlin" ) ;
573+
574+ // Assert
575+ Assert . Contains ( "Train Connection Analysis" , result ) ;
576+ Assert . Contains ( "⚠ No changes available" , result ) ;
577+ }
578+
579+ [ Fact ]
580+ public async Task FindTrainConnectionsAsync_WhenNoConnectionsFound_ReturnsNoConnectionsMessage ( )
581+ {
582+ // Arrange
583+ var stationXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
584+ <stations>
585+ <station name=""Frankfurt Hbf"" eva=""8000105"" ds100=""FF""/>
586+ </stations>" ;
587+
588+ var stationBXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
589+ <stations>
590+ <station name=""Konstanz"" eva=""8003400"" ds100=""KN""/>
591+ </stations>" ;
592+
593+ // Timetable with a train that doesn't go to Konstanz (only to Munich)
594+ var timetableXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
595+ <timetable station=""Frankfurt Hbf"">
596+ <s id=""123456"">
597+ <tl c=""ICE"" n=""123"" f=""Munich Hbf""/>
598+ <dp pt=""2511061430"" pp=""7"" ppth=""Frankfurt Hbf|Stuttgart|Munich Hbf""/>
599+ </s>
600+ </timetable>" ;
601+
602+ var changesXml = @"<?xml version=""1.0"" encoding=""UTF-8""?><timetable/>" ;
603+
604+ var mockHandler = new Mock < HttpMessageHandler > ( ) ;
605+ var requestCount = 0 ;
606+ mockHandler . Protected ( )
607+ . Setup < Task < HttpResponseMessage > > (
608+ "SendAsync" ,
609+ ItExpr . IsAny < HttpRequestMessage > ( ) ,
610+ ItExpr . IsAny < CancellationToken > ( ) )
611+ . ReturnsAsync ( ( ) =>
612+ {
613+ requestCount ++ ;
614+ // First station lookup (Frankfurt)
615+ if ( requestCount == 1 )
616+ return new HttpResponseMessage { StatusCode = HttpStatusCode . OK , Content = new StringContent ( stationXml ) } ;
617+ // Second station lookup (Konstanz)
618+ if ( requestCount == 2 )
619+ return new HttpResponseMessage { StatusCode = HttpStatusCode . OK , Content = new StringContent ( stationBXml ) } ;
620+ // Third is timetable
621+ if ( requestCount == 3 )
622+ return new HttpResponseMessage { StatusCode = HttpStatusCode . OK , Content = new StringContent ( timetableXml ) } ;
623+ // Fourth is full changes
624+ return new HttpResponseMessage { StatusCode = HttpStatusCode . OK , Content = new StringContent ( changesXml ) } ;
625+ } ) ;
626+
627+ var httpClient = new HttpClient ( mockHandler . Object ) { BaseAddress = new Uri ( _config . BaseUrl ) } ;
628+ var service = new TimeTableService ( httpClient , _mockOptions . Object ) ;
629+
630+ // Act
631+ var result = await service . FindTrainConnectionsAsync ( "Frankfurt" , "Konstanz" ) ;
632+
633+ // Assert
634+ Assert . Contains ( "Train Connection Analysis" , result ) ;
635+ Assert . Contains ( "⚠ No direct connections found in the current timetable." , result ) ;
636+ Assert . Contains ( "This could mean:" , result ) ;
637+ Assert . Contains ( "- No direct trains operate between these stations" , result ) ;
638+ Assert . Contains ( "- Trains may require a transfer" , result ) ;
639+ Assert . Contains ( "- Try a different time or date" , result ) ;
640+ }
530641}
0 commit comments