package test import ( "encoding/json" "errors" "fmt" "net/http" "strings" "testing" "github.com/gofiber/fiber/v2" "gorm.io/gorm" "gitlab.com/mbugroup/lti-api.git/internal/entities" "gitlab.com/mbugroup/lti-api.git/internal/utils" ) func TestSupplierIntegration(t *testing.T) { app, db := setupIntegrationApp(t) t.Run("creating supplier with invalid type fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/suppliers", map[string]any{ "name": "Invalid Supplier", "alias": "inv01", "pic": "Jane Doe", "type": "random-type", "category": utils.SupplierCategoryBOP, "hatchery": "Hatchery X", "phone": "081234567891", "email": "invalid@supplier.com", "address": "Somewhere", "npwp": "NPWP-INVALID", "account_number": "ACC-INVALID", "due_date": 30, }) if resp.StatusCode != fiber.StatusBadRequest { t.Fatalf("expected 400 when type is invalid, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("creating supplier with invalid category fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/suppliers", map[string]any{ "name": "Invalid Category Supplier", "alias": "cat01", "pic": "Jane Doe", "type": utils.CustomerSupplierTypeBisnis, "category": "invalid", "phone": "081234567892", "email": "invalid-category@supplier.com", "address": "Somewhere", "due_date": 30, }) if resp.StatusCode != fiber.StatusBadRequest { t.Fatalf("expected 400 when category is invalid, got %d: %s", resp.StatusCode, string(body)) } }) const supplierName = "Supplier Alpha" const alias = "al001" var supplierID uint t.Run("creating supplier succeeds", func(t *testing.T) { supplierID = createSupplier(t, app, supplierName, alias, string(utils.SupplierCategoryBOP)) supplier := fetchSupplier(t, db, supplierID) if supplier.Name != supplierName { t.Fatalf("expected name %q, got %q", supplierName, supplier.Name) } if supplier.Alias != strings.ToUpper(alias) { t.Fatalf("expected alias %q, got %q", strings.ToUpper(alias), supplier.Alias) } if supplier.Type != string(utils.CustomerSupplierTypeBisnis) { t.Fatalf("expected type %q, got %q", utils.CustomerSupplierTypeBisnis, supplier.Type) } if supplier.Category != string(utils.SupplierCategoryBOP) { t.Fatalf("expected category %q, got %q", utils.SupplierCategoryBOP, supplier.Category) } if supplier.DueDate != 30 { t.Fatalf("expected due date 30, got %d", supplier.DueDate) } if supplier.CreatedUser.Id != 1 { t.Fatalf("expected created user id 1, got %d", supplier.CreatedUser.Id) } }) t.Run("creating supplier with duplicate name fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/suppliers", map[string]any{ "name": supplierName, "alias": "dup01", "pic": "Jane Doe", "type": utils.CustomerSupplierTypeBisnis, "category": utils.SupplierCategoryBOP, "phone": "0811111111", "email": "duplicate@supplier.com", "address": "Duplicate address", "due_date": 15, }) if resp.StatusCode != fiber.StatusConflict { t.Fatalf("expected 409 when creating duplicate supplier, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("getting existing supplier succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodGet, fmt.Sprintf("/api/master-data/suppliers/%d", supplierID), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when fetching supplier, got %d: %s", resp.StatusCode, string(body)) } var payload struct { Data struct { Id uint `json:"id"` Name string `json:"name"` Alias string `json:"alias"` Type string `json:"type"` Category string `json:"category"` CreatedUser *struct { Id uint `json:"id"` } `json:"created_user"` } `json:"data"` } if err := json.Unmarshal(body, &payload); err != nil { t.Fatalf("failed to parse supplier response: %v", err) } if payload.Data.Id != supplierID { t.Fatalf("expected id %d, got %d", supplierID, payload.Data.Id) } if payload.Data.Name != supplierName { t.Fatalf("expected name %q, got %q", supplierName, payload.Data.Name) } if payload.Data.Alias != strings.ToUpper(alias) { t.Fatalf("expected alias %q, got %q", strings.ToUpper(alias), payload.Data.Alias) } if payload.Data.Type != string(utils.CustomerSupplierTypeBisnis) { t.Fatalf("expected type %q, got %q", utils.CustomerSupplierTypeBisnis, payload.Data.Type) } if payload.Data.Category != string(utils.SupplierCategoryBOP) { t.Fatalf("expected category %q, got %q", utils.SupplierCategoryBOP, payload.Data.Category) } if payload.Data.CreatedUser == nil || payload.Data.CreatedUser.Id != 1 { t.Fatalf("expected created_user id 1, got %+v", payload.Data.CreatedUser) } }) const updatedAlias = "beta1" t.Run("updating supplier fields succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/suppliers/%d", supplierID), map[string]any{ "alias": updatedAlias, "type": utils.CustomerSupplierTypeIndividual, "category": utils.SupplierCategorySapronak, "due_date": 45, }) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when updating supplier, got %d: %s", resp.StatusCode, string(body)) } var payload struct { Data struct { Alias string `json:"alias"` Type string `json:"type"` Category string `json:"category"` } `json:"data"` } if err := json.Unmarshal(body, &payload); err != nil { t.Fatalf("failed to parse update response: %v", err) } if payload.Data.Alias != strings.ToUpper(updatedAlias) { t.Fatalf("expected alias %q, got %q", strings.ToUpper(updatedAlias), payload.Data.Alias) } if payload.Data.Type != string(utils.CustomerSupplierTypeIndividual) { t.Fatalf("expected type %q, got %q", utils.CustomerSupplierTypeIndividual, payload.Data.Type) } if payload.Data.Category != string(utils.SupplierCategorySapronak) { t.Fatalf("expected category %q, got %q", utils.SupplierCategorySapronak, payload.Data.Category) } supplier := fetchSupplier(t, db, supplierID) if supplier.Alias != strings.ToUpper(updatedAlias) { t.Fatalf("expected persisted alias %q, got %q", strings.ToUpper(updatedAlias), supplier.Alias) } if supplier.Type != string(utils.CustomerSupplierTypeIndividual) { t.Fatalf("expected persisted type %q, got %q", utils.CustomerSupplierTypeIndividual, supplier.Type) } if supplier.Category != string(utils.SupplierCategorySapronak) { t.Fatalf("expected persisted category %q, got %q", utils.SupplierCategorySapronak, supplier.Category) } if supplier.DueDate != 45 { t.Fatalf("expected due date 45, got %d", supplier.DueDate) } }) t.Run("updating supplier with invalid type fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/suppliers/%d", supplierID), map[string]any{ "type": "invalid-type", }) if resp.StatusCode != fiber.StatusBadRequest { t.Fatalf("expected 400 when updating with invalid type, got %d: %s", resp.StatusCode, string(body)) } supplier := fetchSupplier(t, db, supplierID) if supplier.Type != string(utils.CustomerSupplierTypeIndividual) { t.Fatalf("expected type to remain %q after invalid update, got %q", utils.CustomerSupplierTypeIndividual, supplier.Type) } }) t.Run("updating supplier with invalid category fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/suppliers/%d", supplierID), map[string]any{ "category": "invalid", }) if resp.StatusCode != fiber.StatusBadRequest { t.Fatalf("expected 400 when updating with invalid category, got %d: %s", resp.StatusCode, string(body)) } supplier := fetchSupplier(t, db, supplierID) if supplier.Category != string(utils.SupplierCategorySapronak) { t.Fatalf("expected category to remain %q after invalid update, got %q", utils.SupplierCategorySapronak, supplier.Category) } }) t.Run("deleting supplier succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodDelete, fmt.Sprintf("/api/master-data/suppliers/%d", supplierID), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when deleting supplier, got %d: %s", resp.StatusCode, string(body)) } var supplier entities.Supplier if err := db.First(&supplier, supplierID).Error; !errors.Is(err, gorm.ErrRecordNotFound) { t.Fatalf("expected supplier to be deleted, got error %v", err) } }) t.Run("deleting non existent supplier returns 404", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodDelete, fmt.Sprintf("/api/master-data/suppliers/%d", supplierID), nil) if resp.StatusCode != fiber.StatusNotFound { t.Fatalf("expected 404 when deleting missing supplier, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("getting deleted supplier returns 404", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodGet, fmt.Sprintf("/api/master-data/suppliers/%d", supplierID), nil) if resp.StatusCode != fiber.StatusNotFound { t.Fatalf("expected 404 when fetching deleted supplier, got %d: %s", resp.StatusCode, string(body)) } }) }