diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index df7b11fcc2..2291695a8e 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -55,6 +55,7 @@ 158A2D528CC78C4E7A8ED608 /* MockRoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */; }; 15D867E638BFD0E5E71DB1EF /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AFEF3AC64B1358083F76B8B /* List.swift */; }; 165A883C29998EC779465068 /* SoftLogoutViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC38904A9663F7FAFD47457 /* SoftLogoutViewModelProtocol.swift */; }; + 167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */; }; 1702981A8085BE4FB0EC001B /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33116993D54FADC0C721C1F /* Application.swift */; }; 172E6E9A612ADCF10A62CF13 /* BugReportServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */; }; 187E18F21EF4DA244E436E58 /* BugReportViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28959C7DB36C7688A01D4045 /* BugReportViewModelProtocol.swift */; }; @@ -152,6 +153,7 @@ 4A2E0DBB63919AC8309B6D40 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A191D3FDB995309C7E2DE7D /* SettingsViewModel.swift */; }; 4BB282209EA82015D0DF8F89 /* NavigationStackCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */; }; 4C3365818DE1CEAEDF590FD3 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */; }; + 4E8F17EBA24FBBA6ABB62ECB /* MockBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3948D16F021DFDB2CD26EAA8 /* MockBackgroundTaskService.swift */; }; 4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */; }; 4FC1EFE4968A259CBBACFAFB /* RoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A65F140F9FE5E8D4DAEFF354 /* RoomProxy.swift */; }; 4FF90E2242DBD596E1ED2E27 /* AppCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */; }; @@ -160,7 +162,6 @@ 50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; }; 518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; }; 51DB67C5B5BC68B0A6FF54D4 /* MockRoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACBDC1D28EFB7789EB467E0 /* MockRoomProxy.swift */; }; - 524C9C31EF8D58C2249F8A10 /* sample_screenshot.png in Resources */ = {isa = PBXBuildFile; fileRef = 9414DCADBDF9D6C4B806F61E /* sample_screenshot.png */; }; 5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; }; 53DEF39F0C4DE02E3FC56D91 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = AC5D19D7A65EB05A9704FB44 /* SwiftyBeaver */; }; 541374590CA7E8318BD480FD /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; }; @@ -257,6 +258,7 @@ 829062DD3C3F7016FE1A6476 /* RoomDetailsScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BFDAF6918BB096C44788FC9 /* RoomDetailsScreenUITests.swift */; }; 83E5054739949181CA981193 /* LoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD667C4BB98CF4F3FE2CE3B0 /* LoginCoordinator.swift */; }; 85AFBB433AD56704A880F8A0 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */; }; + 85DB5F55FC407DDB6A4F01C9 /* test_image.png in Resources */ = {isa = PBXBuildFile; fileRef = 0D15170391F27AF6718D4F2A /* test_image.png */; }; 86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */; }; 8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; }; 86C2E93920FD15AD17E193A9 /* BugReportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E532D95330139D118A9BF88 /* BugReportViewModel.swift */; }; @@ -400,6 +402,7 @@ CE7148E80F09B7305E026AC6 /* OnboardingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1198B925F4A88DA74083662 /* OnboardingViewModel.swift */; }; CE9530A4CA661E090635C2F2 /* NotificationItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */; }; CEB8FB1269DE20536608B957 /* LoginMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41FABA2B0AEF4389986495 /* LoginMode.swift */; }; + CF6319CC05F964B4D05BF614 /* MockFileCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEC96B3DC55090BBF8876CC2 /* MockFileCache.swift */; }; CF82143AA4A4F7BD11D22946 /* RoomTimelineViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACB6C5E4950B6C9842F35A38 /* RoomTimelineViewProvider.swift */; }; D034A195A3494E38BF060485 /* MockSessionVerificationControllerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A9CCCF53495CF3D7B19FCE /* MockSessionVerificationControllerProxy.swift */; }; D05A193AE63030F2CFCE2E9C /* UITestScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */; }; @@ -416,6 +419,7 @@ D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */; }; D8CFF02C2730EE5BC4F17ABF /* ElementToggleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0960A7F5C1B0B6679BDF26F9 /* ElementToggleStyle.swift */; }; DC2D20609B9B612F6946C3F6 /* RoomMembersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4CF2FC815D26B337E78DA45 /* RoomMembersViewModel.swift */; }; + DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */; }; DD9B70DE54B24E0694A35D8A /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; DDB80FD2753FEAAE43CC2AAE /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A63815AD6A5C306453342F2 /* ImageRoomTimelineItem.swift */; }; DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */; }; @@ -437,6 +441,7 @@ E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */; }; E8AB8D16E6D8E8E501F29BD9 /* FileCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B0B1226DA8DB55918B34CD /* FileCache.swift */; }; E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */; }; + E9631F628251F77A24AA4BB4 /* MockMediaProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CFF3E430B27B7C3AD0A28 /* MockMediaProxy.swift */; }; EA1E7949533E19C6D862680A /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885D8C42DD17625B5261BEFF /* MediaProvider.swift */; }; EA31DD9043B91ECB8E45A9A6 /* ScreenshotDetectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03C9D319676F3C0DC6B0203 /* ScreenshotDetectorTests.swift */; }; EA65360A0EC026DD83AC0CF5 /* AuthenticationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */; }; @@ -549,6 +554,7 @@ 0C13A92C1E9C79F055B8133D /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ar; path = ar.lproj/Localizable.stringsdict; sourceTree = ""; }; 0C88046D6A070D9827181C4D /* OnboardingUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingUITests.swift; sourceTree = ""; }; 0CB569EAA5017B5B23970655 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = ""; }; + 0D15170391F27AF6718D4F2A /* test_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = test_image.png; sourceTree = ""; }; 0D8F620C8B314840D8602E3F /* NSE.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = NSE.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 0DB634B42CFE667112369D57 /* VideoPlayerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerScreen.swift; sourceTree = ""; }; 0DD16CE9A66C9040B066AD60 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = vi; path = vi.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -646,6 +652,7 @@ 37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiItem.swift; sourceTree = ""; }; 38B7319C1D6508702B98A8F6 /* RoomDetailsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreen.swift; sourceTree = ""; }; 39001365B76B89983FDB7AD8 /* EmojiMartJSONLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiMartJSONLoader.swift; sourceTree = ""; }; + 3948D16F021DFDB2CD26EAA8 /* MockBackgroundTaskService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBackgroundTaskService.swift; sourceTree = ""; }; 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadableFrameModifier.swift; sourceTree = ""; }; 399427358A80BA2848E698A2 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; 39EBB6903EFD4236B8D11A42 /* fr-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "fr-CA"; path = "fr-CA.lproj/Localizable.stringsdict"; sourceTree = ""; }; @@ -728,6 +735,7 @@ 607974D08BD2AF83725D817A /* RoomMessageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageProtocol.swift; sourceTree = ""; }; 616197D81103330BF2ADD559 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/Localizable.strings; sourceTree = ""; }; 624244C398804ADC885239AA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; + 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderTests.swift; sourceTree = ""; }; 62BDF0FF4F59AF6EA858B70B /* FilePreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewViewModel.swift; sourceTree = ""; }; 6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = ""; }; 649759084B0C9FE1F8DF8D17 /* UserNotificationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationPresenter.swift; sourceTree = ""; }; @@ -796,7 +804,7 @@ 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineProvider.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; 8ED2D2F6A137A95EA50413BE /* UserNotificationControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationControllerProtocol.swift; sourceTree = ""; }; 8F7D42E66E939B709C1EC390 /* MockRoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomSummaryProvider.swift; sourceTree = ""; }; 8FC26871038FB0E4AAE22605 /* apple_emojis_data.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = apple_emojis_data.json; sourceTree = ""; }; @@ -810,7 +818,6 @@ 938BD1FCD9E6FF3FCFA7AB4C /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-CN"; path = "zh-CN.lproj/Localizable.stringsdict"; sourceTree = ""; }; 93B21E72926FACB13A186689 /* ml */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ml; path = ml.lproj/Localizable.stringsdict; sourceTree = ""; }; 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelTests.swift; sourceTree = ""; }; - 9414DCADBDF9D6C4B806F61E /* sample_screenshot.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = sample_screenshot.png; sourceTree = ""; }; 94BCC8A9C73C1F838122C645 /* TimelineItemPlainStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemPlainStylerView.swift; sourceTree = ""; }; 96561CC53F7C1E24D4C292E4 /* MockNotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNotificationManager.swift; sourceTree = ""; }; 96F37AB24AF5A006521D38D1 /* RoomMessageFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageFactoryProtocol.swift; sourceTree = ""; }; @@ -871,6 +878,7 @@ AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTaskServiceProtocol.swift; sourceTree = ""; }; AB785716B9212C093704E767 /* EmojiPickerHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerHeaderView.swift; sourceTree = ""; }; AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreen.swift; sourceTree = ""; }; + AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageCache.swift; sourceTree = ""; }; AC3F82523D6F48B926D6AF68 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = ""; }; ACA11F7F50A4A3887A18CA5A /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; ACB6C5E4950B6C9842F35A38 /* RoomTimelineViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewProvider.swift; sourceTree = ""; }; @@ -880,6 +888,7 @@ ADCB8A232D3A8FB3E16A7303 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; AE225C66978648AA4AF37B45 /* te */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = te; path = te.lproj/Localizable.strings; sourceTree = ""; }; AE5DDBEBBA17973ED4638823 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = ""; }; + AEC96B3DC55090BBF8876CC2 /* MockFileCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockFileCache.swift; sourceTree = ""; }; AF11DD57D9FACF2A757AB024 /* AnalyticsPromptUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptUITests.swift; sourceTree = ""; }; AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderTests.swift; sourceTree = ""; }; B08CBE1E670690ECF11C2C6A /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = eu; path = eu.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -986,6 +995,7 @@ E254EA67FB16AB33F9F9B18D /* RoomMembersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersScreen.swift; sourceTree = ""; }; E26747B3154A5DBC3A7E24A5 /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = ""; }; E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = ""; }; + E36CFF3E430B27B7C3AD0A28 /* MockMediaProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaProxy.swift; sourceTree = ""; }; E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsClientProtocol.swift; sourceTree = ""; }; E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsUITests.swift; sourceTree = ""; }; E45C57120F28F8D619150219 /* sr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sr; path = sr.lproj/Localizable.strings; sourceTree = ""; }; @@ -1008,7 +1018,7 @@ EBE5502760CF6CA2D7201883 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ja; path = ja.lproj/Localizable.stringsdict; sourceTree = ""; }; ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = ""; }; EDB6E40BAD4504D899FAAC9A /* TemplateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateViewModel.swift; sourceTree = ""; }; EE8BCD14EFED23459A43FDFF /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; @@ -1713,11 +1723,24 @@ EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */, 0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */, A3004DFA1B10951962787D90 /* VideoPlayerViewModelTests.swift */, + 7583EAC171059A86B767209F /* MediaProvider */, 7DBC911559934065993A5FF4 /* NotificationManager */, ); path = Sources; sourceTree = ""; }; + 7583EAC171059A86B767209F /* MediaProvider */ = { + isa = PBXGroup; + children = ( + 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */, + 3948D16F021DFDB2CD26EAA8 /* MockBackgroundTaskService.swift */, + AEC96B3DC55090BBF8876CC2 /* MockFileCache.swift */, + AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */, + E36CFF3E430B27B7C3AD0A28 /* MockMediaProxy.swift */, + ); + path = MediaProvider; + sourceTree = ""; + }; 75D1D02F7F3AC1122FCFB4F3 /* Items */ = { isa = PBXGroup; children = ( @@ -2320,7 +2343,7 @@ E600AACDF87CDBCE32683236 /* Resources */ = { isa = PBXGroup; children = ( - 9414DCADBDF9D6C4B806F61E /* sample_screenshot.png */, + 0D15170391F27AF6718D4F2A /* test_image.png */, ); path = Resources; sourceTree = ""; @@ -2731,8 +2754,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 524C9C31EF8D58C2249F8A10 /* sample_screenshot.png in Resources */, 35E975CFDA60E05362A7CF79 /* target.yml in Resources */, + 85DB5F55FC407DDB6A4F01C9 /* test_image.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2868,7 +2891,12 @@ 149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */, 1E59B77A0B2CE83DCC1B203C /* LoginViewModelTests.swift in Sources */, 2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */, + 167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */, + 4E8F17EBA24FBBA6ABB62ECB /* MockBackgroundTaskService.swift in Sources */, 1146E9EDCF8344F7D6E0D553 /* MockCoder.swift in Sources */, + CF6319CC05F964B4D05BF614 /* MockFileCache.swift in Sources */, + DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */, + E9631F628251F77A24AA4BB4 /* MockMediaProxy.swift in Sources */, 981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */, FCB9B475F908765531335859 /* NavigationSplitCoordinator.swift in Sources */, 4BB282209EA82015D0DF8F89 /* NavigationStackCoordinatorTests.swift in Sources */, diff --git a/ElementX/Sources/Services/Media/MediaProvider.swift b/ElementX/Sources/Services/Media/MediaProvider.swift index 7e69c60680..f5a0cd1487 100644 --- a/ElementX/Sources/Services/Media/MediaProvider.swift +++ b/ElementX/Sources/Services/Media/MediaProvider.swift @@ -20,12 +20,12 @@ import UIKit struct MediaProvider: MediaProviderProtocol { private let mediaProxy: MediaProxyProtocol private let imageCache: Kingfisher.ImageCache - private let fileCache: FileCache + private let fileCache: FileCacheProtocol private let backgroundTaskService: BackgroundTaskServiceProtocol? init(mediaProxy: MediaProxyProtocol, imageCache: Kingfisher.ImageCache, - fileCache: FileCache, + fileCache: FileCacheProtocol, backgroundTaskService: BackgroundTaskServiceProtocol?) { self.mediaProxy = mediaProxy self.imageCache = imageCache diff --git a/ElementX/Sources/Services/UserSession/UserSessionStore.swift b/ElementX/Sources/Services/UserSession/UserSessionStore.swift index 427498d1bb..ffef872dae 100644 --- a/ElementX/Sources/Services/UserSession/UserSessionStore.swift +++ b/ElementX/Sources/Services/UserSession/UserSessionStore.swift @@ -54,7 +54,7 @@ class UserSessionStore: UserSessionStoreProtocol { return .success(UserSession(clientProxy: clientProxy, mediaProvider: MediaProvider(mediaProxy: clientProxy, imageCache: .onlyInMemory, - fileCache: .default, + fileCache: FileCache.default, backgroundTaskService: backgroundTaskService))) case .failure(let error): MXLog.error("Failed restoring login with error: \(error)") @@ -73,7 +73,7 @@ class UserSessionStore: UserSessionStoreProtocol { return .success(UserSession(clientProxy: clientProxy, mediaProvider: MediaProvider(mediaProxy: clientProxy, imageCache: .onlyInMemory, - fileCache: .default, + fileCache: FileCache.default, backgroundTaskService: backgroundTaskService))) case .failure(let error): MXLog.error("Failed creating user session with error: \(error)") diff --git a/NSE/Sources/NotificationServiceExtension.swift b/NSE/Sources/NotificationServiceExtension.swift index 689e38f440..abaf0c6712 100644 --- a/NSE/Sources/NotificationServiceExtension.swift +++ b/NSE/Sources/NotificationServiceExtension.swift @@ -130,7 +130,7 @@ class NotificationServiceExtension: UNNotificationServiceExtension { return MediaProvider(mediaProxy: MediaProxy(client: client), imageCache: .onlyOnDisk, - fileCache: .default, + fileCache: FileCache.default, backgroundTaskService: nil) } diff --git a/UnitTests/Resources/sample_screenshot.png b/UnitTests/Resources/sample_screenshot.png deleted file mode 100644 index 30c02a83d7..0000000000 Binary files a/UnitTests/Resources/sample_screenshot.png and /dev/null differ diff --git a/UnitTests/Resources/test_image.png b/UnitTests/Resources/test_image.png new file mode 100644 index 0000000000..85d7a6a012 Binary files /dev/null and b/UnitTests/Resources/test_image.png differ diff --git a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift new file mode 100644 index 0000000000..fbe4c08a08 --- /dev/null +++ b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift @@ -0,0 +1,246 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import ElementX +import Kingfisher +import XCTest + +@MainActor +final class MediaProviderTests: XCTestCase { + private let mediaProxy = MockMediaProxy() + private let fileCache = MockFileCache() + private var imageCache: MockImageCache! + private var backgroundTaskService = MockBackgroundTaskService() + + var mediaProvider: MediaProvider! + + override func setUp() { + imageCache = MockImageCache(name: "Test") + mediaProvider = MediaProvider(mediaProxy: mediaProxy, + imageCache: imageCache, + fileCache: fileCache, + backgroundTaskService: backgroundTaskService) + } + + func test_whenImageFromSourceWithSourceNil_nilReturned() throws { + let image = mediaProvider.imageFromSource(nil, avatarSize: .room(on: .timeline)) + XCTAssertNil(image) + } + + func test_whenImageFromSourceWithSourceNotNilAndImageCacheContainsImage_ImageIsReturned() throws { + let avatarSize = AvatarSize.room(on: .timeline) + let urlString = "test" + let key = "\(urlString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" + let imageForKey = UIImage() + imageCache.retrievedImagesInMemory[key] = imageForKey + let image = mediaProvider.imageFromSource(MediaSourceProxy(urlString: urlString), avatarSize: avatarSize) + XCTAssertEqual(image, imageForKey) + } + + func test_whenImageFromSourceWithSourceNotNilAndImageNotCached_nilReturned() throws { + let image = mediaProvider.imageFromSource(MediaSourceProxy(urlString: "test"), avatarSize: .room(on: .timeline)) + XCTAssertNil(image) + } + + func test_whenImageFromURLStringWithURLStringNil_nilReturned() throws { + let image = mediaProvider.imageFromURLString(nil, avatarSize: .room(on: .timeline)) + XCTAssertNil(image) + } + + func test_whenImageFromURLStringWithURLStringNotNilAndImageCacheContainsImage_imageIsReturned() throws { + let avatarSize = AvatarSize.room(on: .timeline) + let urlString = "test" + let key = "\(urlString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" + let imageForKey = UIImage() + imageCache.retrievedImagesInMemory[key] = imageForKey + let image = mediaProvider.imageFromURLString("test", avatarSize: avatarSize) + XCTAssertEqual(image, imageForKey) + } + + func test_whenImageFromURLStringWithURLStringNotNilAndImageNotCached_nilReturned() throws { + let image = mediaProvider.imageFromURLString("test", avatarSize: .room(on: .timeline)) + XCTAssertNil(image) + } + + func test_whenLoadImageFromSourceAndImageCacheContainsImage_successIsReturned() async throws { + let avatarSize = AvatarSize.room(on: .timeline) + let urlString = "test" + let key = "\(urlString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" + let imageForKey = UIImage() + imageCache.retrievedImagesInMemory[key] = imageForKey + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(urlString: urlString), avatarSize: avatarSize) + XCTAssertEqual(Result.success(imageForKey), result) + } + + func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageSucceeds_successIsReturned() async throws { + let avatarSize = AvatarSize.room(on: .timeline) + let urlString = "test" + let key = "\(urlString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" + let imageForKey = UIImage() + imageCache.retrievedImages[key] = imageForKey + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(urlString: urlString), avatarSize: avatarSize) + XCTAssertEqual(Result.success(imageForKey), result) + } + + func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageThumbnailIsLoaded() async throws { + let avatarSize = AvatarSize.room(on: .timeline) + let expectedImage = try loadTestImage() + mediaProxy.mediaThumbnailData = expectedImage.pngData() + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(urlString: "test"), avatarSize: avatarSize) + switch result { + case .success(let image): + XCTAssertEqual(image.pngData(), expectedImage.pngData()) + case .failure: + XCTFail("Should be success") + } + } + + func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageIsStored() async throws { + let avatarSize = AvatarSize.room(on: .timeline) + let urlString = "test" + let key = "\(urlString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" + let expectedImage = try loadTestImage() + mediaProxy.mediaThumbnailData = expectedImage.pngData() + _ = await mediaProvider.loadImageFromSource(MediaSourceProxy(urlString: urlString), avatarSize: avatarSize) + let storedImage = try XCTUnwrap(imageCache.storedImages[key]) + XCTAssertEqual(expectedImage.pngData(), storedImage.pngData()) + } + + func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSize_imageContentIsLoaded() async throws { + let expectedImage = try loadTestImage() + mediaProxy.mediaContentData = expectedImage.pngData() + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(urlString: "test"), avatarSize: nil) + switch result { + case .success(let image): + XCTAssertEqual(image.pngData(), expectedImage.pngData()) + case .failure: + XCTFail("Should be success") + } + } + + func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndLoadImageThumbnailFails_errorIsThrown() async throws { + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(urlString: "test"), avatarSize: AvatarSize.room(on: .timeline)) + switch result { + case .success: + XCTFail("Should fail") + case .failure(let error): + XCTAssertEqual(error, MediaProviderError.failedRetrievingImage) + } + } + + func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSizeAndLoadImageContentFails_errorIsThrown() async throws { + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(urlString: "test"), avatarSize: nil) + switch result { + case .success: + XCTFail("Should fail") + case .failure(let error): + XCTAssertEqual(error, MediaProviderError.failedRetrievingImage) + } + } + + func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndImageThumbnailIsLoadedWithCorruptedData_errorIsThrown() async throws { + mediaProxy.mediaThumbnailData = Data() + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(urlString: "test"), avatarSize: AvatarSize.room(on: .timeline)) + switch result { + case .success: + XCTFail("Should fail") + case .failure(let error): + XCTAssertEqual(error, MediaProviderError.invalidImageData) + } + } + + func test_whenFileFromSourceWithSourceNil_nilIsReturned() throws { + let url = mediaProvider.fileFromSource(nil, fileExtension: "png") + XCTAssertNil(url) + } + + func test_whenFileFromSourceWithSource_correctValuesAreReturned() throws { + let expectedURL = try XCTUnwrap(URL(string: "some_url")) + fileCache.fileURLToReturn = expectedURL + let url = mediaProvider.fileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png") + XCTAssertEqual(fileCache.fileKey, "test1") + XCTAssertEqual(fileCache.fileExtension, "png") + XCTAssertEqual(url?.absoluteString, expectedURL.absoluteString) + } + + func test_whenLoadFileFromSourceAndFileFromSourceExists_urlIsReturned() async throws { + let expectedURL = try XCTUnwrap(URL(string: "some_url")) + let expectedResult: Result = .success(expectedURL) + fileCache.fileURLToReturn = expectedURL + let result = await mediaProvider.loadFileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png") + XCTAssertEqual(result, expectedResult) + } + + func test_whenLoadFileFromSourceAndNoFileFromSourceExists_mediaLoadedFromSource() async throws { + let expectedURL = try XCTUnwrap(URL(string: "some_url")) + let expectedResult: Result = .success(expectedURL) + mediaProxy.mediaContentData = try loadTestImage().pngData() + fileCache.storeURLToReturn = expectedURL + let result = await mediaProvider.loadFileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png") + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(mediaProxy.mediaContentData, fileCache.storedData) + XCTAssertEqual("test1", fileCache.storedFileKey) + XCTAssertEqual("png", fileCache.storedFileExtension) + } + + func test_whenLoadFileFromSourceAndNoFileFromSourceExistsAndLoadContentSourceFails_failureIsReturned() async throws { + let expectedResult: Result = .failure(.failedRetrievingImage) + mediaProxy.mediaContentData = nil + let result = await mediaProvider.loadFileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png") + XCTAssertEqual(result, expectedResult) + } + + func test_whenLoadFileFromSourceAndNoFileFromSourceExistsAndStoreDataFails_failureIsReturned() async throws { + let expectedResult: Result = .failure(.failedRetrievingImage) + mediaProxy.mediaContentData = try loadTestImage().pngData() + let result = await mediaProvider.loadFileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png") + XCTAssertEqual(result, expectedResult) + } + + func test_whenFileFromURLStringAndURLIsNil_nilIsReturned() async throws { + mediaProxy.mediaContentData = try loadTestImage().pngData() + let url = mediaProvider.fileFromURLString(nil, fileExtension: "png") + XCTAssertNil(url) + } + + func test_whenFileFromURLString_correctURLIsReturned() throws { + let expectedURL = try XCTUnwrap(URL(string: "some_url")) + fileCache.fileURLToReturn = expectedURL + let url = mediaProvider.fileFromURLString("test/test1", fileExtension: "png") + XCTAssertEqual(url?.absoluteString, expectedURL.absoluteString) + } + + func test_whenLoadFileFromURLString_correctURLIsReturned() async throws { + let expectedURL = try XCTUnwrap(URL(string: "some_url")) + let expectedResult: Result = .success(expectedURL) + fileCache.fileURLToReturn = expectedURL + let result = await mediaProvider.loadFileFromURLString("test/test1", fileExtension: "png") + XCTAssertEqual(result, expectedResult) + } + + private func loadTestImage() throws -> UIImage { + let bundle = Bundle(for: classForCoder) + guard let path = bundle.path(forResource: "test_image", ofType: "png"), + let image = UIImage(contentsOfFile: path) else { + throw MediaProviderTestsError.screenshotNotFound + } + return image + } +} + +enum MediaProviderTestsError: Error { + case screenshotNotFound +} diff --git a/UnitTests/Sources/MediaProvider/MockBackgroundTaskService.swift b/UnitTests/Sources/MediaProvider/MockBackgroundTaskService.swift new file mode 100644 index 0000000000..1a45f9d630 --- /dev/null +++ b/UnitTests/Sources/MediaProvider/MockBackgroundTaskService.swift @@ -0,0 +1,23 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +@testable import ElementX +import Foundation + +class MockBackgroundTaskService: BackgroundTaskServiceProtocol { + func startBackgroundTask(withName name: String, isReusable: Bool, expirationHandler: (() -> Void)?) -> ElementX.BackgroundTaskProtocol? { + nil + } +} diff --git a/UnitTests/Sources/MediaProvider/MockFileCache.swift b/UnitTests/Sources/MediaProvider/MockFileCache.swift new file mode 100644 index 0000000000..2943dc59f8 --- /dev/null +++ b/UnitTests/Sources/MediaProvider/MockFileCache.swift @@ -0,0 +1,52 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +@testable import ElementX +import Foundation + +enum MockFileCacheError: Error { + case someError +} + +class MockFileCache: FileCacheProtocol { + var fileKey: String? + var fileExtension: String? + var fileURLToReturn: URL? + var storedData: Data? + var storedFileExtension: String? + var storedFileKey: String? + var storeURLToReturn: URL? + + func file(forKey key: String, fileExtension: String) -> URL? { + fileKey = key + self.fileExtension = fileExtension + return fileURLToReturn + } + + func store(_ data: Data, with fileExtension: String, forKey key: String) throws -> URL { + storedData = data + storedFileExtension = fileExtension + storedFileKey = key + if let storeURLToReturn { + return storeURLToReturn + } else { + throw MockFileCacheError.someError + } + } + + func remove(forKey key: String, fileExtension: String) throws { } + + func removeAll() throws { } +} diff --git a/UnitTests/Sources/MediaProvider/MockImageCache.swift b/UnitTests/Sources/MediaProvider/MockImageCache.swift new file mode 100644 index 0000000000..0fd9968d9b --- /dev/null +++ b/UnitTests/Sources/MediaProvider/MockImageCache.swift @@ -0,0 +1,48 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +@testable import ElementX +import Kingfisher +import UIKit + +class MockImageCache: ImageCache { + var retrievedImagesInMemory = [String: UIImage]() + var retrievedImages = [String: UIImage]() + var storedImages = [String: UIImage]() + + override func retrieveImageInMemoryCache(forKey key: String, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? { + retrievedImagesInMemory[key] + } + + override func retrieveImage(forKey key: String, options: KingfisherOptionsInfo? = nil, callbackQueue: CallbackQueue = .mainCurrentOrAsync, completionHandler: ((Result) -> Void)?) { + if let image = retrievedImages[key] { + completionHandler?(.success(ImageCacheResult.disk(image))) + } else { + let error = KingfisherError.cacheError(reason: .imageNotExisting(key: key)) + completionHandler?(.failure(error)) + } + } + + override func store(_ image: KFCrossPlatformImage, + original: Data? = nil, + forKey key: String, + processorIdentifier identifier: String = "", + cacheSerializer serializer: CacheSerializer = DefaultCacheSerializer.default, + toDisk: Bool = true, + callbackQueue: CallbackQueue = .untouch, + completionHandler: ((CacheStoreResult) -> Void)? = nil) { + storedImages[key] = image + } +} diff --git a/UnitTests/Sources/MediaProvider/MockMediaProxy.swift b/UnitTests/Sources/MediaProvider/MockMediaProxy.swift new file mode 100644 index 0000000000..89ab1bb406 --- /dev/null +++ b/UnitTests/Sources/MediaProvider/MockMediaProxy.swift @@ -0,0 +1,46 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +@testable import ElementX +import Foundation + +enum MockMediaProxyError: Error { + case someError +} + +class MockMediaProxy: MediaProxyProtocol { + var mediaContentData: Data? + var mediaThumbnailData: Data? + + func mediaSourceForURLString(_ urlString: String) -> MediaSourceProxy { + MediaSourceProxy(urlString: "test") + } + + func loadMediaContentForSource(_ source: ElementX.MediaSourceProxy) async throws -> Data { + if let mediaContentData { + return mediaContentData + } else { + throw MockMediaProxyError.someError + } + } + + func loadMediaThumbnailForSource(_ source: ElementX.MediaSourceProxy, width: UInt, height: UInt) async throws -> Data { + if let mediaThumbnailData { + return mediaThumbnailData + } else { + throw MockMediaProxyError.someError + } + } +} diff --git a/changelog.d/pr-386.change b/changelog.d/pr-386.change new file mode 100644 index 0000000000..76fb276b71 --- /dev/null +++ b/changelog.d/pr-386.change @@ -0,0 +1 @@ +Add MediaProvider tests. \ No newline at end of file