@@ -972,6 +972,291 @@ public async Task GetMessageWaveformData_ResponseFormatIsCorrect_VerifiesSystemR
972972
973973 #endregion
974974
975+ #region GetAllSermons Caching Tests
976+
977+ [ TestMethod ]
978+ public async Task GetAllSermons_CacheMiss_FetchesFromRepositoryAndCachesResult ( )
979+ {
980+ // Arrange
981+ var series1 = CreateTestSermonSeries ( "1" , "Series 1" , "series-1" ) ;
982+ var series2 = CreateTestSermonSeries ( "2" , "Series 2" , "series-2" ) ;
983+ var seriesList = new List < SermonSeries > { series1 , series2 } ;
984+
985+ var message1 = CreateTestSermonMessage ( "msg1" , "1" , "Message 1" ) ;
986+ var message2 = CreateTestSermonMessage ( "msg2" , "2" , "Message 2" ) ;
987+ var messagesList = new List < SermonMessage > { message1 , message2 } ;
988+
989+ _mockSermonsRepository . Setup ( r => r . GetAllSermons ( It . IsAny < bool > ( ) ) )
990+ . ReturnsAsync ( seriesList ) ;
991+
992+ _mockMessagesRepository . Setup ( r => r . GetAllMessages ( ) )
993+ . ReturnsAsync ( messagesList ) ;
994+
995+ // Setup cache miss
996+ object cacheValue = null ;
997+ _mockCache . Setup ( c => c . TryGetValue ( It . IsAny < object > ( ) , out cacheValue ) )
998+ . Returns ( false ) ;
999+
1000+ // Setup cache entry for Set
1001+ var cacheEntry = new Mock < ICacheEntry > ( ) ;
1002+ _mockCache . Setup ( c => c . CreateEntry ( It . IsAny < object > ( ) ) )
1003+ . Returns ( cacheEntry . Object ) ;
1004+
1005+ // Act
1006+ var result = await _sermonsService . GetAllSermons ( highResImg : false ) ;
1007+
1008+ // Assert
1009+ Assert . IsNotNull ( result ) ;
1010+ Assert . IsFalse ( result . HasErrors ) ;
1011+ Assert . IsNotNull ( result . Result ) ;
1012+ Assert . AreEqual ( 2 , result . Result . Summaries . Count ( ) ) ;
1013+
1014+ // Verify repository was called (cache miss)
1015+ _mockSermonsRepository . Verify ( r => r . GetAllSermons ( It . IsAny < bool > ( ) ) , Times . Once ) ;
1016+ _mockMessagesRepository . Verify ( r => r . GetAllMessages ( ) , Times . Once ) ;
1017+
1018+ // Verify cache Set was called
1019+ _mockCache . Verify ( c => c . CreateEntry ( It . Is < object > ( key =>
1020+ key . ToString ( ) . Contains ( "AllSermonsSummaryCache" ) ) ) , Times . Once ) ;
1021+ }
1022+
1023+ [ TestMethod ]
1024+ public async Task GetAllSermons_CacheHit_ReturnsCachedResultWithoutCallingRepository ( )
1025+ {
1026+ // Arrange
1027+ var cachedSummaries = new List < AllSermonSeriesSummary >
1028+ {
1029+ new AllSermonSeriesSummary { Id = "1" , Title = "Cached Series 1" , MessageCount = 5 } ,
1030+ new AllSermonSeriesSummary { Id = "2" , Title = "Cached Series 2" , MessageCount = 3 }
1031+ } ;
1032+ var cachedResponse = new SystemResponse < AllSermonsSummaryResponse > (
1033+ new AllSermonsSummaryResponse { Summaries = cachedSummaries } ,
1034+ "Success!" ) ;
1035+
1036+ // Setup cache hit
1037+ object cacheValue = cachedResponse ;
1038+ _mockCache . Setup ( c => c . TryGetValue ( It . IsAny < object > ( ) , out cacheValue ) )
1039+ . Returns ( true ) ;
1040+
1041+ // Act
1042+ var result = await _sermonsService . GetAllSermons ( highResImg : false ) ;
1043+
1044+ // Assert
1045+ Assert . IsNotNull ( result ) ;
1046+ Assert . IsFalse ( result . HasErrors ) ;
1047+ Assert . AreEqual ( 2 , result . Result . Summaries . Count ( ) ) ;
1048+ Assert . AreEqual ( "Cached Series 1" , result . Result . Summaries . First ( ) . Title ) ;
1049+
1050+ // Verify repository was NOT called (cache hit)
1051+ _mockSermonsRepository . Verify ( r => r . GetAllSermons ( It . IsAny < bool > ( ) ) , Times . Never ) ;
1052+ _mockMessagesRepository . Verify ( r => r . GetAllMessages ( ) , Times . Never ) ;
1053+ }
1054+
1055+ [ TestMethod ]
1056+ public async Task GetAllSermons_HighResImgTrue_UsesDifferentCacheKey ( )
1057+ {
1058+ // Arrange
1059+ var series = CreateTestSermonSeries ( "1" , "Series 1" , "series-1" ) ;
1060+ var seriesList = new List < SermonSeries > { series } ;
1061+ var messagesList = new List < SermonMessage > ( ) ;
1062+
1063+ _mockSermonsRepository . Setup ( r => r . GetAllSermons ( It . IsAny < bool > ( ) ) )
1064+ . ReturnsAsync ( seriesList ) ;
1065+
1066+ _mockMessagesRepository . Setup ( r => r . GetAllMessages ( ) )
1067+ . ReturnsAsync ( messagesList ) ;
1068+
1069+ // Setup cache miss
1070+ object cacheValue = null ;
1071+ _mockCache . Setup ( c => c . TryGetValue ( It . IsAny < object > ( ) , out cacheValue ) )
1072+ . Returns ( false ) ;
1073+
1074+ // Setup cache entry for Set
1075+ var cacheEntry = new Mock < ICacheEntry > ( ) ;
1076+ _mockCache . Setup ( c => c . CreateEntry ( It . IsAny < object > ( ) ) )
1077+ . Returns ( cacheEntry . Object ) ;
1078+
1079+ // Act
1080+ var result = await _sermonsService . GetAllSermons ( highResImg : true ) ;
1081+
1082+ // Assert
1083+ Assert . IsNotNull ( result ) ;
1084+ Assert . IsFalse ( result . HasErrors ) ;
1085+
1086+ // Verify cache key contains "True" for highResImg
1087+ _mockCache . Verify ( c => c . CreateEntry ( It . Is < object > ( key =>
1088+ key . ToString ( ) . Contains ( "True" ) ) ) , Times . Once ) ;
1089+ }
1090+
1091+ [ TestMethod ]
1092+ public async Task GetAllSermons_HighResImgFalse_UsesThumbnailUrl ( )
1093+ {
1094+ // Arrange
1095+ var series = new SermonSeries
1096+ {
1097+ Id = "1" ,
1098+ Name = "Test Series" ,
1099+ Slug = "test-series" ,
1100+ StartDate = DateTime . UtcNow ,
1101+ ArtUrl = "https://example.com/high-res-art.jpg" ,
1102+ Thumbnail = "https://example.com/thumbnail.jpg"
1103+ } ;
1104+ var seriesList = new List < SermonSeries > { series } ;
1105+ var messagesList = new List < SermonMessage > ( ) ;
1106+
1107+ _mockSermonsRepository . Setup ( r => r . GetAllSermons ( It . IsAny < bool > ( ) ) )
1108+ . ReturnsAsync ( seriesList ) ;
1109+
1110+ _mockMessagesRepository . Setup ( r => r . GetAllMessages ( ) )
1111+ . ReturnsAsync ( messagesList ) ;
1112+
1113+ // Setup cache miss
1114+ object cacheValue = null ;
1115+ _mockCache . Setup ( c => c . TryGetValue ( It . IsAny < object > ( ) , out cacheValue ) )
1116+ . Returns ( false ) ;
1117+
1118+ // Setup cache entry
1119+ var cacheEntry = new Mock < ICacheEntry > ( ) ;
1120+ _mockCache . Setup ( c => c . CreateEntry ( It . IsAny < object > ( ) ) )
1121+ . Returns ( cacheEntry . Object ) ;
1122+
1123+ // Act
1124+ var result = await _sermonsService . GetAllSermons ( highResImg : false ) ;
1125+
1126+ // Assert
1127+ Assert . IsNotNull ( result ) ;
1128+ Assert . IsFalse ( result . HasErrors ) ;
1129+ var summary = result . Result . Summaries . First ( ) ;
1130+ Assert . AreEqual ( "https://example.com/thumbnail.jpg" , summary . ArtUrl ) ;
1131+ }
1132+
1133+ [ TestMethod ]
1134+ public async Task GetAllSermons_HighResImgTrue_UsesArtUrl ( )
1135+ {
1136+ // Arrange
1137+ var series = new SermonSeries
1138+ {
1139+ Id = "1" ,
1140+ Name = "Test Series" ,
1141+ Slug = "test-series" ,
1142+ StartDate = DateTime . UtcNow ,
1143+ ArtUrl = "https://example.com/high-res-art.jpg" ,
1144+ Thumbnail = "https://example.com/thumbnail.jpg"
1145+ } ;
1146+ var seriesList = new List < SermonSeries > { series } ;
1147+ var messagesList = new List < SermonMessage > ( ) ;
1148+
1149+ _mockSermonsRepository . Setup ( r => r . GetAllSermons ( It . IsAny < bool > ( ) ) )
1150+ . ReturnsAsync ( seriesList ) ;
1151+
1152+ _mockMessagesRepository . Setup ( r => r . GetAllMessages ( ) )
1153+ . ReturnsAsync ( messagesList ) ;
1154+
1155+ // Setup cache miss
1156+ object cacheValue = null ;
1157+ _mockCache . Setup ( c => c . TryGetValue ( It . IsAny < object > ( ) , out cacheValue ) )
1158+ . Returns ( false ) ;
1159+
1160+ // Setup cache entry
1161+ var cacheEntry = new Mock < ICacheEntry > ( ) ;
1162+ _mockCache . Setup ( c => c . CreateEntry ( It . IsAny < object > ( ) ) )
1163+ . Returns ( cacheEntry . Object ) ;
1164+
1165+ // Act
1166+ var result = await _sermonsService . GetAllSermons ( highResImg : true ) ;
1167+
1168+ // Assert
1169+ Assert . IsNotNull ( result ) ;
1170+ Assert . IsFalse ( result . HasErrors ) ;
1171+ var summary = result . Result . Summaries . First ( ) ;
1172+ Assert . AreEqual ( "https://example.com/high-res-art.jpg" , summary . ArtUrl ) ;
1173+ }
1174+
1175+ [ TestMethod ]
1176+ public async Task GetAllSermons_CalculatesMessageCountCorrectly ( )
1177+ {
1178+ // Arrange
1179+ var series1 = CreateTestSermonSeries ( "1" , "Series 1" , "series-1" ) ;
1180+ var series2 = CreateTestSermonSeries ( "2" , "Series 2" , "series-2" ) ;
1181+ var seriesList = new List < SermonSeries > { series1 , series2 } ;
1182+
1183+ // 3 messages for series 1, 2 messages for series 2
1184+ var messages = new List < SermonMessage >
1185+ {
1186+ CreateTestSermonMessage ( "msg1" , "1" , "Message 1" ) ,
1187+ CreateTestSermonMessage ( "msg2" , "1" , "Message 2" ) ,
1188+ CreateTestSermonMessage ( "msg3" , "1" , "Message 3" ) ,
1189+ CreateTestSermonMessage ( "msg4" , "2" , "Message 4" ) ,
1190+ CreateTestSermonMessage ( "msg5" , "2" , "Message 5" )
1191+ } ;
1192+
1193+ _mockSermonsRepository . Setup ( r => r . GetAllSermons ( It . IsAny < bool > ( ) ) )
1194+ . ReturnsAsync ( seriesList ) ;
1195+
1196+ _mockMessagesRepository . Setup ( r => r . GetAllMessages ( ) )
1197+ . ReturnsAsync ( messages ) ;
1198+
1199+ // Setup cache miss
1200+ object cacheValue = null ;
1201+ _mockCache . Setup ( c => c . TryGetValue ( It . IsAny < object > ( ) , out cacheValue ) )
1202+ . Returns ( false ) ;
1203+
1204+ // Setup cache entry
1205+ var cacheEntry = new Mock < ICacheEntry > ( ) ;
1206+ _mockCache . Setup ( c => c . CreateEntry ( It . IsAny < object > ( ) ) )
1207+ . Returns ( cacheEntry . Object ) ;
1208+
1209+ // Act
1210+ var result = await _sermonsService . GetAllSermons ( highResImg : false ) ;
1211+
1212+ // Assert
1213+ Assert . IsNotNull ( result ) ;
1214+ Assert . IsFalse ( result . HasErrors ) ;
1215+ var summaries = result . Result . Summaries . ToList ( ) ;
1216+ Assert . AreEqual ( 2 , summaries . Count ) ;
1217+
1218+ var series1Summary = summaries . First ( s => s . Id == "1" ) ;
1219+ var series2Summary = summaries . First ( s => s . Id == "2" ) ;
1220+ Assert . AreEqual ( 3 , series1Summary . MessageCount ) ;
1221+ Assert . AreEqual ( 2 , series2Summary . MessageCount ) ;
1222+ }
1223+
1224+ [ TestMethod ]
1225+ public async Task GetAllSermons_SeriesWithNoMessages_ReturnsZeroMessageCount ( )
1226+ {
1227+ // Arrange
1228+ var series = CreateTestSermonSeries ( "1" , "Empty Series" , "empty-series" ) ;
1229+ var seriesList = new List < SermonSeries > { series } ;
1230+ var emptyMessages = new List < SermonMessage > ( ) ;
1231+
1232+ _mockSermonsRepository . Setup ( r => r . GetAllSermons ( It . IsAny < bool > ( ) ) )
1233+ . ReturnsAsync ( seriesList ) ;
1234+
1235+ _mockMessagesRepository . Setup ( r => r . GetAllMessages ( ) )
1236+ . ReturnsAsync ( emptyMessages ) ;
1237+
1238+ // Setup cache miss
1239+ object cacheValue = null ;
1240+ _mockCache . Setup ( c => c . TryGetValue ( It . IsAny < object > ( ) , out cacheValue ) )
1241+ . Returns ( false ) ;
1242+
1243+ // Setup cache entry
1244+ var cacheEntry = new Mock < ICacheEntry > ( ) ;
1245+ _mockCache . Setup ( c => c . CreateEntry ( It . IsAny < object > ( ) ) )
1246+ . Returns ( cacheEntry . Object ) ;
1247+
1248+ // Act
1249+ var result = await _sermonsService . GetAllSermons ( highResImg : false ) ;
1250+
1251+ // Assert
1252+ Assert . IsNotNull ( result ) ;
1253+ Assert . IsFalse ( result . HasErrors ) ;
1254+ var summary = result . Result . Summaries . First ( ) ;
1255+ Assert . AreEqual ( 0 , summary . MessageCount ) ;
1256+ }
1257+
1258+ #endregion
1259+
9751260 #region Helper Methods
9761261
9771262 private SermonSeries CreateTestSermonSeries ( string id , string name , string slug )
0 commit comments