package test import ( "bytes" "encoding/json" "fmt" "io" "net/http" "net/http/httptest" "path/filepath" "strings" "testing" "time" "github.com/glebarez/sqlite" "github.com/gofiber/fiber/v2" "gorm.io/gorm" "gorm.io/gorm/logger" "gitlab.com/mbugroup/lti-api.git/internal/entities" "gitlab.com/mbugroup/lti-api.git/internal/route" "gitlab.com/mbugroup/lti-api.git/internal/utils" ) func setupIntegrationApp(t *testing.T) (*fiber.App, *gorm.DB) { t.Helper() dir := t.TempDir() dsn := filepath.Join(dir, "integration.db") db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)}) if err != nil { t.Fatalf("failed to open sqlite database: %v", err) } if err := db.Exec("PRAGMA foreign_keys = ON").Error; err != nil { t.Fatalf("failed to enable foreign keys: %v", err) } if err := db.AutoMigrate( &entities.User{}, &entities.Area{}, &entities.Location{}, &entities.Kandang{}, &entities.Warehouse{}, &entities.Uom{}, &entities.Customer{}, ); err != nil { t.Fatalf("auto migrate failed: %v", err) } seedUser := entities.User{ Id: 1, IdUser: 1001, Email: "tester@example.com", Name: "Tester", CreatedAt: time.Now(), UpdatedAt: time.Now(), } if err := db.Create(&seedUser).Error; err != nil { t.Fatalf("failed to seed user: %v", err) } app := fiber.New() route.Routes(app, db) return app, db } func doJSONRequest(t *testing.T, app *fiber.App, method, path string, payload any) (*http.Response, []byte) { t.Helper() var body io.Reader if payload != nil { buf := &bytes.Buffer{} if err := json.NewEncoder(buf).Encode(payload); err != nil { t.Fatalf("failed to encode payload: %v", err) } body = buf } req := httptest.NewRequest(method, path, body) req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "application/json") resp, err := app.Test(req, -1) if err != nil { t.Fatalf("request failed: %v", err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("failed to read response body: %v", err) } return resp, data } func parseID(t *testing.T, body []byte) uint { t.Helper() var resp struct { Data struct { Id uint `json:"id"` } `json:"data"` } if err := json.Unmarshal(body, &resp); err != nil { t.Fatalf("failed to parse response: %v", err) } return resp.Data.Id } func createArea(t *testing.T, app *fiber.App, name string) uint { t.Helper() resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/areas", map[string]any{"name": name}) if resp.StatusCode != fiber.StatusCreated { t.Fatalf("expected 201 when creating area, got %d: %s", resp.StatusCode, string(body)) } return parseID(t, body) } func createLocation(t *testing.T, app *fiber.App, name, address string, areaID uint) uint { t.Helper() resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/locations", map[string]any{ "name": name, "address": address, "area_id": areaID, }) if resp.StatusCode != fiber.StatusCreated { t.Fatalf("expected 201 when creating location, got %d: %s", resp.StatusCode, string(body)) } return parseID(t, body) } func createKandang(t *testing.T, app *fiber.App, name string, locationID, picID uint) uint { t.Helper() resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/kandangs", map[string]any{ "name": name, "location_id": locationID, "pic_id": picID, }) if resp.StatusCode != fiber.StatusCreated { t.Fatalf("expected 201 when creating kandang, got %d: %s", resp.StatusCode, string(body)) } return parseID(t, body) } func createCustomer(t *testing.T, app *fiber.App, name string, picID uint) uint { t.Helper() identifier := strings.ToLower(strings.ReplaceAll(name, " ", "_")) resp, body := doJSONRequest(t, app, http.MethodPost, "/api/master-data/customers", map[string]any{ "name": name, "pic_id": picID, "type": utils.CustomerSupplierTypeBisnis, "address": "Customer address", "phone": "081234567890", "email": fmt.Sprintf("%s@example.com", identifier), "account_number": fmt.Sprintf("ACC-%s", identifier), }) if resp.StatusCode != fiber.StatusCreated { t.Fatalf("expected 201 when creating customer, got %d: %s", resp.StatusCode, string(body)) } return parseID(t, body) } func fetchCustomer(t *testing.T, db *gorm.DB, id uint) entities.Customer { t.Helper() var customer entities.Customer if err := db.Preload("Pic").Preload("CreatedUser").First(&customer, id).Error; err != nil { t.Fatalf("failed to fetch customer: %v", err) } return customer } func fetchAreaName(t *testing.T, db *gorm.DB, id uint) string { t.Helper() var area entities.Area if err := db.First(&area, id).Error; err != nil { t.Fatalf("failed to fetch area: %v", err) } return area.Name } func fetchWarehouse(t *testing.T, db *gorm.DB, id uint) entities.Warehouse { t.Helper() var wh entities.Warehouse if err := db.First(&wh, id).Error; err != nil { t.Fatalf("failed to fetch warehouse: %v", err) } return wh }