-
Notifications
You must be signed in to change notification settings - Fork 110
Expand file tree
/
Copy pathMockCloudContainer.swift
More file actions
130 lines (114 loc) · 4.24 KB
/
MockCloudContainer.swift
File metadata and controls
130 lines (114 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#if canImport(CloudKit)
import CloudKit
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
package final class MockCloudContainer: CloudContainer {
package let _accountStatus: LockIsolated<CKAccountStatus>
package let containerIdentifier: String?
package let privateCloudDatabase: MockCloudDatabase
package let sharedCloudDatabase: MockCloudDatabase
package init(
accountStatus: CKAccountStatus = .available,
containerIdentifier: String?,
privateCloudDatabase: MockCloudDatabase,
sharedCloudDatabase: MockCloudDatabase
) {
self._accountStatus = LockIsolated(accountStatus)
self.containerIdentifier = containerIdentifier
self.privateCloudDatabase = privateCloudDatabase
self.sharedCloudDatabase = sharedCloudDatabase
guard let containerIdentifier else { return }
@Dependency(\.mockCloudContainers) var mockCloudContainers
mockCloudContainers.withValue { storage in
storage[containerIdentifier] = self
}
}
package func accountStatus() -> CKAccountStatus {
_accountStatus.withValue(\.self)
}
package var rawValue: CKContainer {
fatalError("This should never be called in tests.")
}
package func accountStatus() async throws -> CKAccountStatus {
_accountStatus.withValue { $0 }
}
package func shareMetadata(
for share: CKShare,
shouldFetchRootRecord: Bool
) async throws -> ShareMetadata {
let database =
share.recordID.zoneID.ownerName == CKCurrentUserDefaultName
? privateCloudDatabase
: sharedCloudDatabase
let rootRecord: CKRecord? = database.storage.withValue {
$0[share.recordID.zoneID]?.records.values.first { record in
record.share?.recordID == share.recordID
}
}
return ShareMetadata(
containerIdentifier: containerIdentifier!,
hierarchicalRootRecordID: rootRecord?.recordID,
rootRecord: shouldFetchRootRecord ? rootRecord : nil,
share: share
)
}
package func accept(_ metadata: ShareMetadata) async throws -> CKShare {
guard let rootRecord = metadata.rootRecord
else {
fatalError("Must provide root record in mock shares during tests.")
}
let (saveResults, _) = try sharedCloudDatabase.modifyRecords(
saving: [metadata.share, rootRecord]
)
try saveResults.values.forEach { _ = try $0.get() }
return metadata.share
}
package static func createContainer(identifier containerIdentifier: String)
-> MockCloudContainer
{
@Dependency(\.mockCloudContainers) var mockCloudContainers
return mockCloudContainers.withValue { storage in
let container: MockCloudContainer
if let existingContainer = storage[containerIdentifier] {
return existingContainer
} else {
container = MockCloudContainer(
accountStatus: .available,
containerIdentifier: containerIdentifier,
privateCloudDatabase: MockCloudDatabase(databaseScope: .private),
sharedCloudDatabase: MockCloudDatabase(databaseScope: .shared)
)
container.privateCloudDatabase.set(container: container)
container.sharedCloudDatabase.set(container: container)
}
storage[containerIdentifier] = container
return container
}
}
package static func == (lhs: MockCloudContainer, rhs: MockCloudContainer) -> Bool {
lhs === rhs
}
package func hash(into hasher: inout Hasher) {
hasher.combine(ObjectIdentifier(self))
}
}
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
private enum MockCloudContainersKey: DependencyKey {
static var liveValue: LockIsolated<[String: MockCloudContainer]> {
LockIsolated<[String: MockCloudContainer]>([:])
}
static var testValue: LockIsolated<[String: MockCloudContainer]> {
LockIsolated<[String: MockCloudContainer]>([:])
}
}
extension DependencyValues {
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
fileprivate var mockCloudContainers: LockIsolated<[String: MockCloudContainer]> {
get {
self[MockCloudContainersKey.self]
}
set {
self[MockCloudContainersKey.self] = newValue
}
}
}
#endif