From bfffd541d8c2ad4df0294e2befad10bf08f82e94 Mon Sep 17 00:00:00 2001 From: Abyan Nawaz Date: Wed, 16 Oct 2024 21:15:51 -0400 Subject: [PATCH 1/3] Attemped unit tests + refactoring code --- .../handlers/friendship/friendship.go | 43 ++-- .../handlers/friendship/friendship_test.go | 229 ++++++++++++++++++ .../internal/handlers/friendship/routes.go | 4 +- 3 files changed, 259 insertions(+), 17 deletions(-) create mode 100644 backend/internal/handlers/friendship/friendship_test.go diff --git a/backend/internal/handlers/friendship/friendship.go b/backend/internal/handlers/friendship/friendship.go index f9ab67a..fcc28af 100644 --- a/backend/internal/handlers/friendship/friendship.go +++ b/backend/internal/handlers/friendship/friendship.go @@ -1,28 +1,43 @@ package friendship import ( - "fmt" "github.com/GenerateNU/nightlife/internal/models" "github.com/gofiber/fiber/v2" - "log" + "github.com/google/uuid" ) // POST endpoint to create friendship between two users in DB func (s *Service) CreateFriendship(c *fiber.Ctx) error { - fmt.Println("Creating a friendship") + var req models.Friendship - var req models.Friendship + // Parse the request body and check for errors + if err := c.BodyParser(&req); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Cannot parse JSON", + }) + } - if err := c.BodyParser(&req); err != nil { - log.Printf("Error parsing JSON: %v, Request: %+v", err, req) - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ - "error": "Cannot parse JSON", - }) - } + // Ensure both user ids are present + if req.UserID1 == uuid.Nil || req.UserID2 == uuid.Nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Both user_id1 and user_id2 are required", + }) + } - if err := s.store.CreateFriendship(c.Context(), req); err != nil { - return err - } + // Set default friendship status if not provided (just an edge case) + if req.FriendshipStatus == "" { + req.FriendshipStatus = models.Pending + } - return c.Status(fiber.StatusCreated).JSON(req) + // Call CreateFriendship method to interact with db + if err := s.store.CreateFriendship(c.Context(), req); err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": "Failed to create friendship", + }) + } + + // On success, return 201 and req body + return c.Status(fiber.StatusCreated).JSON(req) } + + diff --git a/backend/internal/handlers/friendship/friendship_test.go b/backend/internal/handlers/friendship/friendship_test.go new file mode 100644 index 0000000..e094b94 --- /dev/null +++ b/backend/internal/handlers/friendship/friendship_test.go @@ -0,0 +1,229 @@ + package friendship + + import ( + "bytes" + "context" + "encoding/json" + "errors" + "github.com/GenerateNU/nightlife/internal/models" + "github.com/gofiber/fiber/v2" + "github.com/google/uuid" + "net/http" + "net/http/httptest" + "testing" + ) + + // Mock Service structure + type MockStore struct { + // Add fields for your mocked functions + CreateFriendshipFn func(ctx context.Context, friendship models.Friendship) error + CreatePreferencesFn func(ctx context.Context, preferences models.Preferences) error + UpdateProfilePreferencesFn func(ctx context.Context, userID uuid.UUID, pref1, pref2, pref3, pref4 string) error + DeleteAccountFn func(ctx context.Context, userID uuid.UUID) error + RemoveFriendFn func(ctx context.Context, userID uuid.UUID, friendID string) error + GetProfileByColumnFn func(ctx context.Context, column, value string) (models.Profile, error) + GetAllUsersFn func(ctx context.Context) ([]models.Profile, error) + GetAllUserRatingsFn func(ctx context.Context, userID uuid.UUID) ([]models.UserRating, error) + DeleteVenueFn func(ctx context.Context, venueID uuid.UUID) error + DeleteReviewForVenueFn func(ctx context.Context, reviewID int8) error + GetAllVenueRatingsFn func(ctx context.Context, venueID uuid.UUID) ([]models.VenueRatings, error) + GetAllTestsFn func(ctx context.Context) ([]models.Test, error) + } + + // Implement all the Store interface methods for the mock + + // Implement the CreateFriendship method for the MockStore + func (m *MockStore) CreateFriendship(ctx context.Context, friendship models.Friendship) error { + if m.CreateFriendshipFn != nil { + return m.CreateFriendshipFn(ctx, friendship) + } + return nil + } + + // Implement the CreatePreferences method for the MockStore + func (m *MockStore) CreatePreferences(ctx context.Context, preferences models.Preferences) error { + if m.CreatePreferencesFn != nil { + return m.CreatePreferencesFn(ctx, preferences) + } + return nil + } + + // Implement the UpdateProfilePreferences method for the MockStore + func (m *MockStore) UpdateProfilePreferences(ctx context.Context, userID uuid.UUID, pref1, pref2, pref3, pref4 string) error { + if m.UpdateProfilePreferencesFn != nil { + return m.UpdateProfilePreferencesFn(ctx, userID, pref1, pref2, pref3, pref4) + } + return nil + } + + // Implement the DeleteAccount method for the MockStore + func (m *MockStore) DeleteAccount(ctx context.Context, userID uuid.UUID) error { + if m.DeleteAccountFn != nil { + return m.DeleteAccountFn(ctx, userID) + } + return nil + } + + // Implement the RemoveFriend method for the MockStore + func (m *MockStore) RemoveFriend(ctx context.Context, userID uuid.UUID, friendID string) error { + if m.RemoveFriendFn != nil { + return m.RemoveFriendFn(ctx, userID, friendID) + } + return nil + } + + // Implement the GetProfileByColumn method for the MockStore + func (m *MockStore) GetProfileByColumn(ctx context.Context, column, value string) (models.Profile, error) { + if m.GetProfileByColumnFn != nil { + return m.GetProfileByColumnFn(ctx, column, value) + } + return models.Profile{}, nil + } + + // Implement the GetAllUsers method for the MockStore + func (m *MockStore) GetAllUsers(ctx context.Context) ([]models.Profile, error) { + if m.GetAllUsersFn != nil { + return m.GetAllUsersFn(ctx) + } + return nil, nil + } + + // Implement the GetAllUserRatings method for the MockStore + func (m *MockStore) GetAllUserRatings(ctx context.Context, userID uuid.UUID) ([]models.UserRating, error) { + if m.GetAllUserRatingsFn != nil { + return m.GetAllUserRatingsFn(ctx, userID) + } + return nil, nil + } + + // Implement the DeleteVenue method for the MockStore + func (m *MockStore) DeleteVenue(ctx context.Context, venueID uuid.UUID) error { + if m.DeleteVenueFn != nil { + return m.DeleteVenueFn(ctx, venueID) + } + return nil + } + + // Implement the DeleteReviewForVenue method for the MockStore + func (m *MockStore) DeleteReviewForVenue(ctx context.Context, reviewID int8) error { + if m.DeleteReviewForVenueFn != nil { + return m.DeleteReviewForVenueFn(ctx, reviewID) + } + return nil + } + + // Implement the GetAllVenueRatings method for the MockStore + func (m *MockStore) GetAllVenueRatings(ctx context.Context, venueID uuid.UUID) ([]models.VenueRatings, error) { + if m.GetAllVenueRatingsFn != nil { + return m.GetAllVenueRatingsFn(ctx, venueID) + } + return nil, nil + } + + // Implement the GetAllTests method for the MockStore + func (m *MockStore) GetAllTests(ctx context.Context) ([]models.Test, error) { + if m.GetAllTestsFn != nil { + return m.GetAllTestsFn(ctx) + } + return nil, nil + } + + // Implement the Close method for the MockStore to satisfy the storage.Storage interface + func (m *MockStore) Close() { + + } + + // Test for the POST endpoint CreateFriendship + func TestCreateFriendship(t *testing.T) { + // Create a new Fiber app + app := fiber.New() + + // Set up the mock store + mockStore := &MockStore{} + + // Set up the service with the mock store + service := &Service{ + store: mockStore, + } + + // Add the route to Fiber + app.Post("/add-friend", service.CreateFriendship) + + // Define the test cases + tests := []struct { + name string + inputJSON string + mockResponse error + expectedStatus int + expectedBody string + }{ + { + name: "successful creation", + inputJSON: `{"user_id1": "00000000-0000-0000-0000-000000000001", "user_id2": "00000000-0000-0000-0000-000000000002"}`, + mockResponse: nil, + expectedStatus: fiber.StatusCreated, + expectedBody: `{"user_id1":"00000000-0000-0000-0000-000000000001","user_id2":"00000000-0000-0000-0000-000000000002"}`, + }, + { + name: "invalid JSON body", + inputJSON: `{"invalid_json"}`, + mockResponse: nil, + expectedStatus: fiber.StatusBadRequest, + expectedBody: `{"error":"Cannot parse JSON"}`, + }, + { + name: "store error", + inputJSON: `{"user_id1": "00000000-0000-0000-0000-000000000001", "user_id2": "00000000-0000-0000-0000-000000000002"}`, + mockResponse: errors.New("db error"), + expectedStatus: fiber.StatusInternalServerError, + expectedBody: `{"error":"Failed to create friendship"}`, + }, + } + + // Iterate over the test cases + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Mock the CreateFriendship function behavior based on the test case + mockStore.CreateFriendshipFn = func(ctx context.Context, friendship models.Friendship) error { + return tt.mockResponse + } + + // Create the HTTP request + req := httptest.NewRequest(http.MethodPost, "/add-friend", bytes.NewBuffer([]byte(tt.inputJSON))) + req.Header.Set("Content-Type", "application/json") + + // Test the request using Fiber's app.Test() method + resp, err := app.Test(req, -1) + if err != nil { + t.Fatalf("Error making the request: %v", err) + } + + // Check the status code + if resp.StatusCode != tt.expectedStatus { + t.Errorf("expected status %d, got %d", tt.expectedStatus, resp.StatusCode) + } + + // Check the response body + if tt.expectedBody != "" { + var response map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + t.Fatalf("Error unmarshalling response: %v", err) + } + + // Convert the expected response from string to a map for comparison + expectedResponse := make(map[string]interface{}) + if err := json.Unmarshal([]byte(tt.expectedBody), &expectedResponse); err != nil { + t.Fatalf("Error unmarshalling expected body: %v", err) + } + + // Compare the actual response to the expected one + for key, value := range expectedResponse { + if response[key] != value { + t.Errorf("expected %v for key %v, got %v", value, key, response[key]) + } + } + } + }) + } + } + \ No newline at end of file diff --git a/backend/internal/handlers/friendship/routes.go b/backend/internal/handlers/friendship/routes.go index 652f673..39ba487 100644 --- a/backend/internal/handlers/friendship/routes.go +++ b/backend/internal/handlers/friendship/routes.go @@ -1,7 +1,6 @@ package friendship import ( - //"github.com/GenerateNU/nightlife/internal/auth" "github.com/GenerateNU/nightlife/internal/types" "github.com/gofiber/fiber/v2" ) @@ -13,9 +12,8 @@ func Routes(app *fiber.App, params types.Params) { //create a grouping protected := app.Group("/friendships") - //.Use(auth.Protected(¶ms.Supabase)) //create a route - protected.Post("/api/friendship", service.CreateFriendship) + protected.Post("/add-friend", service.CreateFriendship) } From 378b48dcac8289deea6b2d3633bbf4a281bf14a7 Mon Sep 17 00:00:00 2001 From: Abyan Nawaz Date: Wed, 16 Oct 2024 21:49:35 -0400 Subject: [PATCH 2/3] lint fix --- backend/internal/handlers/friendship/friendship_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/internal/handlers/friendship/friendship_test.go b/backend/internal/handlers/friendship/friendship_test.go index e094b94..d9291f1 100644 --- a/backend/internal/handlers/friendship/friendship_test.go +++ b/backend/internal/handlers/friendship/friendship_test.go @@ -184,7 +184,7 @@ for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Mock the CreateFriendship function behavior based on the test case - mockStore.CreateFriendshipFn = func(ctx context.Context, friendship models.Friendship) error { + mockStore.CreateFriendshipFn = func(_ context.Context, friendship models.Friendship) error { return tt.mockResponse } From cfabfaf5d2362a4203d144467b8e243406e85a30 Mon Sep 17 00:00:00 2001 From: Abyan Nawaz Date: Wed, 16 Oct 2024 21:51:10 -0400 Subject: [PATCH 3/3] linting fix pt 2 --- .../handlers/friendship/friendship_test.go | 392 +++++++++--------- 1 file changed, 196 insertions(+), 196 deletions(-) diff --git a/backend/internal/handlers/friendship/friendship_test.go b/backend/internal/handlers/friendship/friendship_test.go index d9291f1..873f669 100644 --- a/backend/internal/handlers/friendship/friendship_test.go +++ b/backend/internal/handlers/friendship/friendship_test.go @@ -1,229 +1,229 @@ - package friendship - - import ( - "bytes" - "context" - "encoding/json" - "errors" - "github.com/GenerateNU/nightlife/internal/models" - "github.com/gofiber/fiber/v2" - "github.com/google/uuid" - "net/http" - "net/http/httptest" - "testing" - ) - - // Mock Service structure - type MockStore struct { - // Add fields for your mocked functions - CreateFriendshipFn func(ctx context.Context, friendship models.Friendship) error - CreatePreferencesFn func(ctx context.Context, preferences models.Preferences) error - UpdateProfilePreferencesFn func(ctx context.Context, userID uuid.UUID, pref1, pref2, pref3, pref4 string) error - DeleteAccountFn func(ctx context.Context, userID uuid.UUID) error - RemoveFriendFn func(ctx context.Context, userID uuid.UUID, friendID string) error - GetProfileByColumnFn func(ctx context.Context, column, value string) (models.Profile, error) - GetAllUsersFn func(ctx context.Context) ([]models.Profile, error) - GetAllUserRatingsFn func(ctx context.Context, userID uuid.UUID) ([]models.UserRating, error) - DeleteVenueFn func(ctx context.Context, venueID uuid.UUID) error - DeleteReviewForVenueFn func(ctx context.Context, reviewID int8) error - GetAllVenueRatingsFn func(ctx context.Context, venueID uuid.UUID) ([]models.VenueRatings, error) - GetAllTestsFn func(ctx context.Context) ([]models.Test, error) +package friendship + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "testing" + + "github.com/GenerateNU/nightlife/internal/models" + "github.com/gofiber/fiber/v2" + "github.com/google/uuid" +) + +// Mock Service structure +type MockStore struct { + // Add fields for your mocked functions + CreateFriendshipFn func(ctx context.Context, friendship models.Friendship) error + CreatePreferencesFn func(ctx context.Context, preferences models.Preferences) error + UpdateProfilePreferencesFn func(ctx context.Context, userID uuid.UUID, pref1, pref2, pref3, pref4 string) error + DeleteAccountFn func(ctx context.Context, userID uuid.UUID) error + RemoveFriendFn func(ctx context.Context, userID uuid.UUID, friendID string) error + GetProfileByColumnFn func(ctx context.Context, column, value string) (models.Profile, error) + GetAllUsersFn func(ctx context.Context) ([]models.Profile, error) + GetAllUserRatingsFn func(ctx context.Context, userID uuid.UUID) ([]models.UserRating, error) + DeleteVenueFn func(ctx context.Context, venueID uuid.UUID) error + DeleteReviewForVenueFn func(ctx context.Context, reviewID int8) error + GetAllVenueRatingsFn func(ctx context.Context, venueID uuid.UUID) ([]models.VenueRatings, error) + GetAllTestsFn func(ctx context.Context) ([]models.Test, error) +} + +// Implement all the Store interface methods for the mock + +// Implement the CreateFriendship method for the MockStore +func (m *MockStore) CreateFriendship(ctx context.Context, friendship models.Friendship) error { + if m.CreateFriendshipFn != nil { + return m.CreateFriendshipFn(ctx, friendship) } + return nil +} - // Implement all the Store interface methods for the mock - - // Implement the CreateFriendship method for the MockStore - func (m *MockStore) CreateFriendship(ctx context.Context, friendship models.Friendship) error { - if m.CreateFriendshipFn != nil { - return m.CreateFriendshipFn(ctx, friendship) - } - return nil +// Implement the CreatePreferences method for the MockStore +func (m *MockStore) CreatePreferences(ctx context.Context, preferences models.Preferences) error { + if m.CreatePreferencesFn != nil { + return m.CreatePreferencesFn(ctx, preferences) } + return nil +} - // Implement the CreatePreferences method for the MockStore - func (m *MockStore) CreatePreferences(ctx context.Context, preferences models.Preferences) error { - if m.CreatePreferencesFn != nil { - return m.CreatePreferencesFn(ctx, preferences) - } - return nil +// Implement the UpdateProfilePreferences method for the MockStore +func (m *MockStore) UpdateProfilePreferences(ctx context.Context, userID uuid.UUID, pref1, pref2, pref3, pref4 string) error { + if m.UpdateProfilePreferencesFn != nil { + return m.UpdateProfilePreferencesFn(ctx, userID, pref1, pref2, pref3, pref4) } + return nil +} - // Implement the UpdateProfilePreferences method for the MockStore - func (m *MockStore) UpdateProfilePreferences(ctx context.Context, userID uuid.UUID, pref1, pref2, pref3, pref4 string) error { - if m.UpdateProfilePreferencesFn != nil { - return m.UpdateProfilePreferencesFn(ctx, userID, pref1, pref2, pref3, pref4) - } - return nil +// Implement the DeleteAccount method for the MockStore +func (m *MockStore) DeleteAccount(ctx context.Context, userID uuid.UUID) error { + if m.DeleteAccountFn != nil { + return m.DeleteAccountFn(ctx, userID) } + return nil +} - // Implement the DeleteAccount method for the MockStore - func (m *MockStore) DeleteAccount(ctx context.Context, userID uuid.UUID) error { - if m.DeleteAccountFn != nil { - return m.DeleteAccountFn(ctx, userID) - } - return nil +// Implement the RemoveFriend method for the MockStore +func (m *MockStore) RemoveFriend(ctx context.Context, userID uuid.UUID, friendID string) error { + if m.RemoveFriendFn != nil { + return m.RemoveFriendFn(ctx, userID, friendID) } + return nil +} - // Implement the RemoveFriend method for the MockStore - func (m *MockStore) RemoveFriend(ctx context.Context, userID uuid.UUID, friendID string) error { - if m.RemoveFriendFn != nil { - return m.RemoveFriendFn(ctx, userID, friendID) - } - return nil +// Implement the GetProfileByColumn method for the MockStore +func (m *MockStore) GetProfileByColumn(ctx context.Context, column, value string) (models.Profile, error) { + if m.GetProfileByColumnFn != nil { + return m.GetProfileByColumnFn(ctx, column, value) } + return models.Profile{}, nil +} - // Implement the GetProfileByColumn method for the MockStore - func (m *MockStore) GetProfileByColumn(ctx context.Context, column, value string) (models.Profile, error) { - if m.GetProfileByColumnFn != nil { - return m.GetProfileByColumnFn(ctx, column, value) - } - return models.Profile{}, nil +// Implement the GetAllUsers method for the MockStore +func (m *MockStore) GetAllUsers(ctx context.Context) ([]models.Profile, error) { + if m.GetAllUsersFn != nil { + return m.GetAllUsersFn(ctx) } + return nil, nil +} - // Implement the GetAllUsers method for the MockStore - func (m *MockStore) GetAllUsers(ctx context.Context) ([]models.Profile, error) { - if m.GetAllUsersFn != nil { - return m.GetAllUsersFn(ctx) - } - return nil, nil +// Implement the GetAllUserRatings method for the MockStore +func (m *MockStore) GetAllUserRatings(ctx context.Context, userID uuid.UUID) ([]models.UserRating, error) { + if m.GetAllUserRatingsFn != nil { + return m.GetAllUserRatingsFn(ctx, userID) } + return nil, nil +} - // Implement the GetAllUserRatings method for the MockStore - func (m *MockStore) GetAllUserRatings(ctx context.Context, userID uuid.UUID) ([]models.UserRating, error) { - if m.GetAllUserRatingsFn != nil { - return m.GetAllUserRatingsFn(ctx, userID) - } - return nil, nil +// Implement the DeleteVenue method for the MockStore +func (m *MockStore) DeleteVenue(ctx context.Context, venueID uuid.UUID) error { + if m.DeleteVenueFn != nil { + return m.DeleteVenueFn(ctx, venueID) } + return nil +} - // Implement the DeleteVenue method for the MockStore - func (m *MockStore) DeleteVenue(ctx context.Context, venueID uuid.UUID) error { - if m.DeleteVenueFn != nil { - return m.DeleteVenueFn(ctx, venueID) - } - return nil +// Implement the DeleteReviewForVenue method for the MockStore +func (m *MockStore) DeleteReviewForVenue(ctx context.Context, reviewID int8) error { + if m.DeleteReviewForVenueFn != nil { + return m.DeleteReviewForVenueFn(ctx, reviewID) } + return nil +} - // Implement the DeleteReviewForVenue method for the MockStore - func (m *MockStore) DeleteReviewForVenue(ctx context.Context, reviewID int8) error { - if m.DeleteReviewForVenueFn != nil { - return m.DeleteReviewForVenueFn(ctx, reviewID) - } - return nil +// Implement the GetAllVenueRatings method for the MockStore +func (m *MockStore) GetAllVenueRatings(ctx context.Context, venueID uuid.UUID) ([]models.VenueRatings, error) { + if m.GetAllVenueRatingsFn != nil { + return m.GetAllVenueRatingsFn(ctx, venueID) } + return nil, nil +} - // Implement the GetAllVenueRatings method for the MockStore - func (m *MockStore) GetAllVenueRatings(ctx context.Context, venueID uuid.UUID) ([]models.VenueRatings, error) { - if m.GetAllVenueRatingsFn != nil { - return m.GetAllVenueRatingsFn(ctx, venueID) - } - return nil, nil +// Implement the GetAllTests method for the MockStore +func (m *MockStore) GetAllTests(ctx context.Context) ([]models.Test, error) { + if m.GetAllTestsFn != nil { + return m.GetAllTestsFn(ctx) } + return nil, nil +} + +// Implement the Close method for the MockStore to satisfy the storage.Storage interface +func (m *MockStore) Close() { + +} + +// Test for the POST endpoint CreateFriendship +func TestCreateFriendship(t *testing.T) { + // Create a new Fiber app + app := fiber.New() + + // Set up the mock store + mockStore := &MockStore{} - // Implement the GetAllTests method for the MockStore - func (m *MockStore) GetAllTests(ctx context.Context) ([]models.Test, error) { - if m.GetAllTestsFn != nil { - return m.GetAllTestsFn(ctx) - } - return nil, nil + // Set up the service with the mock store + service := &Service{ + store: mockStore, } - // Implement the Close method for the MockStore to satisfy the storage.Storage interface - func (m *MockStore) Close() { - + // Add the route to Fiber + app.Post("/add-friend", service.CreateFriendship) + + // Define the test cases + tests := []struct { + name string + inputJSON string + mockResponse error + expectedStatus int + expectedBody string + }{ + { + name: "successful creation", + inputJSON: `{"user_id1": "00000000-0000-0000-0000-000000000001", "user_id2": "00000000-0000-0000-0000-000000000002"}`, + mockResponse: nil, + expectedStatus: fiber.StatusCreated, + expectedBody: `{"user_id1":"00000000-0000-0000-0000-000000000001","user_id2":"00000000-0000-0000-0000-000000000002"}`, + }, + { + name: "invalid JSON body", + inputJSON: `{"invalid_json"}`, + mockResponse: nil, + expectedStatus: fiber.StatusBadRequest, + expectedBody: `{"error":"Cannot parse JSON"}`, + }, + { + name: "store error", + inputJSON: `{"user_id1": "00000000-0000-0000-0000-000000000001", "user_id2": "00000000-0000-0000-0000-000000000002"}`, + mockResponse: errors.New("db error"), + expectedStatus: fiber.StatusInternalServerError, + expectedBody: `{"error":"Failed to create friendship"}`, + }, } - // Test for the POST endpoint CreateFriendship - func TestCreateFriendship(t *testing.T) { - // Create a new Fiber app - app := fiber.New() - - // Set up the mock store - mockStore := &MockStore{} - - // Set up the service with the mock store - service := &Service{ - store: mockStore, - } - - // Add the route to Fiber - app.Post("/add-friend", service.CreateFriendship) - - // Define the test cases - tests := []struct { - name string - inputJSON string - mockResponse error - expectedStatus int - expectedBody string - }{ - { - name: "successful creation", - inputJSON: `{"user_id1": "00000000-0000-0000-0000-000000000001", "user_id2": "00000000-0000-0000-0000-000000000002"}`, - mockResponse: nil, - expectedStatus: fiber.StatusCreated, - expectedBody: `{"user_id1":"00000000-0000-0000-0000-000000000001","user_id2":"00000000-0000-0000-0000-000000000002"}`, - }, - { - name: "invalid JSON body", - inputJSON: `{"invalid_json"}`, - mockResponse: nil, - expectedStatus: fiber.StatusBadRequest, - expectedBody: `{"error":"Cannot parse JSON"}`, - }, - { - name: "store error", - inputJSON: `{"user_id1": "00000000-0000-0000-0000-000000000001", "user_id2": "00000000-0000-0000-0000-000000000002"}`, - mockResponse: errors.New("db error"), - expectedStatus: fiber.StatusInternalServerError, - expectedBody: `{"error":"Failed to create friendship"}`, - }, - } - - // Iterate over the test cases - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Mock the CreateFriendship function behavior based on the test case - mockStore.CreateFriendshipFn = func(_ context.Context, friendship models.Friendship) error { - return tt.mockResponse + // Iterate over the test cases + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Mock the CreateFriendship function behavior based on the test case + mockStore.CreateFriendshipFn = func(_ context.Context, _ models.Friendship) error { + return tt.mockResponse + } + + // Create the HTTP request + req := httptest.NewRequest(http.MethodPost, "/add-friend", bytes.NewBuffer([]byte(tt.inputJSON))) + req.Header.Set("Content-Type", "application/json") + + // Test the request using Fiber's app.Test() method + resp, err := app.Test(req, -1) + if err != nil { + t.Fatalf("Error making the request: %v", err) + } + + // Check the status code + if resp.StatusCode != tt.expectedStatus { + t.Errorf("expected status %d, got %d", tt.expectedStatus, resp.StatusCode) + } + + // Check the response body + if tt.expectedBody != "" { + var response map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + t.Fatalf("Error unmarshalling response: %v", err) } - - // Create the HTTP request - req := httptest.NewRequest(http.MethodPost, "/add-friend", bytes.NewBuffer([]byte(tt.inputJSON))) - req.Header.Set("Content-Type", "application/json") - - // Test the request using Fiber's app.Test() method - resp, err := app.Test(req, -1) - if err != nil { - t.Fatalf("Error making the request: %v", err) - } - - // Check the status code - if resp.StatusCode != tt.expectedStatus { - t.Errorf("expected status %d, got %d", tt.expectedStatus, resp.StatusCode) + + // Convert the expected response from string to a map for comparison + expectedResponse := make(map[string]interface{}) + if err := json.Unmarshal([]byte(tt.expectedBody), &expectedResponse); err != nil { + t.Fatalf("Error unmarshalling expected body: %v", err) } - - // Check the response body - if tt.expectedBody != "" { - var response map[string]interface{} - if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { - t.Fatalf("Error unmarshalling response: %v", err) - } - - // Convert the expected response from string to a map for comparison - expectedResponse := make(map[string]interface{}) - if err := json.Unmarshal([]byte(tt.expectedBody), &expectedResponse); err != nil { - t.Fatalf("Error unmarshalling expected body: %v", err) - } - - // Compare the actual response to the expected one - for key, value := range expectedResponse { - if response[key] != value { - t.Errorf("expected %v for key %v, got %v", value, key, response[key]) - } + + // Compare the actual response to the expected one + for key, value := range expectedResponse { + if response[key] != value { + t.Errorf("expected %v for key %v, got %v", value, key, response[key]) } } - }) - } + } + }) } - \ No newline at end of file +}