Skip to content

Commit c54dc5e

Browse files
briankeaneclaude
andcommitted
Fix SwiftLint violations: large tuple and for-where
- Replace 3-member tuple return with PlayerTestContext struct - Use `where` clause instead of `if` inside `for` loop Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b2e77e0 commit c54dc5e

2 files changed

Lines changed: 70 additions & 68 deletions

File tree

Sources/PlayolaPlayer/Player/Streaming/FadeScheduleBuilder.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,8 @@ public enum FadeScheduleBuilder {
8181
in schedule: [FadeStep],
8282
afterMS currentMS: Int
8383
) -> Int {
84-
for (index, step) in schedule.enumerated() {
85-
if step.timeMS > currentMS {
86-
return index
87-
}
84+
for (index, step) in schedule.enumerated() where step.timeMS > currentMS {
85+
return index
8886
}
8987
return schedule.count
9088
}

Tests/PlayolaPlayerTests/StreamingSpinPlayerTests.swift

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -74,32 +74,36 @@ final class MockStreamingSpinPlayerDelegate: StreamingSpinPlayerDelegate {
7474
@MainActor
7575
struct 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

Comments
 (0)