package test import ( "encoding/json" "errors" "fmt" "net/http" "testing" "github.com/gofiber/fiber/v2" "gorm.io/gorm" "gitlab.com/mbugroup/lti-api.git/internal/entities" ) func TestFcrIntegration(t *testing.T) { app, db := setupIntegrationApp(t) t.Run("creating fcr without standards fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/fcrs", map[string]any{ "name": "FCR Alpha", }) if resp.StatusCode != fiber.StatusBadRequest { t.Fatalf("expected 400 when standards missing, got %d: %s", resp.StatusCode, string(body)) } }) initialStandards := []map[string]any{ { "weight": 7.2, "fcr_number": 400.0, "mortality": 12.0, }, { "weight": 7.4, "fcr_number": 410.0, "mortality": 11.5, }, } var fcrID uint t.Run("creating fcr succeeds", func(t *testing.T) { fcrID = createFcr(t, app, "FCR Layer", initialStandards) fcr := fetchFcr(t, db, fcrID) if fcr.Name != "FCR Layer" { t.Fatalf("expected name FCR Layer, got %q", fcr.Name) } if len(fcr.Standards) != len(initialStandards) { t.Fatalf("expected %d standards, got %d", len(initialStandards), len(fcr.Standards)) } if fcr.CreatedBy != 1 { t.Fatalf("expected created_by 1, got %d", fcr.CreatedBy) } }) t.Run("creating duplicate fcr name fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/fcrs", map[string]any{ "name": "FCR Layer", "fcr_standards": initialStandards, }) if resp.StatusCode != fiber.StatusConflict { t.Fatalf("expected 409 when creating duplicate, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("getting fcr detail succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodGet, fmt.Sprintf("/api/master-data/fcrs/%d", fcrID), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when fetching fcr, got %d: %s", resp.StatusCode, string(body)) } var payload struct { Data struct { Id uint `json:"id"` Name string `json:"name"` FcrStandards []map[string]any `json:"fcr_standards"` } `json:"data"` } if err := json.Unmarshal(body, &payload); err != nil { t.Fatalf("failed to parse fcr detail: %v", err) } if payload.Data.Id != fcrID { t.Fatalf("expected id %d, got %d", fcrID, payload.Data.Id) } if len(payload.Data.FcrStandards) != len(initialStandards) { t.Fatalf("expected %d standards in response, got %d", len(initialStandards), len(payload.Data.FcrStandards)) } }) updatedStandards := []map[string]any{ { "weight": 7.2, "fcr_number": 395.0, "mortality": 10.0, }, { "weight": 7.5, "fcr_number": 420.0, "mortality": 13.0, }, } t.Run("updating fcr name and standards succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/fcrs/%d", fcrID), map[string]any{ "name": "FCR Layer Updated", "fcr_standards": updatedStandards, }) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when updating fcr, got %d: %s", resp.StatusCode, string(body)) } var payload struct { Data struct { Name string `json:"name"` FcrStandards []map[string]any `json:"fcr_standards"` } `json:"data"` } if err := json.Unmarshal(body, &payload); err != nil { t.Fatalf("failed to parse update response: %v", err) } if payload.Data.Name != "FCR Layer Updated" { t.Fatalf("expected updated name, got %q", payload.Data.Name) } if len(payload.Data.FcrStandards) != len(updatedStandards) { t.Fatalf("expected %d standards after update, got %d", len(updatedStandards), len(payload.Data.FcrStandards)) } fcr := fetchFcr(t, db, fcrID) if fcr.Name != "FCR Layer Updated" { t.Fatalf("expected persisted name FCR Layer Updated, got %q", fcr.Name) } if len(fcr.Standards) != len(updatedStandards) { t.Fatalf("expected %d persisted standards, got %d", len(updatedStandards), len(fcr.Standards)) } if fcr.Standards[0].FcrNumber != 395.0 { t.Fatalf("expected first standard fcr_number 395, got %f", fcr.Standards[0].FcrNumber) } }) var otherFcrID uint t.Run("creating another fcr for duplicate update", func(t *testing.T) { otherFcrID = createFcr(t, app, "FCR Grower", []map[string]any{ { "weight": 8.0, "fcr_number": 430.0, "mortality": 9.0, }, }) if otherFcrID == 0 { t.Fatal("expected other fcr id to be non zero") } }) t.Run("updating fcr with duplicate name fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/fcrs/%d", fcrID), map[string]any{ "name": "FCR Grower", }) if resp.StatusCode != fiber.StatusConflict { t.Fatalf("expected 409 when renaming to existing fcr, got %d: %s", resp.StatusCode, string(body)) } fcr := fetchFcr(t, db, fcrID) if fcr.Name != "FCR Layer Updated" { t.Fatalf("expected name unchanged after failed update, got %q", fcr.Name) } }) t.Run("updating fcr with invalid standards fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/fcrs/%d", fcrID), map[string]any{ "fcr_standards": []map[string]any{ { "weight": -1, "fcr_number": 300, "mortality": 5, }, }, }) if resp.StatusCode != fiber.StatusBadRequest { t.Fatalf("expected 400 when updating with invalid standard, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("deleting fcr succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodDelete, fmt.Sprintf("/api/master-data/fcrs/%d", fcrID), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when deleting fcr, got %d: %s", resp.StatusCode, string(body)) } var fcr entities.Fcr if err := db.First(&fcr, fcrID).Error; !errors.Is(err, gorm.ErrRecordNotFound) { t.Fatalf("expected fcr to be deleted, got error %v", err) } var standardsCount int64 if err := db.Model(&entities.FcrStandard{}).Where("fcr_id = ?", fcrID).Count(&standardsCount).Error; err != nil { t.Fatalf("failed counting standards: %v", err) } if standardsCount != 0 { t.Fatalf("expected standards removed, found %d", standardsCount) } }) t.Run("deleting fcr again returns 404", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodDelete, fmt.Sprintf("/api/master-data/fcrs/%d", fcrID), nil) if resp.StatusCode != fiber.StatusNotFound { t.Fatalf("expected 404 when deleting missing fcr, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("getting deleted fcr returns 404", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodGet, fmt.Sprintf("/api/master-data/fcrs/%d", fcrID), nil) if resp.StatusCode != fiber.StatusNotFound { t.Fatalf("expected 404 when fetching deleted fcr, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("cleanup other fcr", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodDelete, fmt.Sprintf("/api/master-data/fcrs/%d", otherFcrID), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when deleting other fcr, got %d: %s", resp.StatusCode, string(body)) } }) }