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" "gitlab.com/mbugroup/lti-api.git/internal/utils" ) func TestCustomerIntegration(t *testing.T) { app, db := setupIntegrationApp(t) t.Run("creating customer without existing pic fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/customers", map[string]any{ "name": "Invalid Customer", "pic_id": 9999, "type": utils.CustomerSupplierTypeBisnis, "address": "Somewhere", "phone": "0800000000", "email": "invalid@example.com", "account_number": "ACC-INVALID", }) if resp.StatusCode != fiber.StatusNotFound { t.Fatalf("expected 404 when pic is missing, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("creating customer with invalid type fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/customers", map[string]any{ "name": "Invalid Type", "pic_id": 1, "type": "UNKNOWN", "address": "Somewhere", "phone": "081234567891", "email": "invalid-type@example.com", "account_number": "ACC-INVALID-TYPE", }) if resp.StatusCode != fiber.StatusBadRequest { t.Fatalf("expected 400 when type is invalid, got %d: %s", resp.StatusCode, string(body)) } }) const customerName = "Customer Alpha" var customerID uint t.Run("creating customer succeeds", func(t *testing.T) { customerID = createCustomer(t, app, customerName, 1) customer := fetchCustomer(t, db, customerID) if customer.Name != customerName { t.Fatalf("expected name %q, got %q", customerName, customer.Name) } if customer.PicId != 1 { t.Fatalf("expected pic id 1, got %d", customer.PicId) } if customer.Type != string(utils.CustomerSupplierTypeBisnis) { t.Fatalf("expected type %q, got %q", utils.CustomerSupplierTypeBisnis, customer.Type) } }) t.Run("creating customer with duplicate name fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/customers", map[string]any{ "name": customerName, "pic_id": 1, "type": utils.CustomerSupplierTypeBisnis, "address": "Duplicate address", "phone": "0811111111", "email": "duplicate@example.com", "account_number": "ACC-DUP", }) if resp.StatusCode != fiber.StatusConflict { t.Fatalf("expected 409 when creating duplicate customer, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("getting existing customer succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodGet, fmt.Sprintf("/api/master-data/customers/%d", customerID), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when fetching customer, got %d: %s", resp.StatusCode, string(body)) } var payload struct { Data struct { Id uint `json:"id"` Name string `json:"name"` } `json:"data"` } if err := json.Unmarshal(body, &payload); err != nil { t.Fatalf("failed to parse customer response: %v", err) } if payload.Data.Id != customerID { t.Fatalf("expected id %d, got %d", customerID, payload.Data.Id) } if payload.Data.Name != customerName { t.Fatalf("expected name %q, got %q", customerName, payload.Data.Name) } }) const updatedName = "Customer Gamma" t.Run("updating customer name succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/customers/%d", customerID), map[string]any{ "name": updatedName, }) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when updating customer, got %d: %s", resp.StatusCode, string(body)) } var payload struct { Data struct { Name string `json:"name"` } `json:"data"` } if err := json.Unmarshal(body, &payload); err != nil { t.Fatalf("failed to parse update response: %v", err) } if payload.Data.Name != updatedName { t.Fatalf("expected updated name %q, got %q", updatedName, payload.Data.Name) } customer := fetchCustomer(t, db, customerID) if customer.Name != updatedName { t.Fatalf("expected persisted name %q, got %q", updatedName, customer.Name) } }) t.Run("updating customer type succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/customers/%d", customerID), map[string]any{ "type": utils.CustomerSupplierTypeIndividual, }) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when updating customer type, got %d: %s", resp.StatusCode, string(body)) } customer := fetchCustomer(t, db, customerID) if customer.Type != string(utils.CustomerSupplierTypeIndividual) { t.Fatalf("expected persisted type %q, got %q", utils.CustomerSupplierTypeIndividual, customer.Type) } }) t.Run("updating customer with invalid type fails", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, fmt.Sprintf("/api/master-data/customers/%d", customerID), map[string]any{ "type": "random-type", }) if resp.StatusCode != fiber.StatusBadRequest { t.Fatalf("expected 400 when updating with invalid type, got %d: %s", resp.StatusCode, string(body)) } customer := fetchCustomer(t, db, customerID) if customer.Type != string(utils.CustomerSupplierTypeIndividual) { t.Fatalf("expected type to remain %q after invalid update, got %q", utils.CustomerSupplierTypeIndividual, customer.Type) } }) t.Run("updating non existent customer returns 404", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodPatch, "/api/master-data/customers/9999", map[string]any{ "name": "Does Not Matter", }) if resp.StatusCode != fiber.StatusNotFound { t.Fatalf("expected 404 when updating missing customer, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("deleting customer succeeds", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodDelete, fmt.Sprintf("/api/master-data/customers/%d", customerID), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when deleting customer, got %d: %s", resp.StatusCode, string(body)) } var customer entities.Customer if err := db.First(&customer, customerID).Error; !errors.Is(err, gorm.ErrRecordNotFound) { t.Fatalf("expected customer to be deleted, got error %v", err) } }) t.Run("deleting non existent customer returns 404", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodDelete, fmt.Sprintf("/api/master-data/customers/%d", customerID), nil) if resp.StatusCode != fiber.StatusNotFound { t.Fatalf("expected 404 when deleting missing customer, got %d: %s", resp.StatusCode, string(body)) } }) t.Run("getting deleted customer returns 404", func(t *testing.T) { resp, body := doJSONRequest(t, app, http.MethodGet, fmt.Sprintf("/api/master-data/customers/%d", customerID), nil) if resp.StatusCode != fiber.StatusNotFound { t.Fatalf("expected 404 when fetching deleted customer, got %d: %s", resp.StatusCode, string(body)) } }) }