FBSDKShareKit/FBSDKShareKitTests/Content/MediaLibrary/PHImageManagerSearchingTests.swift (162 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ @testable import FBSDKShareKit import Photos import XCTest final class PHImageManagerSearchingTests: XCTestCase { // swiftlint:disable implicitly_unwrapped_optional var imageManager: TestPHImageManager! var asset: PHAsset! // swiftlint:enable implicitly_unwrapped_optional override func setUp() { super.setUp() imageManager = TestPHImageManager() asset = PHAsset() } override func tearDown() { imageManager = nil asset = nil super.tearDown() } // MARK: - Requesting images func testFindImageRequest() throws { _ = try? imageManager.fb_findImage(for: asset) XCTAssertIdentical(imageManager.requestImageAsset, asset, .forwardsCallToRequestImage) XCTAssertEqual(imageManager.requestImageTargetSize, PHImageManagerMaximumSize, .targetSizeIsMaximum) XCTAssertEqual(imageManager.requestImageContentMode, .default, .contentModeIsDefault) let options = try XCTUnwrap(imageManager.requestImageOptions, .forwardsCallToRequestImage) XCTAssertEqual(options.resizeMode, .exact, .resizeModeIsExact) XCTAssertEqual(options.deliveryMode, .highQualityFormat, .deliveryModeIsHighQualityFormat) XCTAssertTrue(options.isSynchronous, .imageRequestIsSynchronous) } func testFindImageFailure() { XCTAssertThrowsError( try imageManager.fb_findImage(for: asset), .throwsErrorWhenImageNotAvailable ) { anyError in guard let error = anyError as? PHImageManager.MediaLibrarySearchError else { return XCTFail(.throwsErrorWhenImageNotAvailable) } XCTAssertIdentical(error.asset, asset, .throwsErrorWhenImageNotAvailable) } } func testFindImageSuccess() throws { let expectedImage = UIImage() imageManager.stubbedRequestImageImage = expectedImage var image: UIImage? XCTAssertNoThrow( image = try imageManager.fb_findImage(for: asset), .returnsImageWhenAvailable ) XCTAssertIdentical(image, expectedImage, .returnsImageWhenAvailable) } // MARK: - Getting video URLs func testGetVideoURLRequest() throws { _ = try? imageManager.fb_getVideoURL(for: asset) XCTAssertIdentical(imageManager.requestAVAssetAsset, asset, .forwardsCallToRequestAVAsset) let options = try XCTUnwrap(imageManager.requestAVAssetOptions, .forwardsCallToRequestAVAsset) XCTAssertEqual(options.version, .current, .versionIsCurrent) XCTAssertEqual(options.deliveryMode, .automatic, .deliveryModeIsAutomatic) XCTAssertTrue(options.isNetworkAccessAllowed, .networkAccessAllowed) } func testGetVideoURLAssetFailure() { asset = .withLocalIdentifier XCTAssertThrowsError( try imageManager.fb_getVideoURL(for: asset), .throwsErrorWhenVideoURLAssetNotAvailable ) { anyError in guard let error = anyError as? PHImageManager.MediaLibrarySearchError else { return XCTFail(.throwsErrorWhenVideoURLAssetNotAvailable) } XCTAssertIdentical(error.asset, asset, .throwsErrorWhenVideoURLAssetNotAvailable) } } func testGetVideoURLFileFailure() { asset = .withLocalIdentifier imageManager.stubbedGetVideoURLAsset = AVURLAsset.remote XCTAssertThrowsError( try imageManager.fb_getVideoURL(for: asset), .throwsErrorWhenVideoURLAssetNotAvailable ) { anyError in guard let error = anyError as? PHImageManager.MediaLibrarySearchError else { return XCTFail(.throwsErrorWhenVideoURLAssetNotAvailable) } XCTAssertIdentical(error.asset, asset, .throwsErrorWhenVideoURLAssetNotAvailable) } } func testGetVideoURLIdentifierFailure() { asset = .withoutLocalIdentifier imageManager.stubbedGetVideoURLAsset = AVURLAsset.local XCTAssertThrowsError( try imageManager.fb_getVideoURL(for: asset), .throwsErrorWhenVideoURLIdentifierNotAvailable ) { anyError in guard let error = anyError as? PHImageManager.MediaLibrarySearchError else { return XCTFail(.throwsErrorWhenVideoURLIdentifierNotAvailable) } XCTAssertIdentical(error.asset, asset, .throwsErrorWhenVideoURLIdentifierNotAvailable) } } func testGetVideoURLSuccess() throws { asset = .withLocalIdentifier imageManager.stubbedGetVideoURLAsset = AVURLAsset.local var url: URL? XCTAssertNoThrow( url = try imageManager.fb_getVideoURL(for: asset), .returnsVideoURLWhenAvailable ) let expectedURL = """ assets-library://asset/asset.\(String.urlAssetPathExtension)?id=\(String.uuid)&ext=\(String.urlAssetPathExtension) """ XCTAssertEqual(url?.absoluteString, expectedURL, .returnsVideoURLWhenAvailable) } } // MARK: - Assumptions fileprivate extension String { static let forwardsCallToRequestImage = """ A PHImageManager should forward image-finding requests to its image request method """ static let targetSizeIsMaximum = "The maximum image size should be requested" static let contentModeIsDefault = "The default content mode should be requested" static let resizeModeIsExact = "The exact resize mode should be requested" static let deliveryModeIsHighQualityFormat = "The high quality format delivery mode should be requested" static let imageRequestIsSynchronous = "Image request calls should be synchronous" static let throwsErrorWhenImageNotAvailable = "An error should be thrown when an image is not available for an asset" static let returnsImageWhenAvailable = "An asset's image should be returned when available" static let forwardsCallToRequestAVAsset = """ A PHImageManager should forward video URL requests to its video asset request method """ static let versionIsCurrent = "The version should be current" static let deliveryModeIsAutomatic = "The delivery mode should be automatic" static let networkAccessAllowed = "Network access should be allowed" static let throwsErrorWhenVideoURLAssetNotAvailable = """ An error should be thrown when a URL asset is not available for a video asset """ static let throwsErrorWhenVideoURLFileURLNotAvailable = """ An error should be thrown when a file URL is not available for a video asset """ static let throwsErrorWhenVideoURLIdentifierNotAvailable = """ An error should be thrown when a local identifier is not available for a video asset """ static let returnsVideoURLWhenAvailable = "A URL should be returned when available for a video asset" } // MARK: - Test Values fileprivate extension String { static let uuid = UUID().uuidString static let localIdentifier = "\(uuid)/more-stuff" static let urlAssetPathExtension = "ext" static let urlAssetURL = "file:///somewhere/over.\(urlAssetPathExtension)" } fileprivate extension URL { // swiftlint:disable force_unwrapping static let video = URL(string: "https://facebook.com")! static let remote = URL(string: "https://facebook.com")! static let local = URL(string: "file:///local/video.\(String.urlAssetPathExtension)")! // swiftlint:enable force_unwrapping } fileprivate extension AVURLAsset { static let remote = AVURLAsset(url: .remote) static let local = AVURLAsset(url: .local) } fileprivate extension PHAsset { static let withLocalIdentifier: PHAsset = { let asset = TestPHAsset() asset.stubbedLocalIdentifier = .localIdentifier return asset }() static let withoutLocalIdentifier: PHAsset = { let asset = TestPHAsset() asset.stubbedLocalIdentifier = "" return asset }() }