@granite-js/video 1.0.0
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/CHANGELOG.md +7 -0
- package/GraniteVideo.podspec +72 -0
- package/android/README.md +232 -0
- package/android/build.gradle +117 -0
- package/android/gradle.properties +8 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/run/granite/video/GraniteVideoModule.kt +70 -0
- package/android/src/main/java/run/granite/video/GraniteVideoPackage.kt +43 -0
- package/android/src/main/java/run/granite/video/GraniteVideoView.kt +384 -0
- package/android/src/main/java/run/granite/video/GraniteVideoViewManager.kt +318 -0
- package/android/src/main/java/run/granite/video/event/GraniteVideoEvents.kt +273 -0
- package/android/src/main/java/run/granite/video/event/VideoEventDispatcher.kt +66 -0
- package/android/src/main/java/run/granite/video/event/VideoEventListenerAdapter.kt +157 -0
- package/android/src/main/java/run/granite/video/provider/GraniteVideoProvider.kt +346 -0
- package/android/src/media3/AndroidManifest.xml +9 -0
- package/android/src/media3/java/run/granite/video/provider/media3/ExoPlayerProvider.kt +386 -0
- package/android/src/media3/java/run/granite/video/provider/media3/Media3ContentProvider.kt +29 -0
- package/android/src/media3/java/run/granite/video/provider/media3/Media3Initializer.kt +25 -0
- package/android/src/media3/java/run/granite/video/provider/media3/factory/ExoPlayerFactory.kt +32 -0
- package/android/src/media3/java/run/granite/video/provider/media3/factory/MediaSourceFactory.kt +61 -0
- package/android/src/media3/java/run/granite/video/provider/media3/factory/TrackSelectorFactory.kt +26 -0
- package/android/src/media3/java/run/granite/video/provider/media3/factory/VideoSurfaceFactory.kt +62 -0
- package/android/src/media3/java/run/granite/video/provider/media3/listener/ExoPlayerEventListener.kt +104 -0
- package/android/src/media3/java/run/granite/video/provider/media3/scheduler/ProgressScheduler.kt +56 -0
- package/android/src/test/java/run/granite/video/GraniteVideoViewRobolectricTest.kt +598 -0
- package/android/src/test/java/run/granite/video/event/VideoEventListenerAdapterTest.kt +319 -0
- package/android/src/test/java/run/granite/video/helpers/FakeGraniteVideoProvider.kt +161 -0
- package/android/src/test/java/run/granite/video/helpers/TestProgressScheduler.kt +42 -0
- package/android/src/test/java/run/granite/video/provider/GraniteVideoRegistryTest.kt +232 -0
- package/android/src/test/java/run/granite/video/provider/ProviderContractTest.kt +174 -0
- package/android/src/test/java/run/granite/video/provider/media3/listener/ExoPlayerEventListenerTest.kt +243 -0
- package/android/src/test/resources/kotest.properties +2 -0
- package/dist/module/GraniteVideo.js +458 -0
- package/dist/module/GraniteVideo.js.map +1 -0
- package/dist/module/GraniteVideoNativeComponent.ts +265 -0
- package/dist/module/index.js +7 -0
- package/dist/module/index.js.map +1 -0
- package/dist/module/package.json +1 -0
- package/dist/module/types.js +4 -0
- package/dist/module/types.js.map +1 -0
- package/dist/typescript/GraniteVideo.d.ts +12 -0
- package/dist/typescript/GraniteVideoNativeComponent.d.ts +189 -0
- package/dist/typescript/index.d.ts +5 -0
- package/dist/typescript/types.d.ts +328 -0
- package/ios/GraniteVideoComponentsProvider.h +10 -0
- package/ios/GraniteVideoProvider.swift +280 -0
- package/ios/GraniteVideoView.h +15 -0
- package/ios/GraniteVideoView.mm +661 -0
- package/ios/Providers/AVPlayerProvider.swift +541 -0
- package/package.json +106 -0
- package/src/GraniteVideo.tsx +575 -0
- package/src/GraniteVideoNativeComponent.ts +265 -0
- package/src/index.ts +8 -0
- package/src/types.ts +464 -0
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
package run.granite.video
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.view.View
|
|
5
|
+
import io.mockk.*
|
|
6
|
+
import org.junit.After
|
|
7
|
+
import org.junit.Before
|
|
8
|
+
import org.junit.Test
|
|
9
|
+
import org.junit.runner.RunWith
|
|
10
|
+
import org.robolectric.RobolectricTestRunner
|
|
11
|
+
import org.robolectric.RuntimeEnvironment
|
|
12
|
+
import org.robolectric.annotation.Config
|
|
13
|
+
import run.granite.video.provider.*
|
|
14
|
+
import org.junit.Assert.*
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* GraniteVideoView tests using Robolectric for Android view testing.
|
|
18
|
+
* These tests require a real Android environment provided by Robolectric.
|
|
19
|
+
*/
|
|
20
|
+
@RunWith(RobolectricTestRunner::class)
|
|
21
|
+
@Config(sdk = [28])
|
|
22
|
+
class GraniteVideoViewRobolectricTest {
|
|
23
|
+
|
|
24
|
+
private lateinit var context: Context
|
|
25
|
+
private lateinit var mockProvider: GraniteVideoProvider
|
|
26
|
+
private lateinit var mockPlayerView: View
|
|
27
|
+
private lateinit var mockEventListener: GraniteVideoEventListener
|
|
28
|
+
|
|
29
|
+
@Before
|
|
30
|
+
fun setUp() {
|
|
31
|
+
context = RuntimeEnvironment.getApplication()
|
|
32
|
+
mockProvider = mockk(relaxed = true)
|
|
33
|
+
mockPlayerView = View(context)
|
|
34
|
+
mockEventListener = mockk(relaxed = true)
|
|
35
|
+
|
|
36
|
+
every { mockProvider.createPlayerView(any()) } returns mockPlayerView
|
|
37
|
+
every { mockProvider.providerId } returns "test-provider"
|
|
38
|
+
every { mockProvider.providerName } returns "Test Provider"
|
|
39
|
+
|
|
40
|
+
GraniteVideoRegistry.clear()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@After
|
|
44
|
+
fun tearDown() {
|
|
45
|
+
clearAllMocks()
|
|
46
|
+
GraniteVideoRegistry.clear()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ============================================================
|
|
50
|
+
// Initialization Tests
|
|
51
|
+
// ============================================================
|
|
52
|
+
|
|
53
|
+
@Test
|
|
54
|
+
fun `view created with provider factory should use the provided factory`() {
|
|
55
|
+
val view = GraniteVideoView(
|
|
56
|
+
context = context,
|
|
57
|
+
providerFactory = { mockProvider }
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
assertEquals(mockProvider, view.currentProvider)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@Test
|
|
64
|
+
fun `view should set delegate on provider`() {
|
|
65
|
+
val view = GraniteVideoView(
|
|
66
|
+
context = context,
|
|
67
|
+
providerFactory = { mockProvider }
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
verify { mockProvider.delegate = view }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@Test
|
|
74
|
+
fun `view should create player view on initialization`() {
|
|
75
|
+
GraniteVideoView(
|
|
76
|
+
context = context,
|
|
77
|
+
providerFactory = { mockProvider }
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
verify { mockProvider.createPlayerView(context) }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@Test
|
|
84
|
+
fun `view created with default provider from registry should use registry provider`() {
|
|
85
|
+
GraniteVideoRegistry.registerFactory("default") { mockProvider }
|
|
86
|
+
GraniteVideoRegistry.setDefaultProvider("default")
|
|
87
|
+
|
|
88
|
+
val view = GraniteVideoView(context = context)
|
|
89
|
+
|
|
90
|
+
assertEquals(mockProvider, view.currentProvider)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@Test
|
|
94
|
+
fun `view created with no registry and no factory should have a fallback provider`() {
|
|
95
|
+
val view = GraniteVideoView(context = context)
|
|
96
|
+
|
|
97
|
+
assertNotNull(view.currentProvider)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ============================================================
|
|
101
|
+
// setSource Tests
|
|
102
|
+
// ============================================================
|
|
103
|
+
|
|
104
|
+
@Test
|
|
105
|
+
fun `setSource with valid source should call loadSource on provider`() {
|
|
106
|
+
val view = GraniteVideoView(
|
|
107
|
+
context = context,
|
|
108
|
+
providerFactory = { mockProvider }
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
val source = mapOf(
|
|
112
|
+
"uri" to "https://example.com/video.mp4",
|
|
113
|
+
"type" to "mp4",
|
|
114
|
+
"startPosition" to 10.0,
|
|
115
|
+
"headers" to mapOf("Authorization" to "Bearer token")
|
|
116
|
+
)
|
|
117
|
+
view.setSource(source)
|
|
118
|
+
|
|
119
|
+
verify {
|
|
120
|
+
mockProvider.loadSource(match<GraniteVideoSource> {
|
|
121
|
+
it.uri == "https://example.com/video.mp4" &&
|
|
122
|
+
it.type == "mp4" &&
|
|
123
|
+
it.startPosition == 10.0 &&
|
|
124
|
+
it.headers?.get("Authorization") == "Bearer token"
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@Test
|
|
130
|
+
fun `setSource with null source should not call loadSource`() {
|
|
131
|
+
val view = GraniteVideoView(
|
|
132
|
+
context = context,
|
|
133
|
+
providerFactory = { mockProvider }
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
view.setSource(null)
|
|
137
|
+
|
|
138
|
+
verify(exactly = 0) { mockProvider.loadSource(any()) }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@Test
|
|
142
|
+
fun `setSource when not paused should call play after loading`() {
|
|
143
|
+
val view = GraniteVideoView(
|
|
144
|
+
context = context,
|
|
145
|
+
providerFactory = { mockProvider }
|
|
146
|
+
)
|
|
147
|
+
view.setPaused(false)
|
|
148
|
+
clearMocks(mockProvider, answers = false)
|
|
149
|
+
every { mockProvider.createPlayerView(any()) } returns mockPlayerView
|
|
150
|
+
|
|
151
|
+
view.setSource(mapOf("uri" to "https://example.com/video.mp4"))
|
|
152
|
+
|
|
153
|
+
verifyOrder {
|
|
154
|
+
mockProvider.loadSource(any())
|
|
155
|
+
mockProvider.play()
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ============================================================
|
|
160
|
+
// Playback Control Tests
|
|
161
|
+
// ============================================================
|
|
162
|
+
|
|
163
|
+
@Test
|
|
164
|
+
fun `setPaused(true) should call pause on provider`() {
|
|
165
|
+
val view = GraniteVideoView(
|
|
166
|
+
context = context,
|
|
167
|
+
providerFactory = { mockProvider }
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
view.setPaused(true)
|
|
171
|
+
|
|
172
|
+
verify { mockProvider.pause() }
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@Test
|
|
176
|
+
fun `setPaused(false) should call play on provider`() {
|
|
177
|
+
val view = GraniteVideoView(
|
|
178
|
+
context = context,
|
|
179
|
+
providerFactory = { mockProvider }
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
view.setPaused(false)
|
|
183
|
+
|
|
184
|
+
verify { mockProvider.play() }
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@Test
|
|
188
|
+
fun `setMuted should call setMuted on provider`() {
|
|
189
|
+
val view = GraniteVideoView(
|
|
190
|
+
context = context,
|
|
191
|
+
providerFactory = { mockProvider }
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
view.setMuted(true)
|
|
195
|
+
|
|
196
|
+
verify { mockProvider.setMuted(true) }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@Test
|
|
200
|
+
fun `setVolume should call setVolume on provider`() {
|
|
201
|
+
val view = GraniteVideoView(
|
|
202
|
+
context = context,
|
|
203
|
+
providerFactory = { mockProvider }
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
view.setVolume(0.5f)
|
|
207
|
+
|
|
208
|
+
verify { mockProvider.setVolume(0.5f) }
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
@Test
|
|
212
|
+
fun `setRate should call setRate on provider`() {
|
|
213
|
+
val view = GraniteVideoView(
|
|
214
|
+
context = context,
|
|
215
|
+
providerFactory = { mockProvider }
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
view.setRate(1.5f)
|
|
219
|
+
|
|
220
|
+
verify { mockProvider.setRate(1.5f) }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@Test
|
|
224
|
+
fun `setRepeat should call setRepeat on provider`() {
|
|
225
|
+
val view = GraniteVideoView(
|
|
226
|
+
context = context,
|
|
227
|
+
providerFactory = { mockProvider }
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
view.setRepeat(true)
|
|
231
|
+
|
|
232
|
+
verify { mockProvider.setRepeat(true) }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@Test
|
|
236
|
+
fun `seek should call seek on provider`() {
|
|
237
|
+
val view = GraniteVideoView(
|
|
238
|
+
context = context,
|
|
239
|
+
providerFactory = { mockProvider }
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
view.seek(30.0, 0.5)
|
|
243
|
+
|
|
244
|
+
verify { mockProvider.seek(30.0, 0.5) }
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ============================================================
|
|
248
|
+
// Resize Mode Tests
|
|
249
|
+
// ============================================================
|
|
250
|
+
|
|
251
|
+
@Test
|
|
252
|
+
fun `setResizeMode cover should call setResizeMode with COVER`() {
|
|
253
|
+
val view = GraniteVideoView(
|
|
254
|
+
context = context,
|
|
255
|
+
providerFactory = { mockProvider }
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
view.setResizeMode("cover")
|
|
259
|
+
|
|
260
|
+
verify { mockProvider.setResizeMode(GraniteVideoResizeMode.COVER) }
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
@Test
|
|
264
|
+
fun `setResizeMode stretch should call setResizeMode with STRETCH`() {
|
|
265
|
+
val view = GraniteVideoView(
|
|
266
|
+
context = context,
|
|
267
|
+
providerFactory = { mockProvider }
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
view.setResizeMode("stretch")
|
|
271
|
+
|
|
272
|
+
verify { mockProvider.setResizeMode(GraniteVideoResizeMode.STRETCH) }
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
@Test
|
|
276
|
+
fun `setResizeMode none should call setResizeMode with NONE`() {
|
|
277
|
+
val view = GraniteVideoView(
|
|
278
|
+
context = context,
|
|
279
|
+
providerFactory = { mockProvider }
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
view.setResizeMode("none")
|
|
283
|
+
|
|
284
|
+
verify { mockProvider.setResizeMode(GraniteVideoResizeMode.NONE) }
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
@Test
|
|
288
|
+
fun `setResizeMode contain should call setResizeMode with CONTAIN`() {
|
|
289
|
+
val view = GraniteVideoView(
|
|
290
|
+
context = context,
|
|
291
|
+
providerFactory = { mockProvider }
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
view.setResizeMode("contain")
|
|
295
|
+
|
|
296
|
+
verify { mockProvider.setResizeMode(GraniteVideoResizeMode.CONTAIN) }
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// ============================================================
|
|
300
|
+
// Controls Tests
|
|
301
|
+
// ============================================================
|
|
302
|
+
|
|
303
|
+
@Test
|
|
304
|
+
fun `setControls should call setControlsEnabled on provider`() {
|
|
305
|
+
val view = GraniteVideoView(
|
|
306
|
+
context = context,
|
|
307
|
+
providerFactory = { mockProvider }
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
view.setControls(true)
|
|
311
|
+
|
|
312
|
+
verify { mockProvider.setControlsEnabled(true) }
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
@Test
|
|
316
|
+
fun `setFullscreen should call setFullscreen on provider`() {
|
|
317
|
+
val view = GraniteVideoView(
|
|
318
|
+
context = context,
|
|
319
|
+
providerFactory = { mockProvider }
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
view.setFullscreen(true)
|
|
323
|
+
|
|
324
|
+
verify { mockProvider.setFullscreen(true, true) }
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
@Test
|
|
328
|
+
fun `setPictureInPicture should call setPictureInPictureEnabled on provider`() {
|
|
329
|
+
val view = GraniteVideoView(
|
|
330
|
+
context = context,
|
|
331
|
+
providerFactory = { mockProvider }
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
view.setPictureInPicture(true)
|
|
335
|
+
|
|
336
|
+
verify { mockProvider.setPictureInPictureEnabled(true) }
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// ============================================================
|
|
340
|
+
// Buffer Config Tests
|
|
341
|
+
// ============================================================
|
|
342
|
+
|
|
343
|
+
@Test
|
|
344
|
+
fun `setBufferConfig with valid config should call setBufferConfig on provider`() {
|
|
345
|
+
val view = GraniteVideoView(
|
|
346
|
+
context = context,
|
|
347
|
+
providerFactory = { mockProvider }
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
val config = mapOf(
|
|
351
|
+
"minBufferMs" to 10000,
|
|
352
|
+
"maxBufferMs" to 30000,
|
|
353
|
+
"bufferForPlaybackMs" to 2000
|
|
354
|
+
)
|
|
355
|
+
view.setBufferConfig(config)
|
|
356
|
+
|
|
357
|
+
verify {
|
|
358
|
+
mockProvider.setBufferConfig(match<GraniteVideoBufferConfig> {
|
|
359
|
+
it.minBufferMs == 10000 &&
|
|
360
|
+
it.maxBufferMs == 30000 &&
|
|
361
|
+
it.bufferForPlaybackMs == 2000
|
|
362
|
+
})
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
@Test
|
|
367
|
+
fun `setBufferConfig with null should not call setBufferConfig`() {
|
|
368
|
+
val view = GraniteVideoView(
|
|
369
|
+
context = context,
|
|
370
|
+
providerFactory = { mockProvider }
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
view.setBufferConfig(null)
|
|
374
|
+
|
|
375
|
+
verify(exactly = 0) { mockProvider.setBufferConfig(any()) }
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// ============================================================
|
|
379
|
+
// Delegate Events Tests
|
|
380
|
+
// ============================================================
|
|
381
|
+
|
|
382
|
+
@Test
|
|
383
|
+
fun `onLoadStart should forward to eventListener`() {
|
|
384
|
+
val view = GraniteVideoView(
|
|
385
|
+
context = context,
|
|
386
|
+
providerFactory = { mockProvider }
|
|
387
|
+
)
|
|
388
|
+
view.eventListener = mockEventListener
|
|
389
|
+
|
|
390
|
+
view.onLoadStart(true, "mp4", "https://example.com/video.mp4")
|
|
391
|
+
|
|
392
|
+
verify { mockEventListener.onLoadStart(true, "mp4", "https://example.com/video.mp4") }
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
@Test
|
|
396
|
+
fun `onLoad should forward to eventListener`() {
|
|
397
|
+
val view = GraniteVideoView(
|
|
398
|
+
context = context,
|
|
399
|
+
providerFactory = { mockProvider }
|
|
400
|
+
)
|
|
401
|
+
view.eventListener = mockEventListener
|
|
402
|
+
|
|
403
|
+
val data = GraniteVideoLoadData(
|
|
404
|
+
currentTime = 0.0,
|
|
405
|
+
duration = 60.0,
|
|
406
|
+
naturalWidth = 1920.0,
|
|
407
|
+
naturalHeight = 1080.0,
|
|
408
|
+
orientation = "landscape"
|
|
409
|
+
)
|
|
410
|
+
view.onLoad(data)
|
|
411
|
+
|
|
412
|
+
verify { mockEventListener.onLoad(data) }
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
@Test
|
|
416
|
+
fun `onError should forward to eventListener`() {
|
|
417
|
+
val view = GraniteVideoView(
|
|
418
|
+
context = context,
|
|
419
|
+
providerFactory = { mockProvider }
|
|
420
|
+
)
|
|
421
|
+
view.eventListener = mockEventListener
|
|
422
|
+
|
|
423
|
+
val error = GraniteVideoErrorData(
|
|
424
|
+
code = 1001,
|
|
425
|
+
domain = "ExoPlayer",
|
|
426
|
+
localizedDescription = "Test error",
|
|
427
|
+
errorString = "ERROR_TEST"
|
|
428
|
+
)
|
|
429
|
+
view.onError(error)
|
|
430
|
+
|
|
431
|
+
verify { mockEventListener.onError(error) }
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
@Test
|
|
435
|
+
fun `onProgress should forward to eventListener`() {
|
|
436
|
+
val view = GraniteVideoView(
|
|
437
|
+
context = context,
|
|
438
|
+
providerFactory = { mockProvider }
|
|
439
|
+
)
|
|
440
|
+
view.eventListener = mockEventListener
|
|
441
|
+
|
|
442
|
+
val data = GraniteVideoProgressData(
|
|
443
|
+
currentTime = 10.0,
|
|
444
|
+
playableDuration = 20.0,
|
|
445
|
+
seekableDuration = 60.0
|
|
446
|
+
)
|
|
447
|
+
view.onProgress(data)
|
|
448
|
+
|
|
449
|
+
verify { mockEventListener.onProgress(data) }
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
@Test
|
|
453
|
+
fun `onEnd should forward to eventListener`() {
|
|
454
|
+
val view = GraniteVideoView(
|
|
455
|
+
context = context,
|
|
456
|
+
providerFactory = { mockProvider }
|
|
457
|
+
)
|
|
458
|
+
view.eventListener = mockEventListener
|
|
459
|
+
|
|
460
|
+
view.onEnd()
|
|
461
|
+
|
|
462
|
+
verify { mockEventListener.onEnd() }
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
@Test
|
|
466
|
+
fun `onBuffer should forward to eventListener`() {
|
|
467
|
+
val view = GraniteVideoView(
|
|
468
|
+
context = context,
|
|
469
|
+
providerFactory = { mockProvider }
|
|
470
|
+
)
|
|
471
|
+
view.eventListener = mockEventListener
|
|
472
|
+
|
|
473
|
+
view.onBuffer(true)
|
|
474
|
+
|
|
475
|
+
verify { mockEventListener.onBuffer(true) }
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
@Test
|
|
479
|
+
fun `onPlaybackStateChanged should forward to eventListener`() {
|
|
480
|
+
val view = GraniteVideoView(
|
|
481
|
+
context = context,
|
|
482
|
+
providerFactory = { mockProvider }
|
|
483
|
+
)
|
|
484
|
+
view.eventListener = mockEventListener
|
|
485
|
+
|
|
486
|
+
view.onPlaybackStateChanged(true, false, true)
|
|
487
|
+
|
|
488
|
+
verify { mockEventListener.onPlaybackStateChanged(true, false, true) }
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// ============================================================
|
|
492
|
+
// Provider Selection Tests
|
|
493
|
+
// ============================================================
|
|
494
|
+
|
|
495
|
+
@Test
|
|
496
|
+
fun `default provider set before view creation should be used`() {
|
|
497
|
+
val mockProvider2 = mockk<GraniteVideoProvider>(relaxed = true)
|
|
498
|
+
val mockPlayerView2 = View(context)
|
|
499
|
+
every { mockProvider2.createPlayerView(any()) } returns mockPlayerView2
|
|
500
|
+
every { mockProvider2.providerId } returns "provider2"
|
|
501
|
+
|
|
502
|
+
GraniteVideoRegistry.registerFactory("provider1") { mockProvider }
|
|
503
|
+
GraniteVideoRegistry.registerFactory("provider2") { mockProvider2 }
|
|
504
|
+
GraniteVideoRegistry.setDefaultProvider("provider2")
|
|
505
|
+
|
|
506
|
+
val view = GraniteVideoView(context = context)
|
|
507
|
+
|
|
508
|
+
assertEquals(mockProvider2, view.currentProvider)
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
@Test
|
|
512
|
+
fun `different default providers for different views`() {
|
|
513
|
+
val mockProvider2 = mockk<GraniteVideoProvider>(relaxed = true)
|
|
514
|
+
val mockPlayerView2 = View(context)
|
|
515
|
+
every { mockProvider2.createPlayerView(any()) } returns mockPlayerView2
|
|
516
|
+
every { mockProvider2.providerId } returns "provider2"
|
|
517
|
+
|
|
518
|
+
GraniteVideoRegistry.registerFactory("provider1") { mockProvider }
|
|
519
|
+
GraniteVideoRegistry.registerFactory("provider2") { mockProvider2 }
|
|
520
|
+
|
|
521
|
+
GraniteVideoRegistry.setDefaultProvider("provider1")
|
|
522
|
+
val view1 = GraniteVideoView(context = context)
|
|
523
|
+
|
|
524
|
+
GraniteVideoRegistry.setDefaultProvider("provider2")
|
|
525
|
+
val view2 = GraniteVideoView(context = context)
|
|
526
|
+
|
|
527
|
+
assertEquals(mockProvider, view1.currentProvider)
|
|
528
|
+
assertEquals(mockProvider2, view2.currentProvider)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// ============================================================
|
|
532
|
+
// Commands Tests
|
|
533
|
+
// ============================================================
|
|
534
|
+
|
|
535
|
+
@Test
|
|
536
|
+
fun `pauseCommand should call pause on provider`() {
|
|
537
|
+
val view = GraniteVideoView(
|
|
538
|
+
context = context,
|
|
539
|
+
providerFactory = { mockProvider }
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
view.pauseCommand()
|
|
543
|
+
|
|
544
|
+
verify { mockProvider.pause() }
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
@Test
|
|
548
|
+
fun `resumeCommand should call play on provider`() {
|
|
549
|
+
val view = GraniteVideoView(
|
|
550
|
+
context = context,
|
|
551
|
+
providerFactory = { mockProvider }
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
view.resumeCommand()
|
|
555
|
+
|
|
556
|
+
verify { mockProvider.play() }
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
@Test
|
|
560
|
+
fun `seekCommand should call seek on provider`() {
|
|
561
|
+
val view = GraniteVideoView(
|
|
562
|
+
context = context,
|
|
563
|
+
providerFactory = { mockProvider }
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
view.seekCommand(30.0, 0.1)
|
|
567
|
+
|
|
568
|
+
verify { mockProvider.seek(30.0, 0.1) }
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
@Test
|
|
572
|
+
fun `setVolumeCommand should call setVolume on provider`() {
|
|
573
|
+
val view = GraniteVideoView(
|
|
574
|
+
context = context,
|
|
575
|
+
providerFactory = { mockProvider }
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
view.setVolumeCommand(0.7f)
|
|
579
|
+
|
|
580
|
+
verify { mockProvider.setVolume(0.7f) }
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
@Test
|
|
584
|
+
fun `setSourceCommand should call loadSource with uri`() {
|
|
585
|
+
val view = GraniteVideoView(
|
|
586
|
+
context = context,
|
|
587
|
+
providerFactory = { mockProvider }
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
view.setSourceCommand("https://example.com/video.mp4")
|
|
591
|
+
|
|
592
|
+
verify {
|
|
593
|
+
mockProvider.loadSource(match<GraniteVideoSource> {
|
|
594
|
+
it.uri == "https://example.com/video.mp4"
|
|
595
|
+
})
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|