- Add video upload endpoint POST /courses/:id/lessons/:lesson_id/video - Add VideoTranscodeService for multi-bitrate HLS (720p/480p/360p) - Add VideoTranscodeWorker for async lesson video processing - Add SetLessonVideoPath and UpdateLessonTranscoding to education service - Add uploadLessonVideo to frontend educationService with progress - Add comprehensive handler tests (video upload, auth, validation) - Add service-level tests (models, slugs, clamping, errors, UUIDs) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func TestNewVideoTranscodeService(t *testing.T) {
|
|
svc := NewVideoTranscodeService("/tmp/test-output", nil)
|
|
if svc == nil {
|
|
t.Fatal("expected non-nil service")
|
|
}
|
|
if svc.outputDir != "/tmp/test-output" {
|
|
t.Errorf("expected /tmp/test-output, got %s", svc.outputDir)
|
|
}
|
|
if len(svc.qualities) != 3 {
|
|
t.Errorf("expected 3 default qualities, got %d", len(svc.qualities))
|
|
}
|
|
}
|
|
|
|
func TestNewVideoTranscodeService_WithLogger(t *testing.T) {
|
|
logger := zap.NewNop()
|
|
svc := NewVideoTranscodeService("/tmp/test", logger)
|
|
if svc.logger != logger {
|
|
t.Error("expected provided logger")
|
|
}
|
|
}
|
|
|
|
func TestDefaultVideoQualities(t *testing.T) {
|
|
qualities := DefaultVideoQualities()
|
|
if len(qualities) != 3 {
|
|
t.Fatalf("expected 3 qualities, got %d", len(qualities))
|
|
}
|
|
|
|
expected := []struct {
|
|
name string
|
|
resolution string
|
|
}{
|
|
{"720p", "1280x720"},
|
|
{"480p", "854x480"},
|
|
{"360p", "640x360"},
|
|
}
|
|
|
|
for i, q := range qualities {
|
|
if q.Name != expected[i].name {
|
|
t.Errorf("quality %d: expected name %s, got %s", i, expected[i].name, q.Name)
|
|
}
|
|
if q.Resolution != expected[i].resolution {
|
|
t.Errorf("quality %d: expected resolution %s, got %s", i, expected[i].resolution, q.Resolution)
|
|
}
|
|
if q.Bitrate == "" {
|
|
t.Errorf("quality %d: expected non-empty bitrate", i)
|
|
}
|
|
if q.AudioRate == "" {
|
|
t.Errorf("quality %d: expected non-empty audio rate", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSetQualities(t *testing.T) {
|
|
svc := NewVideoTranscodeService("/tmp/test", nil)
|
|
custom := []VideoQuality{
|
|
{Name: "1080p", Resolution: "1920x1080", Bitrate: "5000k", AudioRate: "192k"},
|
|
}
|
|
svc.SetQualities(custom)
|
|
if len(svc.qualities) != 1 {
|
|
t.Errorf("expected 1 quality after SetQualities, got %d", len(svc.qualities))
|
|
}
|
|
if svc.qualities[0].Name != "1080p" {
|
|
t.Errorf("expected 1080p, got %s", svc.qualities[0].Name)
|
|
}
|
|
}
|
|
|
|
func TestTranscodeVideo_EmptyPath(t *testing.T) {
|
|
svc := NewVideoTranscodeService("/tmp/test", nil)
|
|
_, err := svc.TranscodeVideo(context.Background(), uuid.New(), "")
|
|
if err == nil {
|
|
t.Error("expected error for empty path")
|
|
}
|
|
}
|
|
|
|
func TestTranscodeVideo_NonExistentFile(t *testing.T) {
|
|
svc := NewVideoTranscodeService("/tmp/test", nil)
|
|
_, err := svc.TranscodeVideo(context.Background(), uuid.New(), "/nonexistent/path/video.mp4")
|
|
if err == nil {
|
|
t.Error("expected error for non-existent file")
|
|
}
|
|
}
|
|
|
|
func TestCleanupLessonDir(t *testing.T) {
|
|
svc := NewVideoTranscodeService("/tmp/test-cleanup", nil)
|
|
// Should not error on non-existent dir
|
|
err := svc.CleanupLessonDir(uuid.New())
|
|
if err != nil {
|
|
t.Errorf("expected no error for non-existent dir, got %v", err)
|
|
}
|
|
}
|