From 4a18f76bd1416c9d3c11afd968769f26d58102e6 Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Fri, 2 Jan 2026 09:23:18 -0300 Subject: [PATCH] test: cover product import --- .../internal/usecase/product_service_test.go | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 backend/internal/usecase/product_service_test.go diff --git a/backend/internal/usecase/product_service_test.go b/backend/internal/usecase/product_service_test.go new file mode 100644 index 0000000..247ec7e --- /dev/null +++ b/backend/internal/usecase/product_service_test.go @@ -0,0 +1,130 @@ +package usecase + +import ( + "context" + "errors" + "strings" + "testing" + "time" + + "github.com/gofrs/uuid/v5" + "github.com/saveinmed/backend-go/internal/domain" +) + +type failingBatchRepo struct { + *MockRepository +} + +func (f *failingBatchRepo) BatchCreateProducts(ctx context.Context, products []domain.Product) error { + return errors.New("boom") +} + +func TestImportProductsSuccess(t *testing.T) { + repo := NewMockRepository() + svc := NewService(repo, &MockPaymentGateway{}, &MockNotificationService{}, 2.5, "secret", time.Hour, "pepper") + + csvData := strings.NewReader("name,price,stock,description,ean\nAspirin,12.5,5,Anti-inflammatory,123\nIbuprofen,10,0,,\n") + sellerID := uuid.Must(uuid.NewV7()) + + report, err := svc.ImportProducts(context.Background(), sellerID, csvData) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if report.TotalProcessed != 2 { + t.Fatalf("expected total processed 2, got %d", report.TotalProcessed) + } + if report.SuccessCount != 2 { + t.Fatalf("expected success count 2, got %d", report.SuccessCount) + } + if report.FailedCount != 0 { + t.Fatalf("expected failed count 0, got %d", report.FailedCount) + } + + if len(repo.products) != 2 { + t.Fatalf("expected 2 products, got %d", len(repo.products)) + } + + if repo.products[0].SellerID != sellerID { + t.Errorf("expected seller ID %s, got %s", sellerID, repo.products[0].SellerID) + } + if repo.products[0].PriceCents != 1250 { + t.Errorf("expected price cents 1250, got %d", repo.products[0].PriceCents) + } + if repo.products[0].Stock != 5 { + t.Errorf("expected stock 5, got %d", repo.products[0].Stock) + } +} + +func TestImportProductsMissingHeaders(t *testing.T) { + repo := NewMockRepository() + svc := NewService(repo, &MockPaymentGateway{}, &MockNotificationService{}, 2.5, "secret", time.Hour, "pepper") + + csvData := strings.NewReader("ean,stock\n123,5\n") + _, err := svc.ImportProducts(context.Background(), uuid.Must(uuid.NewV7()), csvData) + if err == nil { + t.Fatal("expected error for missing headers") + } + if !strings.Contains(err.Error(), "missing required header") { + t.Fatalf("expected missing header error, got %v", err) + } +} + +func TestImportProductsEmptyCSV(t *testing.T) { + repo := NewMockRepository() + svc := NewService(repo, &MockPaymentGateway{}, &MockNotificationService{}, 2.5, "secret", time.Hour, "pepper") + + csvData := strings.NewReader("name,price\n") + _, err := svc.ImportProducts(context.Background(), uuid.Must(uuid.NewV7()), csvData) + if err == nil { + t.Fatal("expected error for empty CSV") + } + if !strings.Contains(err.Error(), "csv file is empty") { + t.Fatalf("expected empty csv error, got %v", err) + } +} + +func TestImportProductsInvalidRows(t *testing.T) { + repo := NewMockRepository() + svc := NewService(repo, &MockPaymentGateway{}, &MockNotificationService{}, 2.5, "secret", time.Hour, "pepper") + + csvData := strings.NewReader("name,price,stock\n,12.5,5\nValid,abc,2\nGood,5,1\n") + sellerID := uuid.Must(uuid.NewV7()) + + report, err := svc.ImportProducts(context.Background(), sellerID, csvData) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if report.TotalProcessed != 3 { + t.Fatalf("expected total processed 3, got %d", report.TotalProcessed) + } + if report.FailedCount != 2 { + t.Fatalf("expected failed count 2, got %d", report.FailedCount) + } + if report.SuccessCount != 1 { + t.Fatalf("expected success count 1, got %d", report.SuccessCount) + } + if len(report.Errors) != 2 { + t.Fatalf("expected 2 errors, got %d", len(report.Errors)) + } + + if len(repo.products) != 1 { + t.Fatalf("expected 1 product, got %d", len(repo.products)) + } +} + +func TestImportProductsBatchInsertFailure(t *testing.T) { + baseRepo := NewMockRepository() + repo := &failingBatchRepo{MockRepository: baseRepo} + svc := NewService(repo, &MockPaymentGateway{}, &MockNotificationService{}, 2.5, "secret", time.Hour, "pepper") + + csvData := strings.NewReader("name,price\nItem,12.5\n") + _, err := svc.ImportProducts(context.Background(), uuid.Must(uuid.NewV7()), csvData) + if err == nil { + t.Fatal("expected batch insert error") + } + if !strings.Contains(err.Error(), "batch insert failed") { + t.Fatalf("expected batch insert error, got %v", err) + } +}