@@ -74,32 +74,36 @@ final class MockStreamingSpinPlayerDelegate: StreamingSpinPlayerDelegate {
7474@MainActor
7575struct StreamingSpinPlayerTests {
7676
77- private func createPlayer( mockPlayer: MockAVPlayer ? = nil ) -> (
78- StreamingSpinPlayer , MockAVPlayer , MockStreamingSpinPlayerDelegate
79- ) {
77+ private struct PlayerTestContext {
78+ let player : StreamingSpinPlayer
79+ let mock : MockAVPlayer
80+ let delegate : MockStreamingSpinPlayerDelegate
81+ }
82+
83+ private func createPlayer( mockPlayer: MockAVPlayer ? = nil ) -> PlayerTestContext {
8084 let mock = mockPlayer ?? MockAVPlayer ( )
8185 let delegate = MockStreamingSpinPlayerDelegate ( )
8286 let player = StreamingSpinPlayer (
8387 delegate: delegate,
8488 playerFactory: { mock }
8589 )
86- return ( player, mock, delegate)
90+ return PlayerTestContext ( player: player , mock: mock , delegate : delegate)
8791 }
8892
8993 // MARK: - Initial State
9094
9195 @Test ( " Initial state is available " )
9296 func testInitialState( ) {
93- let ( player , _ , _ ) = createPlayer ( )
94- #expect( player. state == . available)
95- #expect( player. spin == nil )
97+ let ctx = createPlayer ( )
98+ #expect( ctx . player. state == . available)
99+ #expect( ctx . player. spin == nil )
96100 }
97101
98102 // MARK: - Load
99103
100104 @Test ( " Load with nil downloadUrl fails immediately " )
101105 func testLoadNilDownloadUrl( ) async {
102- let ( player , _ , _ ) = createPlayer ( )
106+ let ctx = createPlayer ( )
103107 let audioBlock = AudioBlock (
104108 id: " test " , title: " Test " , artist: " Test " , durationMS: 30000 ,
105109 endOfMessageMS: 28000 , beginningOfOutroMS: 25000 , endOfIntroMS: 5000 ,
@@ -109,31 +113,31 @@ struct StreamingSpinPlayerTests {
109113 )
110114 let spin = Spin . mockWith ( audioBlock: audioBlock)
111115
112- let result = await player. load ( spin)
116+ let result = await ctx . player. load ( spin)
113117
114118 switch result {
115119 case . success:
116120 Issue . record ( " Expected failure for nil downloadUrl " )
117121 case . failure:
118- #expect( player. state == . available)
122+ #expect( ctx . player. state == . available)
119123 }
120124 }
121125
122126 @Test ( " Successful load transitions to loaded state " )
123127 func testLoadSuccess( ) async {
124128 let mock = MockAVPlayer ( )
125- let ( player , _ , delegate ) = createPlayer ( mockPlayer: mock)
129+ let ctx = createPlayer ( mockPlayer: mock)
126130 let spin = Spin . mockWith ( )
127131
128- let result = await player. load ( spin)
132+ let result = await ctx . player. load ( spin)
129133
130134 switch result {
131135 case . success:
132- #expect( player. state == . loaded)
133- #expect( player. spin? . id == spin. id)
136+ #expect( ctx . player. state == . loaded)
137+ #expect( ctx . player. spin? . id == spin. id)
134138 #expect( mock. loadedURL != nil )
135- #expect( delegate. stateChanges. contains ( . loading) )
136- #expect( delegate. stateChanges. contains ( . loaded) )
139+ #expect( ctx . delegate. stateChanges. contains ( . loading) )
140+ #expect( ctx . delegate. stateChanges. contains ( . loaded) )
137141 case . failure( let error) :
138142 Issue . record ( " Expected success but got: \( error) " )
139143 }
@@ -143,70 +147,70 @@ struct StreamingSpinPlayerTests {
143147 func testLoadFailure( ) async {
144148 let mock = MockAVPlayer ( )
145149 mock. shouldFailLoad = true
146- let ( player , _ , delegate ) = createPlayer ( mockPlayer: mock)
150+ let ctx = createPlayer ( mockPlayer: mock)
147151 let spin = Spin . mockWith ( )
148152
149- let result = await player. load ( spin)
153+ let result = await ctx . player. load ( spin)
150154
151155 switch result {
152156 case . success:
153157 Issue . record ( " Expected failure " )
154158 case . failure:
155- #expect( player. state == . error)
156- #expect( delegate. stateChanges. contains ( . loading) )
157- #expect( delegate. stateChanges. contains ( . error) )
159+ #expect( ctx . player. state == . error)
160+ #expect( ctx . delegate. stateChanges. contains ( . loading) )
161+ #expect( ctx . delegate. stateChanges. contains ( . error) )
158162 }
159163 }
160164
161165 @Test ( " Load builds fade schedule " )
162166 func testFadeScheduleBuiltDuringLoad( ) async {
163167 let mock = MockAVPlayer ( )
164- let ( player , _ , _ ) = createPlayer ( mockPlayer: mock)
168+ let ctx = createPlayer ( mockPlayer: mock)
165169
166170 let spin = Spin . mockWith (
167171 startingVolume: 1.0 ,
168172 fades: [ Fade ( atMS: 10000 , toVolume: 0.0 ) ]
169173 )
170174
171- _ = await player. load ( spin)
175+ _ = await ctx . player. load ( spin)
172176
173- #expect( !player. fadeSchedule. isEmpty)
174- #expect( player. fadeSchedule. count == FadeScheduleBuilder . fadeSteps + 1 )
177+ #expect( !ctx . player. fadeSchedule. isEmpty)
178+ #expect( ctx . player. fadeSchedule. count == FadeScheduleBuilder . fadeSteps + 1 )
175179 }
176180
177181 // MARK: - Clear
178182
179183 @Test ( " Clear resets all state " )
180184 func testClear( ) async {
181185 let mock = MockAVPlayer ( )
182- let ( player , _ , _ ) = createPlayer ( mockPlayer: mock)
186+ let ctx = createPlayer ( mockPlayer: mock)
183187
184188 let spin = Spin . mockWith ( )
185- _ = await player. load ( spin)
189+ _ = await ctx . player. load ( spin)
186190
187- player. clear ( )
191+ ctx . player. clear ( )
188192
189- #expect( player. state == . available)
190- #expect( player. spin == nil )
193+ #expect( ctx . player. state == . available)
194+ #expect( ctx . player. spin == nil )
191195 #expect( mock. pauseCallCount == 1 )
192196 #expect( mock. clearItemCallCount == 1 )
193- #expect( player. fadeSchedule. isEmpty)
197+ #expect( ctx . player. fadeSchedule. isEmpty)
194198 }
195199
196200 // MARK: - Stop
197201
198202 @Test ( " Stop calls clear " )
199203 func testStop( ) async {
200204 let mock = MockAVPlayer ( )
201- let ( player , _ , _ ) = createPlayer ( mockPlayer: mock)
205+ let ctx = createPlayer ( mockPlayer: mock)
202206
203207 let spin = Spin . mockWith ( )
204- _ = await player. load ( spin)
208+ _ = await ctx . player. load ( spin)
205209
206- player. stop ( )
210+ ctx . player. stop ( )
207211
208- #expect( player. state == . available)
209- #expect( player. spin == nil )
212+ #expect( ctx . player. state == . available)
213+ #expect( ctx . player. spin == nil )
210214 #expect( mock. pauseCallCount == 1 )
211215 }
212216
@@ -215,42 +219,42 @@ struct StreamingSpinPlayerTests {
215219 @Test ( " PlayNow with offset past endOfMessage clears player " )
216220 func testPlayNowPastEndOfMessage( ) async {
217221 let mock = MockAVPlayer ( )
218- let ( player , _ , _ ) = createPlayer ( mockPlayer: mock)
222+ let ctx = createPlayer ( mockPlayer: mock)
219223
220224 let spin = Spin . mockWith (
221225 audioBlock: AudioBlock . mockWith ( endOfMessageMS: 30000 )
222226 )
223- _ = await player. load ( spin)
227+ _ = await ctx . player. load ( spin)
224228
225- player. playNow ( from: 31.0 ) // 31 seconds > 30s endOfMessage
229+ ctx . player. playNow ( from: 31.0 ) // 31 seconds > 30s endOfMessage
226230
227- #expect( player. state == . available)
228- #expect( player. spin == nil )
231+ #expect( ctx . player. state == . available)
232+ #expect( ctx . player. spin == nil )
229233 }
230234
231235 @Test ( " PlayNow when not loaded is a no-op " )
232236 func testPlayNowNotLoaded( ) {
233- let ( player , mock , _ ) = createPlayer ( )
234- player. spin = Spin . mockWith ( )
237+ let ctx = createPlayer ( )
238+ ctx . player. spin = Spin . mockWith ( )
235239
236- player. playNow ( from: 5.0 )
240+ ctx . player. playNow ( from: 5.0 )
237241
238- #expect( mock. playCallCount == 0 )
239- #expect( player. state == . available)
242+ #expect( ctx . mock. playCallCount == 0 )
243+ #expect( ctx . player. state == . available)
240244 }
241245
242246 @Test ( " PlayNow sets volume from fade schedule " )
243247 func testPlayNowSetsVolume( ) async {
244248 let mock = MockAVPlayer ( )
245- let ( player , _ , _ ) = createPlayer ( mockPlayer: mock)
249+ let ctx = createPlayer ( mockPlayer: mock)
246250
247251 let spin = Spin . mockWith (
248252 startingVolume: 0.8 ,
249253 fades: [ ]
250254 )
251- _ = await player. load ( spin)
255+ _ = await ctx . player. load ( spin)
252256
253- player. playNow ( from: 0.0 )
257+ ctx . player. playNow ( from: 0.0 )
254258
255259 // Give the async Task inside playNow a moment
256260 try ? await Task . sleep ( for: . milliseconds( 50 ) )
@@ -262,22 +266,22 @@ struct StreamingSpinPlayerTests {
262266
263267 @Test ( " SchedulePlay when not loaded is a no-op " )
264268 func testSchedulePlayNotLoaded( ) {
265- let ( player , mock , _ ) = createPlayer ( )
269+ let ctx = createPlayer ( )
266270
267- player. schedulePlay ( at: Date ( ) . addingTimeInterval ( 10 ) )
271+ ctx . player. schedulePlay ( at: Date ( ) . addingTimeInterval ( 10 ) )
268272
269- #expect( mock. playCallCount == 0 )
273+ #expect( ctx . mock. playCallCount == 0 )
270274 }
271275
272276 @Test ( " SchedulePlay sets initial volume " )
273277 func testSchedulePlaySetsVolume( ) async {
274278 let mock = MockAVPlayer ( )
275- let ( player , _ , _ ) = createPlayer ( mockPlayer: mock)
279+ let ctx = createPlayer ( mockPlayer: mock)
276280
277281 let spin = Spin . mockWith ( startingVolume: 0.6 )
278- _ = await player. load ( spin)
282+ _ = await ctx . player. load ( spin)
279283
280- player. schedulePlay ( at: Date ( ) . addingTimeInterval ( 10 ) )
284+ ctx . player. schedulePlay ( at: Date ( ) . addingTimeInterval ( 10 ) )
281285
282286 #expect( mock. volume == 0.6 )
283287 }
@@ -286,22 +290,22 @@ struct StreamingSpinPlayerTests {
286290
287291 @Test ( " Delegate receives state changes " )
288292 func testDelegateReceivesStateChanges( ) {
289- let ( player , _ , delegate ) = createPlayer ( )
293+ let ctx = createPlayer ( )
290294
291- player. state = . loading
292- player. state = . loaded
293- player. state = . playing
295+ ctx . player. state = . loading
296+ ctx . player. state = . loaded
297+ ctx . player. state = . playing
294298
295- #expect( delegate. stateChanges == [ . loading, . loaded, . playing] )
299+ #expect( ctx . delegate. stateChanges == [ . loading, . loaded, . playing] )
296300 }
297301
298302 @Test ( " Duplicate state changes are not reported " )
299303 func testNoDuplicateStateChanges( ) {
300- let ( player , _ , delegate ) = createPlayer ( )
304+ let ctx = createPlayer ( )
301305
302- player. state = . loading
303- player. state = . loading // duplicate
306+ ctx . player. state = . loading
307+ ctx . player. state = . loading // duplicate
304308
305- #expect( delegate. stateChanges == [ . loading] )
309+ #expect( ctx . delegate. stateChanges == [ . loading] )
306310 }
307311}
0 commit comments