mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +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:
@@ -7,15 +7,17 @@
|
||||
//
|
||||
|
||||
@testable import ElementX
|
||||
import SwiftUI
|
||||
import Testing
|
||||
import UniformTypeIdentifiers
|
||||
import XCTest
|
||||
|
||||
final class MediaUploadingPreprocessorTests: XCTestCase {
|
||||
@Suite
|
||||
final class MediaUploadingPreprocessorTests {
|
||||
let maxUploadSize: UInt = 100 * 1024 * 1024
|
||||
var appSettings: AppSettings!
|
||||
var mediaUploadingPreprocessor: MediaUploadingPreprocessor!
|
||||
|
||||
override func setUp() {
|
||||
init() {
|
||||
AppSettings.resetAllSettings()
|
||||
appSettings = AppSettings()
|
||||
appSettings.optimizeMediaUploads = false
|
||||
@@ -23,450 +25,426 @@ final class MediaUploadingPreprocessorTests: XCTestCase {
|
||||
mediaUploadingPreprocessor = MediaUploadingPreprocessor(appSettings: appSettings)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
deinit {
|
||||
AppSettings.resetAllSettings()
|
||||
}
|
||||
|
||||
func testAudioFileProcessing() async {
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "test_audio.mp3", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func audioFileProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "test_audio.mp3", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .audio(audioURL, audioInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
// Check that the file name is preserved
|
||||
XCTAssertEqual(audioURL.lastPathComponent, "test_audio.mp3")
|
||||
#expect(audioURL.lastPathComponent == "test_audio.mp3")
|
||||
|
||||
XCTAssertEqual(audioInfo.mimetype, "audio/mpeg")
|
||||
XCTAssertEqual(audioInfo.duration ?? 0, 27, accuracy: 100)
|
||||
XCTAssertEqual(audioInfo.size ?? 0, 194_811, accuracy: 100)
|
||||
#expect(audioInfo.mimetype == "audio/mpeg")
|
||||
#expect(isEqual(audioInfo.duration ?? 0, 27, within: 100))
|
||||
#expect(isEqual(audioInfo.size ?? 0, 194_811, within: 100))
|
||||
}
|
||||
|
||||
func testLandscapeMovVideoProcessing() async {
|
||||
// Allow an increased execution time as we encode the video twice now.
|
||||
executionTimeAllowance = 180
|
||||
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "landscape_test_video.mov", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func landscapeMovVideoProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "landscape_test_video.mov", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .video(videoURL, thumbnailURL, videoInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
// Check that the file name is preserved
|
||||
XCTAssertEqual(videoURL.lastPathComponent, "landscape_test_video.mp4")
|
||||
XCTAssertEqual(videoURL.pathExtension, "mp4", "The file extension should match the container we use.")
|
||||
#expect(videoURL.lastPathComponent == "landscape_test_video.mp4")
|
||||
#expect(videoURL.pathExtension == "mp4", "The file extension should match the container we use.")
|
||||
|
||||
// Check that the thumbnail is generated correctly
|
||||
guard let thumbnailData = try? Data(contentsOf: thumbnailURL),
|
||||
let thumbnail = UIImage(data: thumbnailData) else {
|
||||
XCTFail("Invalid thumbnail")
|
||||
return
|
||||
}
|
||||
let thumbnailData = try Data(contentsOf: thumbnailURL)
|
||||
let thumbnail = try #require(UIImage(data: thumbnailData), "Invalid thumbnail")
|
||||
|
||||
XCTAssert(thumbnail.size.width <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.width)
|
||||
XCTAssert(thumbnail.size.height <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.height)
|
||||
#expect(thumbnail.size.width <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.width)
|
||||
#expect(thumbnail.size.height <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.height)
|
||||
|
||||
// Check resulting video info
|
||||
XCTAssertEqual(videoInfo.mimetype, "video/mp4")
|
||||
XCTAssertEqual(videoInfo.blurhash, "K9F$LJZ9,+8yA9-:yT,@%1")
|
||||
XCTAssertEqual(videoInfo.size ?? 0, 4_016_620, accuracy: 100)
|
||||
XCTAssertEqual(videoInfo.width, 1280)
|
||||
XCTAssertEqual(videoInfo.height, 720)
|
||||
XCTAssertEqual(videoInfo.duration ?? 0, 30, accuracy: 100)
|
||||
#expect(videoInfo.mimetype == "video/mp4")
|
||||
#expect(videoInfo.blurhash == "K9F$LJZ9,+8yA9-:yT,@%1")
|
||||
#expect(isEqual(videoInfo.size ?? 0, 4_016_620, within: 100))
|
||||
#expect(videoInfo.width == 1280)
|
||||
#expect(videoInfo.height == 720)
|
||||
#expect(isEqual(videoInfo.duration ?? 0, 30, within: 100))
|
||||
|
||||
XCTAssertNotNil(videoInfo.thumbnailInfo)
|
||||
XCTAssertEqual(videoInfo.thumbnailInfo?.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(videoInfo.thumbnailInfo?.size ?? 0, 183_093, accuracy: 100)
|
||||
XCTAssertEqual(videoInfo.thumbnailInfo?.width, 800)
|
||||
XCTAssertEqual(videoInfo.thumbnailInfo?.height, 450)
|
||||
#expect(videoInfo.thumbnailInfo != nil)
|
||||
#expect(videoInfo.thumbnailInfo?.mimetype == "image/jpeg")
|
||||
#expect(isEqual(videoInfo.thumbnailInfo?.size ?? 0, 183_093, within: 100))
|
||||
#expect(videoInfo.thumbnailInfo?.width == 800)
|
||||
#expect(videoInfo.thumbnailInfo?.height == 450)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
appSettings.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .video(optimizedVideoURL, _, optimizedVideoInfo) = optimizedResult else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(optimizedVideoURL.pathExtension, "mp4", "The file extension should match the container we use.")
|
||||
#expect(optimizedVideoURL.pathExtension == "mp4", "The file extension should match the container we use.")
|
||||
|
||||
// Check optimised video info
|
||||
XCTAssertEqual(optimizedVideoInfo.mimetype, "video/mp4")
|
||||
XCTAssertEqual(optimizedVideoInfo.blurhash, "K9F$LJZ9,+8yA9-:yT,@%1")
|
||||
XCTAssertEqual(optimizedVideoInfo.size ?? 0, 4_016_620, accuracy: 100) // Note: The video is already 720p so it doesn't change size.
|
||||
XCTAssertEqual(optimizedVideoInfo.width, 1280)
|
||||
XCTAssertEqual(optimizedVideoInfo.height, 720)
|
||||
XCTAssertEqual(optimizedVideoInfo.duration ?? 0, 30, accuracy: 100)
|
||||
#expect(optimizedVideoInfo.mimetype == "video/mp4")
|
||||
#expect(optimizedVideoInfo.blurhash == "K9F$LJZ9,+8yA9-:yT,@%1")
|
||||
#expect(isEqual(optimizedVideoInfo.size ?? 0, 4_016_620, within: 100)) // Note: The video is already 720p so it doesn't change size.
|
||||
#expect(optimizedVideoInfo.width == 1280)
|
||||
#expect(optimizedVideoInfo.height == 720)
|
||||
#expect(isEqual(optimizedVideoInfo.duration ?? 0, 30, within: 100))
|
||||
}
|
||||
|
||||
func testPortraitMp4VideoProcessing() async {
|
||||
// Allow an increased execution time as we encode the video twice now.
|
||||
executionTimeAllowance = 180
|
||||
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "portrait_test_video.mp4", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func portraitMp4VideoProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "portrait_test_video.mp4", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .video(videoURL, thumbnailURL, videoInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
// Check that the file name is preserved
|
||||
XCTAssertEqual(videoURL.lastPathComponent, "portrait_test_video.mp4")
|
||||
XCTAssertEqual(videoURL.pathExtension, "mp4", "The file extension should match the container we use.")
|
||||
#expect(videoURL.lastPathComponent == "portrait_test_video.mp4")
|
||||
#expect(videoURL.pathExtension == "mp4", "The file extension should match the container we use.")
|
||||
|
||||
// Check that the thumbnail is generated correctly
|
||||
guard let thumbnailData = try? Data(contentsOf: thumbnailURL),
|
||||
let thumbnail = UIImage(data: thumbnailData) else {
|
||||
XCTFail("Invalid thumbnail")
|
||||
return
|
||||
}
|
||||
let thumbnailData = try Data(contentsOf: thumbnailURL)
|
||||
let thumbnail = try #require(UIImage(data: thumbnailData), "Invalid thumbnail")
|
||||
|
||||
XCTAssert(thumbnail.size.width <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.width)
|
||||
XCTAssert(thumbnail.size.height <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.height)
|
||||
#expect(thumbnail.size.width <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.width)
|
||||
#expect(thumbnail.size.height <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.height)
|
||||
|
||||
// Check resulting video info
|
||||
XCTAssertEqual(videoInfo.mimetype, "video/mp4")
|
||||
XCTAssertEqual(videoInfo.blurhash, "KSB{R8O]MuwQS4oJvcaIt8")
|
||||
XCTAssertEqual(videoInfo.size ?? 0, 5_824_946, accuracy: 100)
|
||||
XCTAssertEqual(videoInfo.width, 1080)
|
||||
XCTAssertEqual(videoInfo.height, 1920)
|
||||
XCTAssertEqual(videoInfo.duration ?? 0, 21, accuracy: 100)
|
||||
#expect(videoInfo.mimetype == "video/mp4")
|
||||
#expect(videoInfo.blurhash == "KSB{R8O]MuwQS4oJvcaIt8")
|
||||
#expect(isEqual(videoInfo.size ?? 0, 5_824_946, within: 100))
|
||||
#expect(videoInfo.width == 1080)
|
||||
#expect(videoInfo.height == 1920)
|
||||
#expect(isEqual(videoInfo.duration ?? 0, 21, within: 100))
|
||||
|
||||
XCTAssertNotNil(videoInfo.thumbnailInfo)
|
||||
XCTAssertEqual(videoInfo.thumbnailInfo?.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(videoInfo.thumbnailInfo?.size ?? 0, 40976, accuracy: 100)
|
||||
XCTAssertEqual(videoInfo.thumbnailInfo?.width, 337)
|
||||
XCTAssertEqual(videoInfo.thumbnailInfo?.height, 600)
|
||||
#expect(videoInfo.thumbnailInfo != nil)
|
||||
#expect(videoInfo.thumbnailInfo?.mimetype == "image/jpeg")
|
||||
#expect(isEqual(videoInfo.thumbnailInfo?.size ?? 0, 40976, within: 100))
|
||||
#expect(videoInfo.thumbnailInfo?.width == 337)
|
||||
#expect(videoInfo.thumbnailInfo?.height == 600)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
appSettings.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .video(optimizedVideoURL, _, optimizedVideoInfo) = optimizedResult else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(optimizedVideoURL.pathExtension, "mp4", "The file extension should match the container we use.")
|
||||
#expect(optimizedVideoURL.pathExtension == "mp4", "The file extension should match the container we use.")
|
||||
|
||||
// Check optimised video info
|
||||
XCTAssertEqual(optimizedVideoInfo.mimetype, "video/mp4")
|
||||
XCTAssertEqual(optimizedVideoInfo.blurhash, "KSC5.vO]MuwQS4oJvcaIt8")
|
||||
XCTAssertEqual(optimizedVideoInfo.size ?? 0, 12_169_117, accuracy: 100) // Note: This is slightly stupid because it is larger now 🤦♂️
|
||||
XCTAssertEqual(optimizedVideoInfo.width, 720)
|
||||
XCTAssertEqual(optimizedVideoInfo.height, 1280)
|
||||
XCTAssertEqual(optimizedVideoInfo.duration ?? 0, 30, accuracy: 100)
|
||||
#expect(optimizedVideoInfo.mimetype == "video/mp4")
|
||||
#expect(optimizedVideoInfo.blurhash == "KSC5.vO]MuwQS4oJvcaIt8")
|
||||
#expect(isEqual(optimizedVideoInfo.size ?? 0, 12_169_117, within: 100)) // Note: This is slightly stupid because it is larger now 🤦♂️
|
||||
#expect(optimizedVideoInfo.width == 720)
|
||||
#expect(optimizedVideoInfo.height == 1280)
|
||||
#expect(isEqual(optimizedVideoInfo.duration ?? 0, 30, within: 100))
|
||||
}
|
||||
|
||||
func testLandscapeImageProcessing() async {
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "landscape_test_image.jpg", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func landscapeImageProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "landscape_test_image.jpg", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(convertedImageURL, thumbnailURL, imageInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
compare(originalImageAt: url, toConvertedImageAt: convertedImageURL, withThumbnailAt: thumbnailURL)
|
||||
try compare(originalImageAt: url, toConvertedImageAt: convertedImageURL, withThumbnailAt: thumbnailURL)
|
||||
|
||||
// Check resulting image info
|
||||
XCTAssertEqual(imageInfo.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(imageInfo.blurhash, "K%I#.NofkC_4ayayxujsWB")
|
||||
XCTAssertEqual(imageInfo.size ?? 0, 3_305_795, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.width, 6103)
|
||||
XCTAssertEqual(imageInfo.height, 2621)
|
||||
#expect(imageInfo.mimetype == "image/jpeg")
|
||||
#expect(imageInfo.blurhash == "K%I#.NofkC_4ayayxujsWB")
|
||||
#expect(isEqual(imageInfo.size ?? 0, 3_305_795, within: 100))
|
||||
#expect(imageInfo.width == 6103)
|
||||
#expect(imageInfo.height == 2621)
|
||||
|
||||
XCTAssertNotNil(imageInfo.thumbnailInfo)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.size ?? 0, 87733, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.width, 800)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.height, 344)
|
||||
#expect(imageInfo.thumbnailInfo != nil)
|
||||
#expect(imageInfo.thumbnailInfo?.mimetype == "image/jpeg")
|
||||
#expect(isEqual(imageInfo.thumbnailInfo?.size ?? 0, 87733, within: 100))
|
||||
#expect(imageInfo.thumbnailInfo?.width == 800)
|
||||
#expect(imageInfo.thumbnailInfo?.height == 344)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
appSettings.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
compare(originalImageAt: url, toConvertedImageAt: optimizedImageURL, withThumbnailAt: thumbnailURL)
|
||||
try compare(originalImageAt: url, toConvertedImageAt: optimizedImageURL, withThumbnailAt: thumbnailURL)
|
||||
|
||||
// Check optimised image info
|
||||
XCTAssertEqual(optimizedImageInfo.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(optimizedImageInfo.blurhash, "K%I#.NofkC_4ayaxxujsWB")
|
||||
XCTAssertEqual(optimizedImageInfo.size ?? 0, 524_226, accuracy: 100)
|
||||
XCTAssertEqual(optimizedImageInfo.width, 2048)
|
||||
XCTAssertEqual(optimizedImageInfo.height, 879)
|
||||
#expect(optimizedImageInfo.mimetype == "image/jpeg")
|
||||
#expect(optimizedImageInfo.blurhash == "K%I#.NofkC_4ayaxxujsWB")
|
||||
#expect(isEqual(optimizedImageInfo.size ?? 0, 524_226, within: 100))
|
||||
#expect(optimizedImageInfo.width == 2048)
|
||||
#expect(optimizedImageInfo.height == 879)
|
||||
}
|
||||
|
||||
func testPortraitImageProcessing() async {
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "portrait_test_image.jpg", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func portraitImageProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "portrait_test_image.jpg", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(convertedImageURL, thumbnailURL, imageInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
compare(originalImageAt: url, toConvertedImageAt: convertedImageURL, withThumbnailAt: thumbnailURL)
|
||||
try compare(originalImageAt: url, toConvertedImageAt: convertedImageURL, withThumbnailAt: thumbnailURL)
|
||||
|
||||
// Check resulting image info
|
||||
XCTAssertEqual(imageInfo.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(imageInfo.blurhash, "KdE|0Ls+RP^-n*RP%OWAV@")
|
||||
XCTAssertEqual(imageInfo.size ?? 0, 4_414_666, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.width, 3024)
|
||||
XCTAssertEqual(imageInfo.height, 4032)
|
||||
#expect(imageInfo.mimetype == "image/jpeg")
|
||||
#expect(imageInfo.blurhash == "KdE|0Ls+RP^-n*RP%OWAV@")
|
||||
#expect(isEqual(imageInfo.size ?? 0, 4_414_666, within: 100))
|
||||
#expect(imageInfo.width == 3024)
|
||||
#expect(imageInfo.height == 4032)
|
||||
|
||||
XCTAssertNotNil(imageInfo.thumbnailInfo)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.size ?? 0, 258_914, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.width, 600)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.height, 800)
|
||||
#expect(imageInfo.thumbnailInfo != nil)
|
||||
#expect(imageInfo.thumbnailInfo?.mimetype == "image/jpeg")
|
||||
#expect(isEqual(imageInfo.thumbnailInfo?.size ?? 0, 258_914, within: 100))
|
||||
#expect(imageInfo.thumbnailInfo?.width == 600)
|
||||
#expect(imageInfo.thumbnailInfo?.height == 800)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
appSettings.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
compare(originalImageAt: url, toConvertedImageAt: optimizedImageURL, withThumbnailAt: thumbnailURL)
|
||||
try compare(originalImageAt: url, toConvertedImageAt: optimizedImageURL, withThumbnailAt: thumbnailURL)
|
||||
|
||||
// Check optimised image info
|
||||
XCTAssertEqual(optimizedImageInfo.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(optimizedImageInfo.blurhash, "KdE|0Ls+RP^-n*RP%OWAV@")
|
||||
XCTAssertEqual(optimizedImageInfo.size ?? 0, 1_462_937, accuracy: 100)
|
||||
XCTAssertEqual(optimizedImageInfo.width, 1536)
|
||||
XCTAssertEqual(optimizedImageInfo.height, 2048)
|
||||
#expect(optimizedImageInfo.mimetype == "image/jpeg")
|
||||
#expect(optimizedImageInfo.blurhash == "KdE|0Ls+RP^-n*RP%OWAV@")
|
||||
#expect(isEqual(optimizedImageInfo.size ?? 0, 1_462_937, within: 100))
|
||||
#expect(optimizedImageInfo.width == 1536)
|
||||
#expect(optimizedImageInfo.height == 2048)
|
||||
}
|
||||
|
||||
func testPNGImageProcessing() async {
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "test_image.png", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func pngImageProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "test_image.png", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(convertedImageURL, _, imageInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure the output file matches the image info.
|
||||
XCTAssertEqual(mimeType(from: convertedImageURL), "image/png", "PNGs should always be sent as PNG to preserve the alpha channel.")
|
||||
XCTAssertEqual(convertedImageURL.pathExtension, "png", "The file extension should match the MIME type.")
|
||||
#expect(mimeType(from: convertedImageURL) == "image/png", "PNGs should always be sent as PNG to preserve the alpha channel.")
|
||||
#expect(convertedImageURL.pathExtension == "png", "The file extension should match the MIME type.")
|
||||
|
||||
// Check resulting image info
|
||||
XCTAssertEqual(imageInfo.mimetype, "image/png")
|
||||
XCTAssertEqual(imageInfo.blurhash, "K0TSUA~qfQ~qj[fQfQfQfQ")
|
||||
XCTAssertEqual(imageInfo.size ?? 0, 4868, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.width, 240)
|
||||
XCTAssertEqual(imageInfo.height, 240)
|
||||
#expect(imageInfo.mimetype == "image/png")
|
||||
#expect(imageInfo.blurhash == "K0TSUA~qfQ~qj[fQfQfQfQ")
|
||||
#expect(isEqual(imageInfo.size ?? 0, 4868, within: 100))
|
||||
#expect(imageInfo.width == 240)
|
||||
#expect(imageInfo.height == 240)
|
||||
|
||||
XCTAssertNotNil(imageInfo.thumbnailInfo)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.size ?? 0, 1725, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.width, 240)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.height, 240)
|
||||
#expect(imageInfo.thumbnailInfo != nil)
|
||||
#expect(imageInfo.thumbnailInfo?.mimetype == "image/jpeg")
|
||||
#expect(isEqual(imageInfo.thumbnailInfo?.size ?? 0, 1725, within: 100))
|
||||
#expect(imageInfo.thumbnailInfo?.width == 240)
|
||||
#expect(imageInfo.thumbnailInfo?.height == 240)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
appSettings.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, _, optimizedImageInfo) = optimizedResult else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure the output file matches the image info.
|
||||
XCTAssertEqual(mimeType(from: optimizedImageURL), "image/png", "PNGs should always be sent as PNG to preserve the alpha channel.")
|
||||
XCTAssertEqual(optimizedImageURL.pathExtension, "png", "The file extension should match the MIME type.")
|
||||
#expect(mimeType(from: optimizedImageURL) == "image/png", "PNGs should always be sent as PNG to preserve the alpha channel.")
|
||||
#expect(optimizedImageURL.pathExtension == "png", "The file extension should match the MIME type.")
|
||||
|
||||
// Check optimised image info
|
||||
XCTAssertEqual(optimizedImageInfo.mimetype, "image/png")
|
||||
XCTAssertEqual(optimizedImageInfo.blurhash, "K0TSUA~qfQ~qj[fQfQfQfQ")
|
||||
XCTAssertEqual(optimizedImageInfo.size ?? 0, 8199, accuracy: 100)
|
||||
#expect(optimizedImageInfo.mimetype == "image/png")
|
||||
#expect(optimizedImageInfo.blurhash == "K0TSUA~qfQ~qj[fQfQfQfQ")
|
||||
#expect(isEqual(optimizedImageInfo.size ?? 0, 8199, within: 100))
|
||||
// Assert that resizing didn't upscale to the maxPixelSize.
|
||||
XCTAssertEqual(optimizedImageInfo.width, 240)
|
||||
XCTAssertEqual(optimizedImageInfo.height, 240)
|
||||
#expect(optimizedImageInfo.width == 240)
|
||||
#expect(optimizedImageInfo.height == 240)
|
||||
}
|
||||
|
||||
func testHEICImageProcessing() async {
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "test_apple_image.heic", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func heicImageProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "test_apple_image.heic", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(convertedImageURL, thumbnailURL, imageInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
compare(originalImageAt: url, toConvertedImageAt: convertedImageURL, withThumbnailAt: thumbnailURL)
|
||||
try compare(originalImageAt: url, toConvertedImageAt: convertedImageURL, withThumbnailAt: thumbnailURL)
|
||||
|
||||
// Make sure the output file matches the image info.
|
||||
XCTAssertEqual(mimeType(from: convertedImageURL), "image/heic", "Unoptimised HEICs should always be sent as is.")
|
||||
XCTAssertEqual(convertedImageURL.pathExtension, "heic", "The file extension should match the MIME type.")
|
||||
#expect(mimeType(from: convertedImageURL) == "image/heic", "Unoptimised HEICs should always be sent as is.")
|
||||
#expect(convertedImageURL.pathExtension == "heic", "The file extension should match the MIME type.")
|
||||
|
||||
// Check resulting image info
|
||||
XCTAssertEqual(imageInfo.mimetype, "image/heic")
|
||||
XCTAssertEqual(imageInfo.blurhash, "KGD]3ns:T00$kWxFXmt6xv")
|
||||
XCTAssertEqual(imageInfo.size ?? 0, 1_848_525, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.width, 3024)
|
||||
XCTAssertEqual(imageInfo.height, 4032)
|
||||
#expect(imageInfo.mimetype == "image/heic")
|
||||
#expect(imageInfo.blurhash == "KGD]3ns:T00$kWxFXmt6xv")
|
||||
#expect(isEqual(imageInfo.size ?? 0, 1_848_525, within: 100))
|
||||
#expect(imageInfo.width == 3024)
|
||||
#expect(imageInfo.height == 4032)
|
||||
|
||||
XCTAssertNotNil(imageInfo.thumbnailInfo)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.size ?? 0, 218_108, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.width, 600)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.height, 800)
|
||||
#expect(imageInfo.thumbnailInfo != nil)
|
||||
#expect(imageInfo.thumbnailInfo?.mimetype == "image/jpeg")
|
||||
#expect(isEqual(imageInfo.thumbnailInfo?.size ?? 0, 218_108, within: 100))
|
||||
#expect(imageInfo.thumbnailInfo?.width == 600)
|
||||
#expect(imageInfo.thumbnailInfo?.height == 800)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
appSettings.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
compare(originalImageAt: url, toConvertedImageAt: optimizedImageURL, withThumbnailAt: thumbnailURL)
|
||||
try compare(originalImageAt: url, toConvertedImageAt: optimizedImageURL, withThumbnailAt: thumbnailURL)
|
||||
|
||||
// Make sure the output file matches the image info.
|
||||
XCTAssertEqual(mimeType(from: optimizedImageURL), "image/jpeg", "Optimised HEICs should always be converted to JPEG for compatibility.")
|
||||
XCTAssertEqual(optimizedImageURL.pathExtension, "jpeg", "The file extension should match the MIME type.")
|
||||
#expect(mimeType(from: optimizedImageURL) == "image/jpeg", "Optimised HEICs should always be converted to JPEG for compatibility.")
|
||||
#expect(optimizedImageURL.pathExtension == "jpeg", "The file extension should match the MIME type.")
|
||||
|
||||
// Check optimised image info
|
||||
XCTAssertEqual(optimizedImageInfo.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(optimizedImageInfo.blurhash, "KGD]3ns:T00#kWxFb^s:xv")
|
||||
XCTAssertEqual(optimizedImageInfo.size ?? 0, 1_049_393, accuracy: 100)
|
||||
XCTAssertEqual(optimizedImageInfo.width, 1536)
|
||||
XCTAssertEqual(optimizedImageInfo.height, 2048)
|
||||
#expect(optimizedImageInfo.mimetype == "image/jpeg")
|
||||
#expect(optimizedImageInfo.blurhash == "KGD]3ns:T00#kWxFb^s:xv")
|
||||
#expect(isEqual(optimizedImageInfo.size ?? 0, 1_049_393, within: 100))
|
||||
#expect(optimizedImageInfo.width == 1536)
|
||||
#expect(optimizedImageInfo.height == 2048)
|
||||
}
|
||||
|
||||
func testGIFImageProcessing() async {
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "test_animated_image.gif", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
guard let originalSize = try? FileManager.default.sizeForItem(at: url), originalSize > 0 else {
|
||||
XCTFail("Failed fetching test asset's original size")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func gifImageProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "test_animated_image.gif", withExtension: nil), "Failed retrieving test asset")
|
||||
let originalSizeValue = try UInt64(FileManager.default.sizeForItem(at: url))
|
||||
let originalSize = try #require(originalSizeValue > 0 ? originalSizeValue : nil, "File size must be greater than zero")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(convertedImageURL, _, imageInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure the output file matches the image info.
|
||||
XCTAssertEqual(mimeType(from: convertedImageURL), "image/gif", "GIFs should always be sent as GIF to preserve the animation.")
|
||||
XCTAssertEqual(convertedImageURL.pathExtension, "gif", "The file extension should match the MIME type.")
|
||||
#expect(mimeType(from: convertedImageURL) == "image/gif", "GIFs should always be sent as GIF to preserve the animation.")
|
||||
#expect(convertedImageURL.pathExtension == "gif", "The file extension should match the MIME type.")
|
||||
|
||||
// Check resulting image info
|
||||
XCTAssertEqual(imageInfo.mimetype, "image/gif")
|
||||
XCTAssertEqual(imageInfo.blurhash, "KpRMPTj[_NxuaeRj%MofMx")
|
||||
XCTAssertEqual(imageInfo.size ?? 0, UInt64(originalSize), accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.width, 331)
|
||||
XCTAssertEqual(imageInfo.height, 472)
|
||||
#expect(imageInfo.mimetype == "image/gif")
|
||||
#expect(imageInfo.blurhash == "KpRMPTj[_NxuaeRj%MofMx")
|
||||
#expect(isEqual(imageInfo.size ?? 0, originalSize, within: 100))
|
||||
#expect(imageInfo.width == 331)
|
||||
#expect(imageInfo.height == 472)
|
||||
|
||||
XCTAssertNotNil(imageInfo.thumbnailInfo)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.size ?? 0, 34215, accuracy: 100)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.width, 331)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.height, 472)
|
||||
#expect(imageInfo.thumbnailInfo != nil)
|
||||
#expect(imageInfo.thumbnailInfo?.mimetype == "image/jpeg")
|
||||
#expect(isEqual(imageInfo.thumbnailInfo?.size ?? 0, 34215, within: 100))
|
||||
#expect(imageInfo.thumbnailInfo?.width == 331)
|
||||
#expect(imageInfo.thumbnailInfo?.height == 472)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
appSettings.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, _, optimizedImageInfo) = optimizedResult else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure the output file matches the image info.
|
||||
XCTAssertEqual(mimeType(from: optimizedImageURL), "image/gif", "GIFs should always be sent as GIF to preserve the animation.")
|
||||
XCTAssertEqual(optimizedImageURL.pathExtension, "gif", "The file extension should match the MIME type.")
|
||||
#expect(mimeType(from: optimizedImageURL) == "image/gif", "GIFs should always be sent as GIF to preserve the animation.")
|
||||
#expect(optimizedImageURL.pathExtension == "gif", "The file extension should match the MIME type.")
|
||||
|
||||
// Ensure optimised image is still the same as the original image.
|
||||
XCTAssertEqual(optimizedImageInfo.mimetype, "image/gif")
|
||||
XCTAssertEqual(optimizedImageInfo.blurhash, "KpRMPTj[_NxuaeRj%MofMx")
|
||||
XCTAssertEqual(optimizedImageInfo.size ?? 0, UInt64(originalSize), accuracy: 100)
|
||||
XCTAssertEqual(optimizedImageInfo.width, 331)
|
||||
XCTAssertEqual(optimizedImageInfo.height, 472)
|
||||
#expect(optimizedImageInfo.mimetype == "image/gif")
|
||||
#expect(optimizedImageInfo.blurhash == "KpRMPTj[_NxuaeRj%MofMx")
|
||||
#expect(isEqual(optimizedImageInfo.size ?? 0, originalSize, within: 100))
|
||||
#expect(optimizedImageInfo.width == 331)
|
||||
#expect(optimizedImageInfo.height == 472)
|
||||
}
|
||||
|
||||
func testRotatedImageProcessing() async {
|
||||
guard let url = Bundle(for: Self.self).url(forResource: "test_rotated_image.jpg", withExtension: nil) else {
|
||||
XCTFail("Failed retrieving test asset")
|
||||
return
|
||||
}
|
||||
@Test
|
||||
func rotatedImageProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "test_rotated_image.jpg", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
guard case let .success(result) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(convertedImageURL, thumbnailURL, imageInfo) = result else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
compare(originalImageAt: url, toConvertedImageAt: convertedImageURL, withThumbnailAt: thumbnailURL)
|
||||
try compare(originalImageAt: url, toConvertedImageAt: convertedImageURL, withThumbnailAt: thumbnailURL)
|
||||
|
||||
// Check resulting image info
|
||||
XCTAssertEqual(imageInfo.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(imageInfo.width, 2848)
|
||||
XCTAssertEqual(imageInfo.height, 4272)
|
||||
#expect(imageInfo.mimetype == "image/jpeg")
|
||||
#expect(imageInfo.width == 2848)
|
||||
#expect(imageInfo.height == 4272)
|
||||
|
||||
XCTAssertNotNil(imageInfo.thumbnailInfo)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.width, 533)
|
||||
XCTAssertEqual(imageInfo.thumbnailInfo?.height, 800)
|
||||
#expect(imageInfo.thumbnailInfo != nil)
|
||||
#expect(imageInfo.thumbnailInfo?.width == 533)
|
||||
#expect(imageInfo.thumbnailInfo?.height == 800)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
appSettings.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
|
||||
XCTFail("Failed processing asset")
|
||||
Issue.record("Failed processing asset")
|
||||
return
|
||||
}
|
||||
|
||||
compare(originalImageAt: url, toConvertedImageAt: optimizedImageURL, withThumbnailAt: thumbnailURL)
|
||||
try compare(originalImageAt: url, toConvertedImageAt: optimizedImageURL, withThumbnailAt: thumbnailURL)
|
||||
|
||||
// Check optimised image info
|
||||
XCTAssertEqual(optimizedImageInfo.mimetype, "image/jpeg")
|
||||
XCTAssertEqual(optimizedImageInfo.width, 1365)
|
||||
XCTAssertEqual(optimizedImageInfo.height, 2048)
|
||||
#expect(optimizedImageInfo.mimetype == "image/jpeg")
|
||||
#expect(optimizedImageInfo.width == 1365)
|
||||
#expect(optimizedImageInfo.height == 2048)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func compare(originalImageAt originalImageURL: URL, toConvertedImageAt convertedImageURL: URL, withThumbnailAt thumbnailURL: URL) {
|
||||
private func isEqual<N: UnsignedInteger>(_ lhs: N, _ rhs: N, within tolerance: N) -> Bool {
|
||||
isEqual(Double(lhs), Double(rhs), within: Double(tolerance))
|
||||
}
|
||||
|
||||
private func isEqual<N: SignedNumeric & Comparable>(_ lhs: N, _ rhs: N, within tolerance: N) -> Bool {
|
||||
abs(lhs - rhs) <= tolerance
|
||||
}
|
||||
|
||||
private func compare(originalImageAt originalImageURL: URL, toConvertedImageAt convertedImageURL: URL, withThumbnailAt thumbnailURL: URL) throws {
|
||||
guard let originalImageData = try? Data(contentsOf: originalImageURL),
|
||||
let originalImage = UIImage(data: originalImageData),
|
||||
let convertedImageData = try? Data(contentsOf: convertedImageURL),
|
||||
@@ -476,53 +454,41 @@ final class MediaUploadingPreprocessorTests: XCTestCase {
|
||||
|
||||
if appSettings.optimizeMediaUploads {
|
||||
// Check that new image has been scaled within the requirements for an optimised image
|
||||
XCTAssert(convertedImage.size.width <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize)
|
||||
XCTAssert(convertedImage.size.height <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize)
|
||||
#expect(convertedImage.size.width <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize)
|
||||
#expect(convertedImage.size.height <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize)
|
||||
} else {
|
||||
// Check that the file name is preserved
|
||||
XCTAssertEqual(originalImageURL.lastPathComponent, convertedImageURL.lastPathComponent)
|
||||
#expect(originalImageURL.lastPathComponent == convertedImageURL.lastPathComponent)
|
||||
// Check that new image is the same size as the original one
|
||||
XCTAssertEqual(originalImage.size, convertedImage.size)
|
||||
#expect(originalImage.size == convertedImage.size)
|
||||
}
|
||||
|
||||
// Check that the GPS data has been stripped
|
||||
let originalMetadata = metadata(from: originalImageData)
|
||||
XCTAssertNotNil(originalMetadata.value(forKeyPath: "\(kCGImagePropertyGPSDictionary)"))
|
||||
let originalMetadata = try metadata(from: originalImageData)
|
||||
#expect(originalMetadata.value(forKeyPath: "\(kCGImagePropertyGPSDictionary)") != nil)
|
||||
|
||||
let convertedMetadata = metadata(from: convertedImageData)
|
||||
XCTAssertNil(convertedMetadata.value(forKeyPath: "\(kCGImagePropertyGPSDictionary)"))
|
||||
let convertedMetadata = try metadata(from: convertedImageData)
|
||||
#expect(convertedMetadata.value(forKeyPath: "\(kCGImagePropertyGPSDictionary)") == nil)
|
||||
|
||||
// Check that the thumbnail is generated correctly
|
||||
guard let thumbnailData = try? Data(contentsOf: thumbnailURL),
|
||||
let thumbnail = UIImage(data: thumbnailData) else {
|
||||
XCTFail("Invalid thumbnail")
|
||||
return
|
||||
}
|
||||
let thumbnailData = try Data(contentsOf: thumbnailURL)
|
||||
let thumbnail = try #require(UIImage(data: thumbnailData), "Invalid thumbnail")
|
||||
|
||||
if thumbnail.size.width > thumbnail.size.height {
|
||||
XCTAssert(thumbnail.size.width <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.width)
|
||||
XCTAssert(thumbnail.size.height <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.height)
|
||||
#expect(thumbnail.size.width <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.width)
|
||||
#expect(thumbnail.size.height <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.height)
|
||||
} else {
|
||||
XCTAssert(thumbnail.size.width <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.height)
|
||||
XCTAssert(thumbnail.size.height <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.width)
|
||||
#expect(thumbnail.size.width <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.height)
|
||||
#expect(thumbnail.size.height <= MediaUploadingPreprocessor.Constants.maximumThumbnailSize.width)
|
||||
}
|
||||
|
||||
let thumbnailMetadata = metadata(from: thumbnailData)
|
||||
XCTAssertNil(thumbnailMetadata.value(forKeyPath: "\(kCGImagePropertyGPSDictionary)"))
|
||||
let thumbnailMetadata = try metadata(from: thumbnailData)
|
||||
#expect(thumbnailMetadata.value(forKeyPath: "\(kCGImagePropertyGPSDictionary)") == nil)
|
||||
}
|
||||
|
||||
private func metadata(from imageData: Data) -> NSDictionary {
|
||||
guard let imageSource = CGImageSourceCreateWithData(imageData as NSData, nil) else {
|
||||
XCTFail("Invalid asset")
|
||||
return [:]
|
||||
}
|
||||
|
||||
guard let convertedMetadata: NSDictionary = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) else {
|
||||
XCTFail("Test asset is expected to contain metadata")
|
||||
return [:]
|
||||
}
|
||||
|
||||
return convertedMetadata
|
||||
private func metadata(from imageData: Data) throws -> NSDictionary {
|
||||
let imageSource = try #require(CGImageSourceCreateWithData(imageData as NSData, nil), "Invalid asset")
|
||||
return try #require(CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as NSDictionary?, "Test asset is expected to contain metadata")
|
||||
}
|
||||
|
||||
private func mimeType(from url: URL) -> String? {
|
||||
@@ -530,7 +496,7 @@ final class MediaUploadingPreprocessorTests: XCTestCase {
|
||||
let typeIdentifier = CGImageSourceGetType(imageSource),
|
||||
let type = UTType(typeIdentifier as String),
|
||||
let mimeType = type.preferredMIMEType else {
|
||||
XCTFail("Failed to get mimetype from URL.")
|
||||
Issue.record("Failed to get mimetype from URL.")
|
||||
return nil
|
||||
}
|
||||
return mimeType
|
||||
|
||||
Reference in New Issue
Block a user