@@ -3,6 +3,8 @@ import XCTest
33import Foundation
44@testable import WooCommerce
55
6+ import Combine
7+
68/// Tests cases for `PublishSubject`
79///
810final class PublishSubjectTests : XCTestCase {
@@ -110,4 +112,152 @@ final class PublishSubjectTests: XCTestCase {
110112 // Then
111113 XCTAssertEqual ( emittedValues, [ " dicta " ] )
112114 }
115+
116+ // MARK: - Proof of Compatibility with Combine's PassthroughSubject
117+
118+ func testCombinePassthroughSubjectEmitsValuesToAnObserver( ) throws {
119+ guard #available( iOS 13 . 0 , * ) else {
120+ try XCTSkipIf ( true , " This test is for iOS 13.0+ only " )
121+ return
122+ }
123+
124+ // Given
125+ let subject = PassthroughSubject < String , Error > ( )
126+ var disposeBag = Set < AnyCancellable > ( )
127+
128+ var emittedValues = [ String] ( )
129+ subject. sink ( receiveCompletion: { _ in
130+ // noop
131+ } ) { value in
132+ emittedValues. append ( value)
133+ } . store ( in: & disposeBag)
134+
135+ // When
136+ subject. send ( " dicta " )
137+
138+ // Then
139+ XCTAssertEqual ( emittedValues, [ " dicta " ] )
140+ }
141+
142+ func testCombinePassthroughSubjectContinuouslyEmitsValuesToAnObserver( ) throws {
143+ guard #available( iOS 13 . 0 , * ) else {
144+ try XCTSkipIf ( true , " This test is for iOS 13.0+ only " )
145+ return
146+ }
147+
148+ // Given
149+ let subject = PassthroughSubject < String , Error > ( )
150+ var disposeBag = Set < AnyCancellable > ( )
151+
152+ var emittedValues = [ String] ( )
153+ subject. sink ( receiveCompletion: { _ in
154+ // noop
155+ } ) { value in
156+ emittedValues. append ( value)
157+ } . store ( in: & disposeBag)
158+
159+ // When
160+ subject. send ( " dicta " )
161+ subject. send ( " amet " )
162+ subject. send ( " dolor " )
163+
164+ // Then
165+ XCTAssertEqual ( emittedValues, [ " dicta " , " amet " , " dolor " ] )
166+ }
167+
168+ func testCombinePassthroughSubjectDoesNotEmitValuesBeforeTheSubscription( ) throws {
169+ guard #available( iOS 13 . 0 , * ) else {
170+ try XCTSkipIf ( true , " This test is for iOS 13.0+ only " )
171+ return
172+ }
173+
174+ // Given
175+ let subject = PassthroughSubject < String , Error > ( )
176+ var disposeBag = Set < AnyCancellable > ( )
177+
178+ var emittedValues = [ String] ( )
179+
180+ // When
181+ // These are not emitted because there's no observer yet
182+ subject. send ( " dicta " )
183+ subject. send ( " amet " )
184+
185+ // Add the observer
186+ subject. sink ( receiveCompletion: { _ in
187+ // noop
188+ } ) { value in
189+ emittedValues. append ( value)
190+ } . store ( in: & disposeBag)
191+
192+ // This will be emitted to the observer
193+ subject. send ( " dolor " )
194+
195+ // Then
196+ XCTAssertEqual ( emittedValues, [ " dolor " ] )
197+ }
198+
199+ func testCombinePassthroughSubjectEmitsValuesToAllObservers( ) throws {
200+ guard #available( iOS 13 . 0 , * ) else {
201+ try XCTSkipIf ( true , " This test is for iOS 13.0+ only " )
202+ return
203+ }
204+
205+ // Given
206+ let subject = PassthroughSubject < String , Error > ( )
207+ var disposeBag = Set < AnyCancellable > ( )
208+
209+ var emittedValues = [ String] ( )
210+
211+ // First observer
212+ subject. sink ( receiveCompletion: { _ in
213+ // noop
214+ } ) { value in
215+ emittedValues. append ( value)
216+ } . store ( in: & disposeBag)
217+
218+ // Second observer
219+ subject. sink ( receiveCompletion: { _ in
220+ // noop
221+ } ) { value in
222+ emittedValues. append ( value)
223+ } . store ( in: & disposeBag)
224+
225+ // When
226+ subject. send ( " dicta " )
227+ subject. send ( " amet " )
228+
229+ // Then
230+ // We'll receive two values for each observer
231+ XCTAssertEqual ( emittedValues, [ " dicta " , " dicta " , " amet " , " amet " ] )
232+ }
233+
234+ func testCombinePassthroughSubjectDoesNotEmitValuesToCancelledObservers( ) throws {
235+ guard #available( iOS 13 . 0 , * ) else {
236+ try XCTSkipIf ( true , " This test is for iOS 13.0+ only " )
237+ return
238+ }
239+
240+ // Given
241+ let subject = PassthroughSubject < String , Error > ( )
242+
243+ var emittedValues = [ String] ( )
244+ let cancellable = subject. sink ( receiveCompletion: { _ in
245+ // noop
246+ } ) { value in
247+ emittedValues. append ( value)
248+ }
249+
250+ // This will be emitted because the observer is active
251+ subject. send ( " dicta " )
252+
253+ // When
254+ // Cancel the observer
255+ cancellable. cancel ( )
256+
257+ // This will not be emitted anymore
258+ subject. send ( " amet " )
259+
260+ // Then
261+ XCTAssertEqual ( emittedValues, [ " dicta " ] )
262+ }
113263}
0 commit comments