@@ -9,6 +9,37 @@ import XCTest
9
9
10
10
final class RTCAudioStore_Tests : XCTestCase , @unchecked Sendable {
11
11
12
+ private final class SpyReducer : RTCAudioStoreReducer , @unchecked Sendable {
13
+ var reduceError : Error ?
14
+ private( set) var reduceWasCalled : ( state: RTCAudioStore . State , action: RTCAudioStoreAction , calledAt: Date ) ?
15
+ func reduce(
16
+ state: RTCAudioStore . State ,
17
+ action: RTCAudioStoreAction ,
18
+ file: StaticString ,
19
+ function: StaticString ,
20
+ line: UInt
21
+ ) throws -> RTCAudioStore . State {
22
+ reduceWasCalled = ( state, action, . init( ) )
23
+ guard let reduceError else {
24
+ return state
25
+ }
26
+ throw reduceError
27
+ }
28
+ }
29
+
30
+ private final class SpyMiddleware : RTCAudioStoreMiddleware , @unchecked Sendable {
31
+ private( set) var applyWasCalled : ( state: RTCAudioStore . State , action: RTCAudioStoreAction , calledAt: Date ) ?
32
+ func apply(
33
+ state: RTCAudioStore . State ,
34
+ action: RTCAudioStoreAction ,
35
+ file: StaticString ,
36
+ function: StaticString ,
37
+ line: UInt
38
+ ) {
39
+ applyWasCalled = ( state, action, . init( ) )
40
+ }
41
+ }
42
+
12
43
// MARK: - Properties
13
44
14
45
private lazy var subject : RTCAudioStore ! = . init( )
@@ -37,4 +68,49 @@ final class RTCAudioStore_Tests: XCTestCase, @unchecked Sendable {
37
68
&& self . subject. state. isAudioEnabled == false
38
69
}
39
70
}
71
+
72
+ // MARK: - dispatch
73
+
74
+ func test_dispatch_middlewareWasCalledBeforeReducer( ) async throws {
75
+ let reducer = SpyReducer ( )
76
+ let middleware = SpyMiddleware ( )
77
+ subject. add ( reducer)
78
+ subject. add ( middleware)
79
+
80
+ subject. dispatch ( . audioSession( . isActive( true ) ) )
81
+ await fulfillment { middleware. applyWasCalled != nil && reducer. reduceWasCalled != nil }
82
+
83
+ let middlewareWasCalledAt = try XCTUnwrap ( middleware. applyWasCalled? . calledAt)
84
+ let reducerWasCalledAt = try XCTUnwrap ( reducer. reduceWasCalled? . calledAt)
85
+ XCTAssertTrue ( reducerWasCalledAt. timeIntervalSince ( middlewareWasCalledAt) > 0 )
86
+ }
87
+
88
+ // MARK: - dispatchAsync
89
+
90
+ func test_dispatchAsync_middlewareWasCalledBeforeReducer( ) async throws {
91
+ let reducer = SpyReducer ( )
92
+ let middleware = SpyMiddleware ( )
93
+ subject. add ( reducer)
94
+ subject. add ( middleware)
95
+
96
+ try await subject. dispatchAsync ( . audioSession( . isActive( true ) ) )
97
+
98
+ let middlewareWasCalledAt = try XCTUnwrap ( middleware. applyWasCalled? . calledAt)
99
+ let reducerWasCalledAt = try XCTUnwrap ( reducer. reduceWasCalled? . calledAt)
100
+ XCTAssertTrue ( reducerWasCalledAt. timeIntervalSince ( middlewareWasCalledAt) > 0 )
101
+ }
102
+
103
+ func test_dispatchAsync_reducerThrowsError_rethrowsError( ) async throws {
104
+ let expected = ClientError ( . unique)
105
+ let reducer = SpyReducer ( )
106
+ reducer. reduceError = expected
107
+ subject. add ( reducer)
108
+
109
+ do {
110
+ try await subject. dispatchAsync ( . audioSession( . isActive( true ) ) )
111
+ XCTFail ( )
112
+ } catch {
113
+ XCTAssertEqual ( ( error as? ClientError ) ? . localizedDescription, expected. localizedDescription)
114
+ }
115
+ }
40
116
}
0 commit comments