forked from wangziqi/gongxue-base
feat: add video playback progress reporting
This commit is contained in:
@@ -1694,6 +1694,35 @@ async function testVideos() {
|
||||
quotaPlayback.watermark?.traceId,
|
||||
'quota video play event should record watermark trace id',
|
||||
);
|
||||
|
||||
const progressStarted = await request('/api/videos/progress', {
|
||||
method: 'POST',
|
||||
body: { playToken: quotaPlayback.playToken, eventType: 'start', progressSeconds: 3, durationSeconds: 90 },
|
||||
});
|
||||
assert.equal(progressStarted.item?.status, 'started', 'video progress start should mark event started');
|
||||
assert.equal(progressStarted.item?.playback?.watchedSeconds, 3, 'video progress start should record watched seconds');
|
||||
|
||||
const progressHeartbeat = await request('/api/videos/progress', {
|
||||
method: 'POST',
|
||||
body: { playToken: quotaPlayback.playToken, eventType: 'heartbeat', progressSeconds: 45, watchedSeconds: 48, durationSeconds: 90 },
|
||||
});
|
||||
assert.equal(progressHeartbeat.item?.status, 'started', 'video heartbeat should keep event started before completion threshold');
|
||||
assert.equal(progressHeartbeat.item?.playback?.watchedSeconds, 48, 'video heartbeat should keep max watched seconds');
|
||||
|
||||
const progressCompleted = await request('/api/videos/progress', {
|
||||
method: 'POST',
|
||||
body: { playToken: quotaPlayback.playToken, eventType: 'complete', progressSeconds: 90, durationSeconds: 90 },
|
||||
});
|
||||
assert.equal(progressCompleted.item?.status, 'completed', 'video completion should mark event completed');
|
||||
assert.equal(progressCompleted.item?.playback?.completionRate, 1, 'video completion should record completion rate');
|
||||
|
||||
const secondUserProgressDenied = await request('/api/videos/progress', {
|
||||
userId: SECOND_STUDENT_USER_ID,
|
||||
method: 'POST',
|
||||
body: { playToken: quotaPlayback.playToken, eventType: 'heartbeat', progressSeconds: 10 },
|
||||
expectStatus: 404,
|
||||
});
|
||||
assert.equal(secondUserProgressDenied.code, 'VIDEO_PLAY_EVENT_NOT_FOUND', 'another user must not update a play token');
|
||||
}
|
||||
|
||||
async function testVocabulary() {
|
||||
@@ -3735,6 +3764,13 @@ async function testTenantContentAssetsAndImports() {
|
||||
assert.equal(mediaVideoSummary.videoPlay?.svipPlays >= 1, true, 'media analytics summary should count SVIP video plays');
|
||||
assert.ok(mediaVideoSummary.videoTop?.some(item => item.videoId === ids.video), 'media analytics summary should include top videos');
|
||||
|
||||
const mediaQuotaVideoSummary = await request('/api/tenant-content/media-analytics/summary', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
query: { timeRange: '30d', videoId: ids.quotaVideo },
|
||||
});
|
||||
assert.equal(mediaQuotaVideoSummary.videoPlay?.completedEvents >= 1, true, 'media analytics summary should count completed video events');
|
||||
assert.equal(mediaQuotaVideoSummary.videoPlay?.watchedSeconds >= 90, true, 'media analytics summary should count watched seconds');
|
||||
|
||||
const mediaVideoEventsByVideo = await request('/api/tenant-content/media-analytics/video-events', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
query: { timeRange: '30d', videoId: ids.video, limit: 5 },
|
||||
|
||||
Reference in New Issue
Block a user