@@ -144,4 +144,59 @@ struct PushOutcomeTests {
144144 #expect( outcome. failures [ rejected] != nil )
145145 #expect( !outcome. didDelete ( rejected) )
146146 }
147+
148+ @Test ( " A push that stopped after saving some records carries those saves with the error " )
149+ func interruptionKeepsWhatWasSaved( ) throws {
150+ var completed = PushOutcome ( )
151+ let saved = makeRecord ( " Connection_Saved " )
152+ completed. recordSave ( saved)
153+
154+ let error = SyncPushInterruption . after ( completed, failingWith: CKError ( . networkFailure) )
155+
156+ let interruption = try #require( error as? SyncPushInterruption )
157+ #expect( interruption. completed. didSave ( saved. recordID) )
158+ #expect( ( interruption. cause as? CKError ) ? . code == . networkFailure)
159+ }
160+
161+ @Test ( " A push that stopped before saving anything throws its own error unchanged " )
162+ func interruptionWithoutProgressIsTheRawError( ) {
163+ let error = SyncPushInterruption . after ( PushOutcome ( ) , failingWith: CKError ( . networkFailure) )
164+
165+ #expect( !( error is SyncPushInterruption ) )
166+ #expect( ( error as? CKError ) ? . code == . networkFailure)
167+ }
168+
169+ @Test ( " An interruption from a later batch keeps the saves of the batches before it " )
170+ func nestedInterruptionsMerge( ) throws {
171+ var earlier = PushOutcome ( )
172+ let first = makeRecord ( " Connection_First " )
173+ earlier. recordSave ( first)
174+ var later = PushOutcome ( )
175+ let second = makeRecord ( " Connection_Second " )
176+ later. recordSave ( second)
177+ let inner = SyncPushInterruption ( completed: later, cause: CKError ( . networkFailure) )
178+
179+ let error = SyncPushInterruption . after ( earlier, failingWith: inner)
180+
181+ let interruption = try #require( error as? SyncPushInterruption )
182+ #expect( interruption. completed. didSave ( first. recordID) )
183+ #expect( interruption. completed. didSave ( second. recordID) )
184+ }
185+
186+ @Test ( " An interrupted push reports the error that stopped it " )
187+ func interruptionMapsToItsCause( ) {
188+ let interruption = SyncPushInterruption ( completed: PushOutcome ( ) , cause: CKError ( . networkFailure) )
189+
190+ #expect( SyncError . from ( interruption) == . networkUnavailable)
191+ }
192+
193+ @Test ( " An outcome with nothing saved, deleted or rejected is empty " )
194+ func emptyOutcome( ) {
195+ var outcome = PushOutcome ( )
196+ #expect( outcome. isEmpty)
197+
198+ outcome. recordDeletion ( recordID ( " Connection_Gone " ) )
199+
200+ #expect( !outcome. isEmpty)
201+ }
147202}
0 commit comments