@rntp/player 5.0.0-beta.3 → 5.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +7 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/SleepTimerController.kt +128 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/TrackPlayerModule.kt +40 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/TrackPlayerPlaybackService.kt +107 -87
- package/android/src/main/java/com/doublesymmetry/trackplayer/models/BrowseTree.kt +51 -20
- package/android/src/main/java/com/doublesymmetry/trackplayer/models/PlayerConfig.kt +12 -1
- package/android/src/test/java/com/doublesymmetry/trackplayer/ExoPlayerIntegrationTest.kt +319 -0
- package/android/src/test/java/com/doublesymmetry/trackplayer/SleepTimerIntegrationTest.kt +473 -0
- package/android/src/test/java/com/doublesymmetry/trackplayer/SleepTimerStateTest.kt +58 -0
- package/android/src/test/java/com/doublesymmetry/trackplayer/models/BrowseNavigationTest.kt +215 -0
- package/android/src/test/java/com/doublesymmetry/trackplayer/models/BrowseTreeTest.kt +166 -0
- package/android/src/test/java/com/doublesymmetry/trackplayer/models/EmitEventTest.kt +68 -0
- package/android/src/test/java/com/doublesymmetry/trackplayer/models/PlayerConfigTest.kt +400 -0
- package/android/src/test/java/com/doublesymmetry/trackplayer/models/TrackPlayerMediaItemTest.kt +380 -0
- package/android/src/test/resources/robolectric.properties +1 -0
- package/ios/CarPlay/RNTPCarPlaySceneDelegate.swift +43 -14
- package/ios/TrackPlayer.swift +46 -101
- package/ios/TrackPlayerBridge.mm +2 -0
- package/ios/player/AVPlayerEngine.swift +46 -32
- package/ios/player/AudioCache.swift +34 -0
- package/ios/player/AudioPlayer.swift +36 -21
- package/ios/player/CacheProxyServer.swift +429 -0
- package/ios/player/DownloadCoordinator.swift +242 -0
- package/ios/player/Preloader.swift +21 -90
- package/ios/player/SleepTimerController.swift +147 -0
- package/ios/tests/AVPlayerEngineIntegrationTests.swift +230 -0
- package/ios/tests/AudioPlayerTests.swift +6 -0
- package/ios/tests/CacheProxyServerTests.swift +403 -0
- package/ios/tests/DownloadCoordinatorTests.swift +197 -0
- package/ios/tests/LocalAudioServer.swift +171 -0
- package/ios/tests/MockPlayerEngine.swift +1 -0
- package/ios/tests/QueueManagerTests.swift +6 -0
- package/ios/tests/SleepTimerIntegrationTests.swift +408 -0
- package/ios/tests/SleepTimerTests.swift +70 -0
- package/lib/commonjs/NativeTrackPlayer.js.map +1 -1
- package/lib/commonjs/audio.js +39 -4
- package/lib/commonjs/audio.js.map +1 -1
- package/lib/commonjs/interfaces/PlayerConfig.js +1 -1
- package/lib/commonjs/interfaces/PlayerConfig.js.map +1 -1
- package/lib/module/NativeTrackPlayer.js.map +1 -1
- package/lib/module/audio.js +37 -4
- package/lib/module/audio.js.map +1 -1
- package/lib/module/interfaces/PlayerConfig.js +1 -1
- package/lib/module/interfaces/PlayerConfig.js.map +1 -1
- package/lib/typescript/src/NativeTrackPlayer.d.ts +2 -0
- package/lib/typescript/src/NativeTrackPlayer.d.ts.map +1 -1
- package/lib/typescript/src/audio.d.ts +16 -4
- package/lib/typescript/src/audio.d.ts.map +1 -1
- package/lib/typescript/src/interfaces/BrowseTree.d.ts +35 -5
- package/lib/typescript/src/interfaces/BrowseTree.d.ts.map +1 -1
- package/lib/typescript/src/interfaces/MediaItem.d.ts +4 -1
- package/lib/typescript/src/interfaces/MediaItem.d.ts.map +1 -1
- package/lib/typescript/src/interfaces/PlayerConfig.d.ts +19 -2
- package/lib/typescript/src/interfaces/PlayerConfig.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/NativeTrackPlayer.ts +4 -0
- package/src/audio.ts +37 -4
- package/src/interfaces/BrowseTree.ts +40 -5
- package/src/interfaces/MediaItem.ts +4 -1
- package/src/interfaces/PlayerConfig.ts +22 -3
- package/ios/player/CachingResourceLoader.swift +0 -273
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
package com.doublesymmetry.trackplayer.models
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableArray
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap
|
|
5
|
+
import com.facebook.react.bridge.ReadableMapKeySetIterator
|
|
6
|
+
import io.mockk.every
|
|
7
|
+
import io.mockk.mockk
|
|
8
|
+
import org.junit.Test
|
|
9
|
+
import org.junit.Assert.*
|
|
10
|
+
import org.junit.runner.RunWith
|
|
11
|
+
import org.robolectric.RobolectricTestRunner
|
|
12
|
+
import org.robolectric.RuntimeEnvironment
|
|
13
|
+
|
|
14
|
+
@RunWith(RobolectricTestRunner::class)
|
|
15
|
+
class PlayerConfigTest {
|
|
16
|
+
|
|
17
|
+
// ---- Default config ----
|
|
18
|
+
|
|
19
|
+
@Test
|
|
20
|
+
fun `default config has sensible defaults`() {
|
|
21
|
+
val config = PlayerConfig()
|
|
22
|
+
|
|
23
|
+
assertEquals("music", config.contentType)
|
|
24
|
+
assertTrue(config.handleAudioBecomingNoisy)
|
|
25
|
+
assertEquals(WakeMode.NONE, config.wakeMode)
|
|
26
|
+
assertFalse(config.skipSilenceEnabled)
|
|
27
|
+
assertEquals(listOf(PlayerCommand.PLAY_PAUSE), config.availableCommands)
|
|
28
|
+
assertEquals(RemoteControlHandling.NATIVE, config.remoteControlHandling)
|
|
29
|
+
assertTrue(config.perCommandHandling.isEmpty())
|
|
30
|
+
assertEquals(15L, config.forwardInterval)
|
|
31
|
+
assertEquals(15L, config.backwardInterval)
|
|
32
|
+
assertNull(config.notificationChannelId)
|
|
33
|
+
assertNull(config.notificationChannelName)
|
|
34
|
+
assertNull(config.notificationSmallIcon)
|
|
35
|
+
assertNull(config.cacheMaxSizeBytes)
|
|
36
|
+
assertNull(config.castReceiverAppId)
|
|
37
|
+
assertEquals(0.0, config.progressSyncIntervalSeconds, 0.001)
|
|
38
|
+
assertNull(config.progressSyncHttpUrl)
|
|
39
|
+
assertNull(config.progressSyncHttpHeaders)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ---- Store and load round-trip ----
|
|
43
|
+
|
|
44
|
+
@Test
|
|
45
|
+
fun `store and load round-trip preserves config`() {
|
|
46
|
+
val context = RuntimeEnvironment.getApplication()
|
|
47
|
+
|
|
48
|
+
val config = PlayerConfig(
|
|
49
|
+
contentType = "speech",
|
|
50
|
+
handleAudioBecomingNoisy = false,
|
|
51
|
+
wakeMode = WakeMode.NETWORK,
|
|
52
|
+
skipSilenceEnabled = true,
|
|
53
|
+
forwardInterval = 30L,
|
|
54
|
+
backwardInterval = 10L,
|
|
55
|
+
notificationChannelId = "my-channel",
|
|
56
|
+
notificationChannelName = "My Player",
|
|
57
|
+
notificationSmallIcon = "ic_notification",
|
|
58
|
+
cacheMaxSizeBytes = 50L * 1024 * 1024,
|
|
59
|
+
castReceiverAppId = "ABCD1234",
|
|
60
|
+
progressSyncIntervalSeconds = 5.0,
|
|
61
|
+
progressSyncHttpUrl = "https://example.com/progress",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
config.store(context)
|
|
65
|
+
val loaded = config.load(context)
|
|
66
|
+
|
|
67
|
+
assertEquals("speech", loaded.contentType)
|
|
68
|
+
assertFalse(loaded.handleAudioBecomingNoisy)
|
|
69
|
+
assertEquals(WakeMode.NETWORK, loaded.wakeMode)
|
|
70
|
+
assertTrue(loaded.skipSilenceEnabled)
|
|
71
|
+
assertEquals(30L, loaded.forwardInterval)
|
|
72
|
+
assertEquals(10L, loaded.backwardInterval)
|
|
73
|
+
assertEquals("my-channel", loaded.notificationChannelId)
|
|
74
|
+
assertEquals("My Player", loaded.notificationChannelName)
|
|
75
|
+
assertEquals("ic_notification", loaded.notificationSmallIcon)
|
|
76
|
+
assertEquals(50L * 1024 * 1024, loaded.cacheMaxSizeBytes)
|
|
77
|
+
assertEquals("ABCD1234", loaded.castReceiverAppId)
|
|
78
|
+
assertEquals(5.0, loaded.progressSyncIntervalSeconds, 0.001)
|
|
79
|
+
assertEquals("https://example.com/progress", loaded.progressSyncHttpUrl)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@Test
|
|
83
|
+
fun `load with no stored data returns default config`() {
|
|
84
|
+
val context = RuntimeEnvironment.getApplication()
|
|
85
|
+
// Ensure a fresh prefs state by using a unique pref name
|
|
86
|
+
val prefs = context.getSharedPreferences("TrackPlayerPrefs", 0)
|
|
87
|
+
prefs.edit().remove("player_config").apply()
|
|
88
|
+
|
|
89
|
+
val loaded = PlayerConfig().load(context)
|
|
90
|
+
assertEquals("music", loaded.contentType)
|
|
91
|
+
assertEquals(WakeMode.NONE, loaded.wakeMode)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ---- fromReadableMap ----
|
|
95
|
+
|
|
96
|
+
@Test
|
|
97
|
+
fun `fromReadableMap parses contentType`() {
|
|
98
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
99
|
+
every { getString("contentType") } returns "speech"
|
|
100
|
+
every { getMap("android") } returns null
|
|
101
|
+
every { getMap("cache") } returns null
|
|
102
|
+
every { getMap("progressSync") } returns null
|
|
103
|
+
every { hasKey(any()) } returns false
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
107
|
+
assertEquals("speech", config.contentType)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@Test
|
|
111
|
+
fun `fromReadableMap defaults contentType to music when absent`() {
|
|
112
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
113
|
+
every { getString("contentType") } returns null
|
|
114
|
+
every { getMap("android") } returns null
|
|
115
|
+
every { getMap("cache") } returns null
|
|
116
|
+
every { getMap("progressSync") } returns null
|
|
117
|
+
every { hasKey(any()) } returns false
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
121
|
+
assertEquals("music", config.contentType)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@Test
|
|
125
|
+
fun `fromReadableMap parses android-specific config`() {
|
|
126
|
+
val androidMap = mockk<ReadableMap>(relaxed = true) {
|
|
127
|
+
every { getString("wakeMode") } returns "network"
|
|
128
|
+
every { hasKey("skipSilenceEnabled") } returns true
|
|
129
|
+
every { getBoolean("skipSilenceEnabled") } returns true
|
|
130
|
+
every { hasKey("cast") } returns true
|
|
131
|
+
every { getString("cast") } returns "RECV_APP_ID"
|
|
132
|
+
every { getMap("notification") } returns null
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
136
|
+
every { getString("contentType") } returns null
|
|
137
|
+
every { getMap("android") } returns androidMap
|
|
138
|
+
every { getMap("cache") } returns null
|
|
139
|
+
every { getMap("progressSync") } returns null
|
|
140
|
+
every { hasKey(any()) } returns false
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
144
|
+
assertEquals(WakeMode.NETWORK, config.wakeMode)
|
|
145
|
+
assertTrue(config.skipSilenceEnabled)
|
|
146
|
+
assertEquals("RECV_APP_ID", config.castReceiverAppId)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@Test
|
|
150
|
+
fun `fromReadableMap parses notification fields`() {
|
|
151
|
+
val notifMap = mockk<ReadableMap>(relaxed = true) {
|
|
152
|
+
every { getString("channelId") } returns "rntp-channel"
|
|
153
|
+
every { getString("channelName") } returns "Music Player"
|
|
154
|
+
every { getString("smallIcon") } returns "ic_music"
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
val androidMap = mockk<ReadableMap>(relaxed = true) {
|
|
158
|
+
every { getString("wakeMode") } returns null
|
|
159
|
+
every { hasKey("skipSilenceEnabled") } returns false
|
|
160
|
+
every { hasKey("cast") } returns false
|
|
161
|
+
every { getMap("notification") } returns notifMap
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
165
|
+
every { getString("contentType") } returns null
|
|
166
|
+
every { getMap("android") } returns androidMap
|
|
167
|
+
every { getMap("cache") } returns null
|
|
168
|
+
every { getMap("progressSync") } returns null
|
|
169
|
+
every { hasKey(any()) } returns false
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
173
|
+
assertEquals("rntp-channel", config.notificationChannelId)
|
|
174
|
+
assertEquals("Music Player", config.notificationChannelName)
|
|
175
|
+
assertEquals("ic_music", config.notificationSmallIcon)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@Test
|
|
179
|
+
fun `fromReadableMap parses cache config`() {
|
|
180
|
+
val cacheMap = mockk<ReadableMap>(relaxed = true) {
|
|
181
|
+
every { hasKey("maxSizeBytes") } returns true
|
|
182
|
+
every { getDouble("maxSizeBytes") } returns (200.0 * 1024 * 1024)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
186
|
+
every { getString("contentType") } returns null
|
|
187
|
+
every { getMap("android") } returns null
|
|
188
|
+
every { getMap("cache") } returns cacheMap
|
|
189
|
+
every { getMap("progressSync") } returns null
|
|
190
|
+
every { hasKey(any()) } returns false
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
194
|
+
assertEquals(200L * 1024 * 1024, config.cacheMaxSizeBytes)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@Test
|
|
198
|
+
fun `fromReadableMap uses default cache size when maxSizeBytes absent`() {
|
|
199
|
+
val cacheMap = mockk<ReadableMap>(relaxed = true) {
|
|
200
|
+
every { hasKey("maxSizeBytes") } returns false
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
204
|
+
every { getString("contentType") } returns null
|
|
205
|
+
every { getMap("android") } returns null
|
|
206
|
+
every { getMap("cache") } returns cacheMap
|
|
207
|
+
every { getMap("progressSync") } returns null
|
|
208
|
+
every { hasKey(any()) } returns false
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
212
|
+
// Default cache size is 500MB
|
|
213
|
+
assertEquals(500L * 1024 * 1024, config.cacheMaxSizeBytes)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@Test
|
|
217
|
+
fun `fromReadableMap parses wakeMode none`() {
|
|
218
|
+
val androidMap = mockk<ReadableMap>(relaxed = true) {
|
|
219
|
+
every { getString("wakeMode") } returns "none"
|
|
220
|
+
every { hasKey("skipSilenceEnabled") } returns false
|
|
221
|
+
every { hasKey("cast") } returns false
|
|
222
|
+
every { getMap("notification") } returns null
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
226
|
+
every { getString("contentType") } returns null
|
|
227
|
+
every { getMap("android") } returns androidMap
|
|
228
|
+
every { getMap("cache") } returns null
|
|
229
|
+
every { getMap("progressSync") } returns null
|
|
230
|
+
every { hasKey(any()) } returns false
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
234
|
+
assertEquals(WakeMode.NONE, config.wakeMode)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@Test
|
|
238
|
+
fun `fromReadableMap parses wakeMode local`() {
|
|
239
|
+
val androidMap = mockk<ReadableMap>(relaxed = true) {
|
|
240
|
+
every { getString("wakeMode") } returns "local"
|
|
241
|
+
every { hasKey("skipSilenceEnabled") } returns false
|
|
242
|
+
every { hasKey("cast") } returns false
|
|
243
|
+
every { getMap("notification") } returns null
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
247
|
+
every { getString("contentType") } returns null
|
|
248
|
+
every { getMap("android") } returns androidMap
|
|
249
|
+
every { getMap("cache") } returns null
|
|
250
|
+
every { getMap("progressSync") } returns null
|
|
251
|
+
every { hasKey(any()) } returns false
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
255
|
+
assertEquals(WakeMode.LOCAL, config.wakeMode)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ---- withCommands (command handling modes) ----
|
|
259
|
+
|
|
260
|
+
@Test
|
|
261
|
+
fun `withCommands sets native handling`() {
|
|
262
|
+
val commandsMap = mockk<ReadableMap>(relaxed = true) {
|
|
263
|
+
every { getString("handling") } returns "native"
|
|
264
|
+
every { hasKey("capabilities") } returns false
|
|
265
|
+
every { hasKey("perCommandHandling") } returns false
|
|
266
|
+
every { hasKey("forwardInterval") } returns false
|
|
267
|
+
every { hasKey("backwardInterval") } returns false
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
val config = PlayerConfig().withCommands(commandsMap)
|
|
271
|
+
assertEquals(RemoteControlHandling.NATIVE, config.remoteControlHandling)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@Test
|
|
275
|
+
fun `withCommands sets js handling`() {
|
|
276
|
+
val commandsMap = mockk<ReadableMap>(relaxed = true) {
|
|
277
|
+
every { getString("handling") } returns "js"
|
|
278
|
+
every { hasKey("capabilities") } returns false
|
|
279
|
+
every { hasKey("perCommandHandling") } returns false
|
|
280
|
+
every { hasKey("forwardInterval") } returns false
|
|
281
|
+
every { hasKey("backwardInterval") } returns false
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
val config = PlayerConfig().withCommands(commandsMap)
|
|
285
|
+
assertEquals(RemoteControlHandling.JS, config.remoteControlHandling)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
@Test
|
|
289
|
+
fun `withCommands sets hybrid handling`() {
|
|
290
|
+
val commandsMap = mockk<ReadableMap>(relaxed = true) {
|
|
291
|
+
every { getString("handling") } returns "hybrid"
|
|
292
|
+
every { hasKey("capabilities") } returns false
|
|
293
|
+
every { hasKey("perCommandHandling") } returns false
|
|
294
|
+
every { hasKey("forwardInterval") } returns false
|
|
295
|
+
every { hasKey("backwardInterval") } returns false
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
val config = PlayerConfig().withCommands(commandsMap)
|
|
299
|
+
assertEquals(RemoteControlHandling.HYBRID, config.remoteControlHandling)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
@Test
|
|
303
|
+
fun `withCommands parses perCommandHandling for hybrid mode`() {
|
|
304
|
+
val perCommandIterator = mockk<ReadableMapKeySetIterator> {
|
|
305
|
+
every { hasNextKey() } returnsMany listOf(true, true, false)
|
|
306
|
+
every { nextKey() } returnsMany listOf("next", "previous")
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
val perCommandMap = mockk<ReadableMap>(relaxed = true) {
|
|
310
|
+
every { keySetIterator() } returns perCommandIterator
|
|
311
|
+
every { getString("next") } returns "js"
|
|
312
|
+
every { getString("previous") } returns "native"
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
val commandsMap = mockk<ReadableMap>(relaxed = true) {
|
|
316
|
+
every { getString("handling") } returns "hybrid"
|
|
317
|
+
every { hasKey("capabilities") } returns false
|
|
318
|
+
every { hasKey("perCommandHandling") } returns true
|
|
319
|
+
every { getMap("perCommandHandling") } returns perCommandMap
|
|
320
|
+
every { hasKey("forwardInterval") } returns false
|
|
321
|
+
every { hasKey("backwardInterval") } returns false
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
val config = PlayerConfig().withCommands(commandsMap)
|
|
325
|
+
assertEquals(RemoteControlHandling.HYBRID, config.remoteControlHandling)
|
|
326
|
+
assertEquals(RemoteControlHandling.JS, config.perCommandHandling["next"])
|
|
327
|
+
assertEquals(RemoteControlHandling.NATIVE, config.perCommandHandling["previous"])
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
@Test
|
|
331
|
+
fun `withCommands parses capabilities`() {
|
|
332
|
+
val capabilitiesArray = mockk<ReadableArray>(relaxed = true) {
|
|
333
|
+
every { size() } returns 3
|
|
334
|
+
every { toArrayList() } returns arrayListOf("seek", "next", "previous")
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
val commandsMap = mockk<ReadableMap>(relaxed = true) {
|
|
338
|
+
every { getString("handling") } returns null
|
|
339
|
+
every { hasKey("capabilities") } returns true
|
|
340
|
+
every { getArray("capabilities") } returns capabilitiesArray
|
|
341
|
+
every { hasKey("perCommandHandling") } returns false
|
|
342
|
+
every { hasKey("forwardInterval") } returns false
|
|
343
|
+
every { hasKey("backwardInterval") } returns false
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
val config = PlayerConfig().withCommands(commandsMap)
|
|
347
|
+
assertTrue(config.availableCommands.contains(PlayerCommand.SEEK))
|
|
348
|
+
assertTrue(config.availableCommands.contains(PlayerCommand.NEXT))
|
|
349
|
+
assertTrue(config.availableCommands.contains(PlayerCommand.PREVIOUS))
|
|
350
|
+
assertFalse(config.availableCommands.contains(PlayerCommand.PLAY_PAUSE))
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
@Test
|
|
354
|
+
fun `withCommands parses forwardInterval and backwardInterval`() {
|
|
355
|
+
val commandsMap = mockk<ReadableMap>(relaxed = true) {
|
|
356
|
+
every { getString("handling") } returns null
|
|
357
|
+
every { hasKey("capabilities") } returns false
|
|
358
|
+
every { hasKey("perCommandHandling") } returns false
|
|
359
|
+
every { hasKey("forwardInterval") } returns true
|
|
360
|
+
every { getDouble("forwardInterval") } returns 30.0
|
|
361
|
+
every { hasKey("backwardInterval") } returns true
|
|
362
|
+
every { getDouble("backwardInterval") } returns 5.0
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
val config = PlayerConfig().withCommands(commandsMap)
|
|
366
|
+
assertEquals(30L, config.forwardInterval)
|
|
367
|
+
assertEquals(5L, config.backwardInterval)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
@Test
|
|
371
|
+
fun `withCommands with unknown handling preserves existing handling`() {
|
|
372
|
+
val commandsMap = mockk<ReadableMap>(relaxed = true) {
|
|
373
|
+
every { getString("handling") } returns "unknown-value"
|
|
374
|
+
every { hasKey("capabilities") } returns false
|
|
375
|
+
every { hasKey("perCommandHandling") } returns false
|
|
376
|
+
every { hasKey("forwardInterval") } returns false
|
|
377
|
+
every { hasKey("backwardInterval") } returns false
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
val original = PlayerConfig(remoteControlHandling = RemoteControlHandling.JS)
|
|
381
|
+
val config = original.withCommands(commandsMap)
|
|
382
|
+
assertEquals(RemoteControlHandling.JS, config.remoteControlHandling)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
@Test
|
|
386
|
+
fun `fromReadableMap with null android section defaults wakeMode to NONE`() {
|
|
387
|
+
val map = mockk<ReadableMap>(relaxed = true) {
|
|
388
|
+
every { getString("contentType") } returns null
|
|
389
|
+
every { getMap("android") } returns null
|
|
390
|
+
every { getMap("cache") } returns null
|
|
391
|
+
every { getMap("progressSync") } returns null
|
|
392
|
+
every { hasKey(any()) } returns false
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
val config = PlayerConfig.fromReadableMap(map)
|
|
396
|
+
assertEquals(WakeMode.NONE, config.wakeMode)
|
|
397
|
+
assertFalse(config.skipSilenceEnabled)
|
|
398
|
+
assertNull(config.castReceiverAppId)
|
|
399
|
+
}
|
|
400
|
+
}
|