package handlers import ( "encoding/json" "net/http" "net/http/httptest" "strings" "testing" "github.com/gin-gonic/gin" "github.com/google/uuid" "go.uber.org/zap" "veza-backend-api/internal/core/education" ) func TestNewEducationHandler(t *testing.T) { logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) if handler == nil { t.Fatal("expected non-nil handler") } if handler.service == nil { t.Error("expected non-nil service") } } func TestEducationHandler_CreateCourse_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodPost, "/courses", strings.NewReader(`{}`)) c.Request.Header.Set("Content-Type", "application/json") handler.CreateCourse(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_CreateCourse_InvalidBody(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("user_id", uuid.New()) c.Request = httptest.NewRequest(http.MethodPost, "/courses", strings.NewReader(`{}`)) c.Request.Header.Set("Content-Type", "application/json") handler.CreateCourse(c) var resp map[string]interface{} if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatalf("failed to decode response: %v", err) } if resp["success"] != false { t.Error("expected success=false for invalid request") } } func TestEducationHandler_GetCourse_InvalidID(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Params = gin.Params{{Key: "id", Value: "not-a-uuid"}} c.Request = httptest.NewRequest(http.MethodGet, "/courses/not-a-uuid", nil) handler.GetCourse(c) var resp map[string]interface{} if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatalf("failed to decode response: %v", err) } if resp["success"] != false { t.Error("expected success=false for invalid ID") } } func TestEducationHandler_GetCourseBySlug_EmptySlug(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Params = gin.Params{{Key: "slug", Value: ""}} c.Request = httptest.NewRequest(http.MethodGet, "/courses/slug/", nil) handler.GetCourseBySlug(c) var resp map[string]interface{} if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatalf("failed to decode response: %v", err) } if resp["success"] != false { t.Error("expected success=false for empty slug") } } func TestEducationHandler_Enroll_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodPost, "/courses/123/enroll", strings.NewReader(`{}`)) c.Request.Header.Set("Content-Type", "application/json") handler.Enroll(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_UpdateProgress_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodPost, "/lessons/123/progress", strings.NewReader(`{}`)) c.Request.Header.Set("Content-Type", "application/json") handler.UpdateProgress(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_IssueCertificate_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodPost, "/courses/123/certificate", nil) handler.IssueCertificate(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_CreateReview_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodPost, "/courses/123/reviews", strings.NewReader(`{}`)) c.Request.Header.Set("Content-Type", "application/json") handler.CreateReview(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_GetMyEnrollments_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodGet, "/enrollments", nil) handler.GetMyEnrollments(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_UploadLessonVideo_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodPost, "/courses/123/lessons/456/video", nil) c.Request.Header.Set("Content-Type", "multipart/form-data") handler.UploadLessonVideo(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_UploadLessonVideo_InvalidCourseID(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("user_id", uuid.New()) c.Params = gin.Params{{Key: "id", Value: "not-a-uuid"}} c.Request = httptest.NewRequest(http.MethodPost, "/courses/not-a-uuid/lessons/456/video", nil) handler.UploadLessonVideo(c) var resp map[string]interface{} if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatalf("failed to decode response: %v", err) } if resp["success"] != false { t.Error("expected success=false for invalid course ID") } } func TestEducationHandler_UploadLessonVideo_InvalidLessonID(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Set("user_id", uuid.New()) c.Params = gin.Params{ {Key: "id", Value: uuid.New().String()}, {Key: "lesson_id", Value: "not-a-uuid"}, } c.Request = httptest.NewRequest(http.MethodPost, "/courses/123/lessons/not-a-uuid/video", nil) handler.UploadLessonVideo(c) var resp map[string]interface{} if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatalf("failed to decode response: %v", err) } if resp["success"] != false { t.Error("expected success=false for invalid lesson ID") } } func TestEducationHandler_DeleteLesson_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodDelete, "/courses/123/lessons/456", nil) handler.DeleteLesson(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_ReorderLessons_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodPost, "/courses/123/lessons/reorder", strings.NewReader(`{}`)) c.Request.Header.Set("Content-Type", "application/json") handler.ReorderLessons(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_GetCourseProgress_NoAuth(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodGet, "/courses/123/progress", nil) handler.GetCourseProgress(c) if w.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", w.Code) } } func TestEducationHandler_VerifyCertificate_EmptyCode(t *testing.T) { gin.SetMode(gin.TestMode) logger := zap.NewNop() svc := education.NewService(nil, logger) handler := NewEducationHandler(svc, logger) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Params = gin.Params{{Key: "code", Value: ""}} c.Request = httptest.NewRequest(http.MethodGet, "/certificates/", nil) handler.VerifyCertificate(c) var resp map[string]interface{} if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatalf("failed to decode response: %v", err) } if resp["success"] != false { t.Error("expected success=false for empty code") } }