RadrootsBackgroundTaskTests.swift (4521B)
1 import Foundation 2 import Testing 3 @testable import RadrootsKit 4 5 @Test func backgroundTaskIdentifierNormalizesAndRejectsUnsafeValues() throws { 6 let identifier = try RadrootsBackgroundTaskIdentifier(" ORG.RADROOTS.FIELD-IOS.refresh ") 7 8 #expect(identifier.rawValue == "org.radroots.field-ios.refresh") 9 10 #expect(throws: RadrootsBackgroundTaskError.invalidRequest("background task identifier must not be empty")) { 11 _ = try RadrootsBackgroundTaskIdentifier(" ") 12 } 13 #expect(throws: RadrootsBackgroundTaskError.invalidRequest("background task identifier must use lowercase safe identifier characters")) { 14 _ = try RadrootsBackgroundTaskIdentifier(".org.radroots") 15 } 16 #expect(throws: RadrootsBackgroundTaskError.invalidRequest("background task identifier cannot contain empty path components")) { 17 _ = try RadrootsBackgroundTaskIdentifier("org.radroots..refresh") 18 } 19 } 20 21 @Test func backgroundTaskRequestValidatesKindSpecificOptions() throws { 22 let refresh = try RadrootsBackgroundTaskRequest( 23 identifier: "org.radroots.field-ios.background.refresh", 24 kind: .appRefresh, 25 earliestBeginDate: Date(timeIntervalSince1970: 10) 26 ) 27 28 #expect(refresh.kind == .appRefresh) 29 #expect(refresh.earliestBeginDate == Date(timeIntervalSince1970: 10)) 30 #expect(!refresh.requiresNetworkConnectivity) 31 32 let processing = try RadrootsBackgroundTaskRequest( 33 identifier: "org.radroots.field-ios.background.processing", 34 kind: .processing, 35 requiresNetworkConnectivity: true, 36 requiresExternalPower: true 37 ) 38 39 #expect(processing.kind == .processing) 40 #expect(processing.requiresNetworkConnectivity) 41 #expect(processing.requiresExternalPower) 42 43 #expect(throws: RadrootsBackgroundTaskError.invalidRequest("app refresh tasks cannot require network connectivity or external power")) { 44 _ = try RadrootsBackgroundTaskRequest( 45 identifier: "org.radroots.field-ios.background.refresh", 46 kind: .appRefresh, 47 requiresNetworkConnectivity: true 48 ) 49 } 50 #expect(throws: RadrootsBackgroundTaskError.invalidRequest("background task earliest begin date must be finite")) { 51 _ = try RadrootsBackgroundTaskRequest( 52 identifier: "org.radroots.field-ios.background.refresh", 53 kind: .appRefresh, 54 earliestBeginDate: Date(timeIntervalSinceReferenceDate: .infinity) 55 ) 56 } 57 } 58 59 @Test func backgroundTaskSnapshotPreservesRequestValues() throws { 60 let request = try RadrootsBackgroundTaskRequest( 61 identifier: "org.radroots.field-ios.background.processing", 62 kind: .processing, 63 earliestBeginDate: Date(timeIntervalSince1970: 5), 64 requiresNetworkConnectivity: true 65 ) 66 let snapshot = try RadrootsBackgroundTaskSnapshot( 67 request: request, 68 submittedAt: Date(timeIntervalSince1970: 7) 69 ) 70 71 #expect(snapshot.identifier == request.identifier) 72 #expect(snapshot.kind == .processing) 73 #expect(snapshot.earliestBeginDate == Date(timeIntervalSince1970: 5)) 74 #expect(snapshot.submittedAt == Date(timeIntervalSince1970: 7)) 75 #expect(snapshot.requiresNetworkConnectivity) 76 #expect(!snapshot.requiresExternalPower) 77 78 #expect(throws: RadrootsBackgroundTaskError.invalidRequest("background task submitted date must be finite")) { 79 _ = try RadrootsBackgroundTaskSnapshot( 80 request: request, 81 submittedAt: Date(timeIntervalSinceReferenceDate: .infinity) 82 ) 83 } 84 } 85 86 @Test func unavailableBackgroundTaskSchedulerThrowsTypedErrors() async throws { 87 let scheduler = RadrootsUnavailableBackgroundTaskScheduler(reason: "missing background support") 88 let identifier = try RadrootsBackgroundTaskIdentifier("org.radroots.field-ios.background.refresh") 89 let request = try RadrootsBackgroundTaskRequest(identifier: identifier, kind: .appRefresh) 90 91 await #expect(throws: RadrootsBackgroundTaskError.unavailable("missing background support")) { 92 _ = try await scheduler.submit(request) 93 } 94 await #expect(throws: RadrootsBackgroundTaskError.unavailable("missing background support")) { 95 try await scheduler.cancel(identifier) 96 } 97 await #expect(throws: RadrootsBackgroundTaskError.unavailable("missing background support")) { 98 try await scheduler.cancelAll() 99 } 100 await #expect(throws: RadrootsBackgroundTaskError.unavailable("missing background support")) { 101 _ = try await scheduler.pendingTasks() 102 } 103 }