Tests/Unit/CloudKitErrorClassifierTests.swift (4310B)
1import CloudKit
2import Foundation
3import Testing
4
5#if os(macOS)
6@testable import Listless
7#else
8@testable import Listless_iOS
9#endif
10
11@Suite("CloudKitErrorClassifier")
12struct CloudKitErrorClassifierTests {
13
14
15
16 @Test(
17 "Network and server errors are transient",
18 arguments: [
19 CKError.Code.networkUnavailable,
20 CKError.Code.networkFailure,
21 CKError.Code.serviceUnavailable,
22 CKError.Code.requestRateLimited,
23 CKError.Code.zoneBusy,
24 CKError.Code.serverResponseLost,
25 CKError.Code.operationCancelled,
26 ]
27 )
28 func transientErrors(code: CKError.Code) {
29 let error = CKError(code)
30 let issue = CloudKitErrorClassifier.classify(error)
31
32 guard case .transient(let message) = issue else {
33 Issue.record("Expected .transient, got \(issue)")
34 return
35 }
36 #expect(message.contains("retry"))
37 }
38
39
40
41 @Test(
42 "First-launch errors are deferred",
43 arguments: [
44 CKError.Code.accountTemporarilyUnavailable,
45 CKError.Code.zoneNotFound,
46 CKError.Code.userDeletedZone,
47 ]
48 )
49 func deferredErrors(code: CKError.Code) {
50 let error = CKError(code)
51 let issue = CloudKitErrorClassifier.classify(error)
52
53 guard case .deferred(let message) = issue else {
54 Issue.record("Expected .deferred, got \(issue)")
55 return
56 }
57 #expect(message.contains("retry"))
58 }
59
60
61
62 @Test("Not authenticated is transient with sign-in message")
63 func notAuthenticated() {
64 let error = CKError(.notAuthenticated)
65 let issue = CloudKitErrorClassifier.classify(error)
66
67 guard case .transient(let message) = issue else {
68 Issue.record("Expected .transient, got \(issue)")
69 return
70 }
71 #expect(message.contains("Sign in"))
72 }
73
74 @Test("Quota exceeded is transient with storage message")
75 func quotaExceeded() {
76 let error = CKError(.quotaExceeded)
77 let issue = CloudKitErrorClassifier.classify(error)
78
79 guard case .transient(let message) = issue else {
80 Issue.record("Expected .transient, got \(issue)")
81 return
82 }
83 #expect(message.contains("storage full"))
84 }
85
86 @Test(
87 "Permission errors are transient with unavailable message",
88 arguments: [
89 CKError.Code.permissionFailure,
90 CKError.Code.badContainer,
91 CKError.Code.missingEntitlement,
92 ]
93 )
94 func permissionErrors(code: CKError.Code) {
95 let error = CKError(code)
96 let issue = CloudKitErrorClassifier.classify(error)
97
98 guard case .transient(let message) = issue else {
99 Issue.record("Expected .transient, got \(issue)")
100 return
101 }
102 #expect(message.contains("unavailable"))
103 }
104
105
106
107 @Test("Unknown CKError code is deferred")
108 func unknownCKError() {
109 let error = CKError(.internalError)
110 let issue = CloudKitErrorClassifier.classify(error)
111
112 guard case .deferred(let message) = issue else {
113 Issue.record("Expected .deferred, got \(issue)")
114 return
115 }
116 #expect(message.contains("retry"))
117 }
118
119
120
121 @Test("Core Data error is transient")
122 func coreDataError() {
123 let error = NSError(domain: NSCocoaErrorDomain, code: 1570, userInfo: nil)
124 let issue = CloudKitErrorClassifier.classify(error)
125
126 guard case .transient(let message) = issue else {
127 Issue.record("Expected .transient, got \(issue)")
128 return
129 }
130 #expect(message.contains("retry"))
131 }
132
133 @Test("Unknown domain error is transient")
134 func unknownDomainError() {
135 let error = NSError(domain: "com.example.unknown", code: 42, userInfo: nil)
136 let issue = CloudKitErrorClassifier.classify(error)
137
138 guard case .transient(let message) = issue else {
139 Issue.record("Expected .transient, got \(issue)")
140 return
141 }
142 #expect(message.contains("retry"))
143 }
144}