Update the SDK. (#3565)

* Update the SDK.

* Add mockMXC URLs to fix all the crashes during tests.

* Refactor Voice Messages to not use a MediaSource for local files.
This commit is contained in:
Doug
2024-11-28 08:34:38 +00:00
committed by GitHub
parent e70a95cfa2
commit 751be7b3a7
75 changed files with 222 additions and 590 deletions
@@ -91,7 +91,7 @@ class ComposerToolbarViewModelTests: XCTestCase {
func testSuggestions() {
let suggestions: [SuggestionItem] = [.user(item: MentionSuggestionItem(id: "@user_mention_1:matrix.org", displayName: "User 1", avatarURL: nil, range: .init())),
.user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: URL.documentsDirectory, range: .init()))]
.user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCAvatar, range: .init()))]
let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions))
viewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService,
@@ -15,50 +15,13 @@ class MediaPlayerProviderTests: XCTestCase {
private var mediaPlayerProvider: MediaPlayerProvider!
private let oggMimeType = "audio/ogg"
private let someURL = URL("/some/url")
private let someOtherURL = URL("/some/other/url")
private let someURL = URL.mockMXCAudio
private let someOtherURL = URL.mockMXCFile
override func setUp() async throws {
mediaPlayerProvider = MediaPlayerProvider()
}
func testPlayerForWrongMediaType() async throws {
let mediaSourceWithoutMimeType = MediaSourceProxy(url: someURL, mimeType: nil)
switch mediaPlayerProvider.player(for: mediaSourceWithoutMimeType) {
case .failure(.unsupportedMediaType):
// Ok
break
default:
XCTFail("An error is expected")
}
let mediaSourceVideo = MediaSourceProxy(url: someURL, mimeType: "video/mp4")
switch mediaPlayerProvider.player(for: mediaSourceVideo) {
case .failure(.unsupportedMediaType):
// Ok
break
default:
XCTFail("An error is expected")
}
}
func testPlayerFor() async throws {
let mediaSource = MediaSourceProxy(url: someURL, mimeType: oggMimeType)
guard case .success(let playerA) = mediaPlayerProvider.player(for: mediaSource) else {
XCTFail("A valid player is expected")
return
}
// calling it again with another mediasource must returns the same player
let otherMediaSource = MediaSourceProxy(url: someOtherURL, mimeType: oggMimeType)
guard case .success(let playerB) = mediaPlayerProvider.player(for: otherMediaSource) else {
XCTFail("A valid player is expected")
return
}
XCTAssert(playerA === playerB)
}
func testPlayerStates() async throws {
let audioPlayerStateId = AudioPlayerStateIdentifier.timelineItemIdentifier(.randomEvent)
// By default, there should be no player state
@@ -15,7 +15,7 @@ final class MediaLoaderTests: XCTestCase {
mediaLoadingClient.getMediaContentMediaSourceReturnValue = Data()
let mediaLoader = MediaLoader(client: mediaLoadingClient)
let mediaSource = MediaSourceProxy(url: URL.documentsDirectory, mimeType: nil)
let mediaSource = MediaSourceProxy(url: .mockMXCFile, mimeType: nil)
do {
for _ in 1...10 {
@@ -33,7 +33,7 @@ final class MediaLoaderTests: XCTestCase {
mediaLoadingClient.getMediaThumbnailMediaSourceWidthHeightReturnValue = Data()
let mediaLoader = MediaLoader(client: mediaLoadingClient)
let mediaSource = MediaSourceProxy(url: URL.documentsDirectory, mimeType: nil)
let mediaSource = MediaSourceProxy(url: .mockMXCImage, mimeType: nil)
do {
for _ in 1...10 {
@@ -36,7 +36,7 @@ final class MediaProviderTests: XCTestCase {
return
}
let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"))
let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"))
let connectivitySubject = CurrentValueSubject<NetworkMonitorReachability, Never>(.unreachable)
@@ -59,7 +59,7 @@ final class MediaProviderTests: XCTestCase {
}
func testLoadingRetriedOnReconnectionCancelsAfterSecondFailure() async throws {
let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"))
let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"))
let connectivitySubject = CurrentValueSubject<NetworkMonitorReachability, Never>(.reachable)
@@ -79,7 +79,7 @@ final class MediaProviderTests: XCTestCase {
func test_whenImageFromSourceWithSourceNotNilAndImageCacheContainsImage_ImageIsReturned() throws {
let avatarSize = Avatars.Size.room(on: .timeline)
let url = URL.picturesDirectory
let url = URL.mockMXCImage
let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}"
let imageForKey = UIImage()
imageCache.retrievedImagesInMemory[key] = imageForKey
@@ -89,14 +89,14 @@ final class MediaProviderTests: XCTestCase {
}
func test_whenImageFromSourceWithSourceNotNilAndImageNotCached_nilReturned() throws {
let image = mediaProvider.imageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"),
let image = mediaProvider.imageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
size: Avatars.Size.room(on: .timeline).scaledSize)
XCTAssertNil(image)
}
func test_whenLoadImageFromSourceAndImageCacheContainsImage_successIsReturned() async throws {
let avatarSize = Avatars.Size.room(on: .timeline)
let url = URL.picturesDirectory
let url = URL.mockMXCImage
let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}"
let imageForKey = UIImage()
imageCache.retrievedImagesInMemory[key] = imageForKey
@@ -107,7 +107,7 @@ final class MediaProviderTests: XCTestCase {
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageSucceeds_successIsReturned() async throws {
let avatarSize = Avatars.Size.room(on: .timeline)
let url = URL.picturesDirectory
let url = URL.mockMXCImage
let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}"
let imageForKey = UIImage()
imageCache.retrievedImages[key] = imageForKey
@@ -122,7 +122,7 @@ final class MediaProviderTests: XCTestCase {
mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData()
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"),
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
size: avatarSize.scaledSize)
switch result {
case .success(let image):
@@ -134,7 +134,7 @@ final class MediaProviderTests: XCTestCase {
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageIsStored() async throws {
let avatarSize = Avatars.Size.room(on: .timeline)
let url = URL.picturesDirectory
let url = URL.mockMXCImage
let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}"
let expectedImage = try loadTestImage()
@@ -151,7 +151,7 @@ final class MediaProviderTests: XCTestCase {
mediaLoader.loadMediaContentForSourceReturnValue = expectedImage.pngData()
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"),
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
size: nil)
switch result {
case .success(let image):
@@ -164,7 +164,7 @@ final class MediaProviderTests: XCTestCase {
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndLoadImageThumbnailFails_errorIsThrown() async throws {
mediaLoader.loadMediaThumbnailForSourceWidthHeightThrowableError = MediaProviderTestsError.error
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"),
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
size: Avatars.Size.room(on: .timeline).scaledSize)
switch result {
case .success:
@@ -177,7 +177,7 @@ final class MediaProviderTests: XCTestCase {
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSizeAndLoadImageContentFails_errorIsThrown() async throws {
mediaLoader.loadMediaContentForSourceThrowableError = MediaProviderTestsError.error
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"),
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
size: nil)
switch result {
case .success:
@@ -190,7 +190,7 @@ final class MediaProviderTests: XCTestCase {
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndImageThumbnailIsLoadedWithCorruptedData_errorIsThrown() async throws {
mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = Data()
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"),
let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
size: Avatars.Size.room(on: .timeline).scaledSize)
switch result {
case .success:
@@ -58,7 +58,7 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase {
}
func testAvatarDidChange() {
setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .picturesDirectory, members: [.mockMeAdmin]))
setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .mockMXCAvatar, members: [.mockMeAdmin]))
context.send(viewAction: .removeImage)
XCTAssertTrue(context.viewState.avatarDidChange)
XCTAssertTrue(context.viewState.canSave)
@@ -100,7 +100,7 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase {
}
func testDeleteAvatar() {
setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .picturesDirectory, members: [.mockMeAdmin]))
setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .mockMXCAvatar, members: [.mockMeAdmin]))
XCTAssertNotNil(context.viewState.avatarURL)
context.send(viewAction: .removeImage)
XCTAssertNil(context.viewState.avatarURL)
@@ -184,13 +184,13 @@ class RoomScreenViewModelTests: XCTestCase {
try await deferred.fulfill()
configuration.name = "NewName"
configuration.avatarURL = .documentsDirectory
configuration.avatarURL = .mockMXCAvatar
configuration.hasOngoingCall = true
roomProxyMock.canUserJoinCallUserIDReturnValue = .success(true)
deferred = deferFulfillment(viewModel.context.$viewState) { viewState in
viewState.roomTitle == "NewName" &&
viewState.roomAvatar == .room(id: "TestID", name: "NewName", avatarURL: .documentsDirectory) &&
viewState.roomAvatar == .room(id: "TestID", name: "NewName", avatarURL: .mockMXCAvatar) &&
viewState.canJoinCall &&
viewState.hasOngoingCall
}
@@ -15,7 +15,7 @@ class UserProfileScreenViewModelTests: XCTestCase {
var context: UserProfileScreenViewModelType.Context { viewModel.context }
func testInitialState() async throws {
let profile = UserProfileProxy(userID: "@alice:matrix.org", displayName: "Alice", avatarURL: .picturesDirectory)
let profile = UserProfileProxy(userID: "@alice:matrix.org", displayName: "Alice", avatarURL: .mockMXCAvatar)
let clientProxy = ClientProxyMock(.init())
clientProxy.profileForReturnValue = .success(profile)
@@ -35,7 +35,7 @@ class UserProfileScreenViewModelTests: XCTestCase {
}
func testInitialStateAccountOwner() async throws {
let profile = UserProfileProxy(userID: RoomMemberProxyMock.mockMe.userID, displayName: "Me", avatarURL: .picturesDirectory)
let profile = UserProfileProxy(userID: RoomMemberProxyMock.mockMe.userID, displayName: "Me", avatarURL: .mockMXCAvatar)
let clientProxy = ClientProxyMock(.init())
clientProxy.profileForReturnValue = .success(profile)
@@ -16,7 +16,7 @@ class VoiceMessageCacheTests: XCTestCase {
private var mediaSource: MediaSourceProxy!
private var fileManager: FileManager!
private let someURL = URL("/some/url")
private let someURL = URL.mockMXCAudio
private let testFilename = "test-file"
private let mpeg4aacFileExtension = "m4a"
private let testTemporaryDirectory = URL.temporaryDirectory.appendingPathComponent("test-voice-messsage-cache")
@@ -16,7 +16,7 @@ class VoiceMessageMediaManagerTests: XCTestCase {
private var voiceMessageCache: VoiceMessageCacheMock!
private var mediaProvider: MediaProviderMock!
private let someURL = URL("/some/url")
private let someURL = URL.mockMXCAudio
private let audioOGGMimeType = "audio/ogg"
override func setUp() async throws {
@@ -43,9 +43,7 @@ class VoiceMessageRecorderTests: XCTestCase {
audioPlayer.state = .stopped
mediaPlayerProvider = MediaPlayerProviderMock()
mediaPlayerProvider.playerForClosure = { _ in
.success(self.audioPlayer)
}
mediaPlayerProvider.player = audioPlayer
audioConverter = AudioConverterMock()
voiceMessageCache = VoiceMessageCacheMock()
voiceMessageCache.urlForRecording = FileManager.default.temporaryDirectory.appendingPathComponent("test-voice-message").appendingPathExtension("m4a")
@@ -121,11 +119,10 @@ class VoiceMessageRecorderTests: XCTestCase {
return
}
XCTAssertEqual(voiceMessageRecorder.previewAudioPlayerState?.isAttached, true)
XCTAssert(audioPlayer.loadMediaSourceUsingAutoplayCalled)
XCTAssertEqual(audioPlayer.loadMediaSourceUsingAutoplayReceivedArguments?.url, recordingURL)
XCTAssertEqual(audioPlayer.loadMediaSourceUsingAutoplayReceivedArguments?.mediaSource.mimeType, "audio/m4a")
XCTAssertEqual(audioPlayer.loadMediaSourceUsingAutoplayReceivedArguments?.mediaSource.url, recordingURL)
XCTAssertEqual(audioPlayer.loadMediaSourceUsingAutoplayReceivedArguments?.autoplay, true)
XCTAssert(audioPlayer.loadSourceURLPlaybackURLAutoplayCalled)
XCTAssertEqual(audioPlayer.loadSourceURLPlaybackURLAutoplayReceivedArguments?.sourceURL, recordingURL)
XCTAssertEqual(audioPlayer.loadSourceURLPlaybackURLAutoplayReceivedArguments?.playbackURL, recordingURL)
XCTAssertEqual(audioPlayer.loadSourceURLPlaybackURLAutoplayReceivedArguments?.autoplay, true)
XCTAssertFalse(audioPlayer.playCalled)
}
@@ -141,7 +138,7 @@ class VoiceMessageRecorderTests: XCTestCase {
func testResumePlayback() async throws {
try await setRecordingComplete()
audioPlayer.url = recordingURL
audioPlayer.playbackURL = recordingURL
guard case .success = await voiceMessageRecorder.startPlayback() else {
XCTFail("Playback should start")
@@ -149,7 +146,7 @@ class VoiceMessageRecorderTests: XCTestCase {
}
XCTAssertEqual(voiceMessageRecorder.previewAudioPlayerState?.isAttached, true)
// The media must not have been reloaded
XCTAssertFalse(audioPlayer.loadMediaSourceUsingAutoplayCalled)
XCTAssertFalse(audioPlayer.loadSourceURLPlaybackURLAutoplayCalled)
XCTAssertTrue(audioPlayer.playCalled)
}