mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:02:10 +00:00
Finish migration of UnitTests target from XCTestCase to Swift Testing (#5129)
* Initial plan * Migrate 3 test files from XCTest to Swift Testing - MediaUploadPreviewScreenViewModelTests: @MainActor @Suite struct with init(), BundleFinder class for Bundle(for:), mutating test/setup functions, [self] capture replacing [weak self] in closures - NotificationManagerTests: @MainActor @Suite final class with init()/deinit, expectation/fulfillment(of:) replaced with confirmation(...), test_ prefix stripped - NotificationSettingsScreenViewModelTests: @MainActor @Suite struct with init() throws, non-optional stored properties, test prefix stripped Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate 3 XCTest files to Swift Testing - NotificationSettingsEditScreenViewModelTests: @MainActor @Suite struct with init() throws, mutating test methods - TimelineViewModelTests: @MainActor @Suite final class with init() async throws + deinit - AttributedStringBuilderTests: @Suite struct with init() async throws All XCT assertions replaced with #expect/#require/Issue.record Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate 4 test files from XCTest to Swift Testing - TimelineMediaPreviewViewModelTests: @Suite struct, mutating @Test funcs, testLoadingItem renamed to loadingItem (called internally by other tests) - ServerConfirmationScreenViewModelTests: @Suite final class with init()/deinit - CompletionSuggestionServiceTests: @Suite struct with init() - RoomFlowCoordinatorTests: @Suite final class with deinit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate 4 test files from XCTest to Swift Testing - VoiceMessageRecorderTests: @Suite struct with init() async throws, added BundleFinder class for Bundle lookup, migrated all assertions - SpaceScreenViewModelTests: @Suite struct, private mutating setupViewModel, all test funcs mutating, XCTestExpectation → confirmation - RoomNotificationSettingsScreenViewModelTests: @Suite struct with init() throws, cancellable tests marked mutating - JoinRoomScreenViewModelTests: @Suite final class with init()/deinit, XCTestExpectation → confirmation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate 6 test files from XCTestCase to Swift Testing Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> * Fix trailing blank line in RoomPollsHistoryScreenViewModelTests Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> * Migrate 3 test files from XCTest to Swift Testing - MediaUploadingPreprocessorTests: @Suite final class with init()/deinit, removed executionTimeAllowance, XCTAssertEqual(accuracy:) → abs(Double) - SecurityAndPrivacyScreenViewModelTests: @MainActor @Suite final class, 5 expectation+fulfillment → await confirmation(...) - CreateRoomViewModelTests: @MainActor @Suite final class, 4 expectation+fulfillment → await confirmation(...) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate RoomScreenViewModelTests and RoomDetailsScreenViewModelTests to Swift Testing - Replace XCTest with Testing framework - RoomScreenViewModelTests: final class with init() async throws + deinit - RoomDetailsScreenViewModelTests: struct with init() and mutating funcs - Convert XCT assertions to #expect / Issue.record - Convert XCTestExpectation patterns to confirmation { confirm in } - Strip 'test' prefix from all test function names Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate ComposerToolbarViewModelTests from XCTest to Swift Testing - Replace import XCTest with import Testing - Convert XCTestCase class to @MainActor @Suite final class - Replace setUp()/tearDown() with init()/deinit - Strip 'test' prefix from all 41 test method names and add @Test - Replace XCTAssert* with #expect()/#require() - Replace try XCTUnwrap() with try #require() - Convert expectation+wait patterns to deferFulfillment with PassthroughSubject - Convert isInverted expectation to boolean flag checked after await - Use deferFulfillment on $viewState for state-transition tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address comments with Copilot. * Fix the failing tests. * Fixed flaky tests (#5137) resolved flaky tests * Tweaks and fixes. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> Co-authored-by: Doug <douglase@element.io> Co-authored-by: Mauro <34335419+Velin92@users.noreply.github.com>
This commit is contained in:
@@ -9,17 +9,19 @@
|
||||
import Combine
|
||||
@testable import ElementX
|
||||
import Kingfisher
|
||||
import XCTest
|
||||
import SwiftUI
|
||||
import Testing
|
||||
|
||||
@Suite
|
||||
@MainActor
|
||||
final class MediaProviderTests: XCTestCase {
|
||||
private var mediaLoader: MediaLoaderMock!
|
||||
private var imageCache: MockImageCache!
|
||||
struct MediaProviderTests {
|
||||
private var mediaLoader: MediaLoaderMock
|
||||
private var imageCache: MockImageCache
|
||||
private var reachabilitySubject = CurrentValueSubject<NetworkMonitorReachability, Never>(.reachable)
|
||||
|
||||
var mediaProvider: MediaProvider!
|
||||
|
||||
override func setUp() {
|
||||
init() {
|
||||
mediaLoader = MediaLoaderMock()
|
||||
imageCache = MockImageCache(name: "Test")
|
||||
|
||||
@@ -28,12 +30,10 @@ final class MediaProviderTests: XCTestCase {
|
||||
homeserverReachabilityPublisher: reachabilitySubject.asCurrentValuePublisher())
|
||||
}
|
||||
|
||||
func testLoadingRetriedOnReconnection() async throws {
|
||||
@Test
|
||||
func loadingRetriedOnReconnection() async throws {
|
||||
let testImage = try loadTestImage()
|
||||
guard let pngData = testImage.pngData() else {
|
||||
XCTFail("Test image should contain valid .png data")
|
||||
return
|
||||
}
|
||||
let pngData = try #require(testImage.pngData(), "Test image should contain valid .png data")
|
||||
|
||||
let loadTask = try mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"))
|
||||
|
||||
@@ -51,11 +51,12 @@ final class MediaProviderTests: XCTestCase {
|
||||
|
||||
let result = try? await loadTask.value
|
||||
|
||||
XCTAssertNotNil(result)
|
||||
XCTAssertEqual(mediaLoader.loadMediaContentForSourceCallsCount, 2)
|
||||
#expect(result != nil)
|
||||
#expect(mediaLoader.loadMediaContentForSourceCallsCount == 2)
|
||||
}
|
||||
|
||||
func testLoadingRetriedOnReconnectionCancelsAfterSecondFailure() async throws {
|
||||
@Test
|
||||
func loadingRetriedOnReconnectionCancelsAfterSecondFailure() async throws {
|
||||
let loadTask = try mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"))
|
||||
|
||||
reachabilitySubject.send(.reachable)
|
||||
@@ -64,15 +65,17 @@ final class MediaProviderTests: XCTestCase {
|
||||
|
||||
let result = try? await loadTask.value
|
||||
|
||||
XCTAssertNil(result)
|
||||
#expect(result == nil)
|
||||
}
|
||||
|
||||
func test_whenImageFromSourceWithSourceNil_nilReturned() {
|
||||
@Test
|
||||
func whenImageFromSourceWithSourceNil_nilReturned() {
|
||||
let image = mediaProvider.imageFromSource(nil, size: Avatars.Size.room(on: .timeline).scaledSize)
|
||||
XCTAssertNil(image)
|
||||
#expect(image == nil)
|
||||
}
|
||||
|
||||
func test_whenImageFromSourceWithSourceNotNilAndImageCacheContainsImage_ImageIsReturned() throws {
|
||||
@Test
|
||||
func whenImageFromSourceWithSourceNotNilAndImageCacheContainsImage_ImageIsReturned() throws {
|
||||
let avatarSize = Avatars.Size.room(on: .timeline)
|
||||
let url = URL.mockMXCImage
|
||||
let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}"
|
||||
@@ -80,16 +83,18 @@ final class MediaProviderTests: XCTestCase {
|
||||
imageCache.retrievedImagesInMemory[key] = imageForKey
|
||||
let image = try mediaProvider.imageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"),
|
||||
size: avatarSize.scaledSize)
|
||||
XCTAssertEqual(image, imageForKey)
|
||||
#expect(image == imageForKey)
|
||||
}
|
||||
|
||||
func test_whenImageFromSourceWithSourceNotNilAndImageNotCached_nilReturned() throws {
|
||||
@Test
|
||||
func whenImageFromSourceWithSourceNotNilAndImageNotCached_nilReturned() throws {
|
||||
let image = try mediaProvider.imageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
|
||||
size: Avatars.Size.room(on: .timeline).scaledSize)
|
||||
XCTAssertNil(image)
|
||||
#expect(image == nil)
|
||||
}
|
||||
|
||||
func test_whenLoadImageFromSourceAndImageCacheContainsImage_successIsReturned() async throws {
|
||||
@Test
|
||||
func whenLoadImageFromSourceAndImageCacheContainsImage_successIsReturned() async throws {
|
||||
let avatarSize = Avatars.Size.room(on: .timeline)
|
||||
let url = URL.mockMXCImage
|
||||
let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}"
|
||||
@@ -97,10 +102,11 @@ final class MediaProviderTests: XCTestCase {
|
||||
imageCache.retrievedImagesInMemory[key] = imageForKey
|
||||
let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"),
|
||||
size: avatarSize.scaledSize)
|
||||
XCTAssertEqual(Result.success(imageForKey), result)
|
||||
#expect(Result.success(imageForKey) == result)
|
||||
}
|
||||
|
||||
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageSucceeds_successIsReturned() async throws {
|
||||
@Test
|
||||
func whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageSucceeds_successIsReturned() async throws {
|
||||
let avatarSize = Avatars.Size.room(on: .timeline)
|
||||
let url = URL.mockMXCImage
|
||||
let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}"
|
||||
@@ -108,10 +114,11 @@ final class MediaProviderTests: XCTestCase {
|
||||
imageCache.retrievedImages[key] = imageForKey
|
||||
let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"),
|
||||
size: avatarSize.scaledSize)
|
||||
XCTAssertEqual(Result.success(imageForKey), result)
|
||||
#expect(Result.success(imageForKey) == result)
|
||||
}
|
||||
|
||||
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageThumbnailIsLoaded() async throws {
|
||||
@Test
|
||||
func whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageThumbnailIsLoaded() async throws {
|
||||
let avatarSize = Avatars.Size.room(on: .timeline)
|
||||
let expectedImage = try loadTestImage()
|
||||
|
||||
@@ -121,13 +128,14 @@ final class MediaProviderTests: XCTestCase {
|
||||
size: avatarSize.scaledSize)
|
||||
switch result {
|
||||
case .success(let image):
|
||||
XCTAssertEqual(image.pngData(), expectedImage.pngData())
|
||||
#expect(image.pngData() == expectedImage.pngData())
|
||||
case .failure:
|
||||
XCTFail("Should be success")
|
||||
Issue.record("Should be success")
|
||||
}
|
||||
}
|
||||
|
||||
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageIsStored() async throws {
|
||||
@Test
|
||||
func whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageIsStored() async throws {
|
||||
let avatarSize = Avatars.Size.room(on: .timeline)
|
||||
let url = URL.mockMXCImage
|
||||
let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}"
|
||||
@@ -137,11 +145,12 @@ final class MediaProviderTests: XCTestCase {
|
||||
|
||||
_ = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"),
|
||||
size: avatarSize.scaledSize)
|
||||
let storedImage = try XCTUnwrap(imageCache.storedImages[key])
|
||||
XCTAssertEqual(expectedImage.pngData(), storedImage.pngData())
|
||||
let storedImage = try #require(imageCache.storedImages[key])
|
||||
#expect(expectedImage.pngData() == storedImage.pngData())
|
||||
}
|
||||
|
||||
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSize_imageContentIsLoaded() async throws {
|
||||
@Test
|
||||
func whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSize_imageContentIsLoaded() async throws {
|
||||
let expectedImage = try loadTestImage()
|
||||
|
||||
mediaLoader.loadMediaContentForSourceReturnValue = expectedImage.pngData()
|
||||
@@ -150,53 +159,56 @@ final class MediaProviderTests: XCTestCase {
|
||||
size: nil)
|
||||
switch result {
|
||||
case .success(let image):
|
||||
XCTAssertEqual(image.pngData(), expectedImage.pngData())
|
||||
#expect(image.pngData() == expectedImage.pngData())
|
||||
case .failure:
|
||||
XCTFail("Should be success")
|
||||
Issue.record("Should be success")
|
||||
}
|
||||
}
|
||||
|
||||
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndLoadImageThumbnailFails_errorIsThrown() async throws {
|
||||
@Test
|
||||
func whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndLoadImageThumbnailFails_errorIsThrown() async throws {
|
||||
mediaLoader.loadMediaThumbnailForSourceWidthHeightThrowableError = MediaProviderTestsError.error
|
||||
|
||||
let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
|
||||
size: Avatars.Size.room(on: .timeline).scaledSize)
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Should fail")
|
||||
Issue.record("Should fail")
|
||||
case .failure(let error):
|
||||
XCTAssertEqual(error, MediaProviderError.failedRetrievingImage)
|
||||
#expect(error == MediaProviderError.failedRetrievingImage)
|
||||
}
|
||||
}
|
||||
|
||||
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSizeAndLoadImageContentFails_errorIsThrown() async throws {
|
||||
@Test
|
||||
func whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSizeAndLoadImageContentFails_errorIsThrown() async throws {
|
||||
mediaLoader.loadMediaContentForSourceThrowableError = MediaProviderTestsError.error
|
||||
|
||||
let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
|
||||
size: nil)
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Should fail")
|
||||
Issue.record("Should fail")
|
||||
case .failure(let error):
|
||||
XCTAssertEqual(error, MediaProviderError.failedRetrievingImage)
|
||||
#expect(error == MediaProviderError.failedRetrievingImage)
|
||||
}
|
||||
}
|
||||
|
||||
func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndImageThumbnailIsLoadedWithCorruptedData_errorIsThrown() async throws {
|
||||
@Test
|
||||
func whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndImageThumbnailIsLoadedWithCorruptedData_errorIsThrown() async throws {
|
||||
mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = Data()
|
||||
|
||||
let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"),
|
||||
size: Avatars.Size.room(on: .timeline).scaledSize)
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Should fail")
|
||||
Issue.record("Should fail")
|
||||
case .failure(let error):
|
||||
XCTAssertEqual(error, MediaProviderError.invalidImageData)
|
||||
#expect(error == MediaProviderError.invalidImageData)
|
||||
}
|
||||
}
|
||||
|
||||
private func loadTestImage() throws -> UIImage {
|
||||
guard let path = Bundle(for: Self.self).path(forResource: "test_image", ofType: "png"),
|
||||
guard let path = Bundle(for: UnitTestsAppCoordinator.self).path(forResource: "test_image", ofType: "png"),
|
||||
let image = UIImage(contentsOfFile: path) else {
|
||||
throw MediaProviderTestsError.error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user