RadrootsAppleMediaPickerTests.swift (3458B)
1 import Foundation 2 import Testing 3 @testable import RadrootsKit 4 5 @Test func captureAsyncSupportRunsCleanupOnTimeout() async throws { 6 let probe = RadrootsCaptureCleanupProbe() 7 8 await #expect(throws: RadrootsCaptureIntakeError.transientFailure("timeout")) { 9 let _: Int = try await RadrootsAppleCaptureAsyncSupport.awaitMainActorCallback( 10 timeout: 0.001, 11 timeoutMessage: "timeout" 12 ) { _, setCleanup in 13 setCleanup { 14 probe.recordCleanup() 15 } 16 } 17 } 18 19 try await Task.sleep(nanoseconds: 20_000_000) 20 #expect(await probe.cleanupCount == 1) 21 } 22 23 @Test func captureAsyncSupportRunsCleanupOnceOnDoubleCompletion() async throws { 24 let probe = RadrootsCaptureCleanupProbe() 25 26 let value: Int = try await RadrootsAppleCaptureAsyncSupport.awaitMainActorCallback( 27 timeout: 10, 28 timeoutMessage: "timeout" 29 ) { completion, setCleanup in 30 setCleanup { 31 probe.recordCleanup() 32 } 33 completion(.success(7)) 34 completion(.success(8)) 35 } 36 37 try await Task.sleep(nanoseconds: 20_000_000) 38 #expect(value == 7) 39 #expect(await probe.cleanupCount == 1) 40 } 41 42 @Test func captureAsyncSupportRunsCleanupOnTaskCancellation() async throws { 43 let probe = RadrootsCaptureCleanupProbe() 44 let task = Task<Int, any Error> { 45 try await RadrootsAppleCaptureAsyncSupport.awaitMainActorCallback( 46 timeout: 10, 47 timeoutMessage: "timeout" 48 ) { _, setCleanup in 49 setCleanup { 50 probe.recordCleanup() 51 } 52 } 53 } 54 55 task.cancel() 56 57 await #expect(throws: RadrootsCaptureIntakeError.userCancelled("capture request was cancelled")) { 58 _ = try await task.value 59 } 60 try await Task.sleep(nanoseconds: 20_000_000) 61 #expect(await probe.cleanupCount == 1) 62 } 63 64 #if !canImport(UIKit) 65 @Test func appleMediaPickerReportsUnavailableWithoutUIKit() async throws { 66 let picker = try RadrootsAppleMediaPicker(fileAccess: mediaPickerTestFileAccess()) 67 let support = try await picker.currentSupport() 68 69 #expect(!support.importAvailable) 70 #expect(!support.cameraCaptureAvailable) 71 #expect(support.supportedImportKinds.isEmpty) 72 #expect(support.supportedCaptureKinds.isEmpty) 73 74 await #expect(throws: RadrootsCaptureIntakeError.unavailable("media import is unavailable")) { 75 _ = try await picker.importMedia(try RadrootsMediaImportRequest()) 76 } 77 await #expect(throws: RadrootsCaptureIntakeError.unavailable("camera photo capture is unavailable")) { 78 _ = try await picker.captureMedia(try RadrootsMediaCaptureRequest()) 79 } 80 } 81 #endif 82 83 private func mediaPickerTestFileAccess() throws -> RadrootsAppleFileAccess { 84 let root = FileManager.default.temporaryDirectory 85 .appendingPathComponent("radroots-media-picker-\(UUID().uuidString)", isDirectory: true) 86 let roots = try RadrootsAppleFileRoots( 87 appIdentifier: "org.radroots.media-picker-test", 88 dataRoot: root.appendingPathComponent("data", isDirectory: true), 89 cacheRoot: root.appendingPathComponent("cache", isDirectory: true), 90 temporaryRoot: root.appendingPathComponent("temporary", isDirectory: true) 91 ) 92 return RadrootsAppleFileAccess(roots: roots) 93 } 94 95 @MainActor 96 private final class RadrootsCaptureCleanupProbe { 97 private(set) var cleanupCount = 0 98 99 func recordCleanup() { 100 cleanupCount += 1 101 } 102 }