package processor import ( "context" "testing" "apskel-pos-be/internal/models" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) // Mock repositories for testing type MockProductRepository struct { mock.Mock } type MockCategoryRepository struct { mock.Mock } type MockProductVariantRepository struct { mock.Mock } type MockInventoryRepository struct { mock.Mock } type MockOutletRepository struct { mock.Mock } // Test helper functions func TestCreateProductWithInventory(t *testing.T) { // This is a basic test structure - in a real implementation, // you would use a proper testing framework with database mocks t.Run("should create product with inventory when create_inventory is true", func(t *testing.T) { // Arrange productRepo := &MockProductRepository{} categoryRepo := &MockCategoryRepository{} productVariantRepo := &MockProductVariantRepository{} inventoryRepo := &MockInventoryRepository{} outletRepo := &MockOutletRepository{} processor := NewProductProcessorImpl( productRepo, categoryRepo, productVariantRepo, inventoryRepo, outletRepo, ) req := &models.CreateProductRequest{ OrganizationID: uuid.New(), CategoryID: uuid.New(), Name: "Test Product", Price: 10.0, Cost: 5.0, InitialStock: &[]int{100}[0], ReorderLevel: &[]int{20}[0], CreateInventory: true, } // Mock expectations categoryRepo.On("GetByID", mock.Anything, req.CategoryID).Return(&models.Category{}, nil) productRepo.On("ExistsBySKU", mock.Anything, req.OrganizationID, mock.Anything, mock.Anything).Return(false, nil) productRepo.On("ExistsByName", mock.Anything, req.OrganizationID, req.Name, mock.Anything).Return(false, nil) productRepo.On("Create", mock.Anything, mock.Anything).Return(nil) productRepo.On("GetWithCategory", mock.Anything, mock.Anything).Return(&models.Product{}, nil) // Mock outlets outlets := []*models.Outlet{ {ID: uuid.New()}, {ID: uuid.New()}, } outletRepo.On("GetByOrganizationID", mock.Anything, req.OrganizationID).Return(outlets, nil) // Mock inventory creation inventoryRepo.On("BulkCreate", mock.Anything, mock.Anything).Return(nil) // Act result, err := processor.CreateProduct(context.Background(), req) // Assert assert.NoError(t, err) assert.NotNil(t, result) // Verify that inventory was created inventoryRepo.AssertCalled(t, "BulkCreate", mock.Anything, mock.Anything) outletRepo.AssertCalled(t, "GetByOrganizationID", mock.Anything, req.OrganizationID) }) t.Run("should not create inventory when create_inventory is false", func(t *testing.T) { // Arrange productRepo := &MockProductRepository{} categoryRepo := &MockCategoryRepository{} productVariantRepo := &MockProductVariantRepository{} inventoryRepo := &MockInventoryRepository{} outletRepo := &MockOutletRepository{} processor := NewProductProcessorImpl( productRepo, categoryRepo, productVariantRepo, inventoryRepo, outletRepo, ) req := &models.CreateProductRequest{ OrganizationID: uuid.New(), CategoryID: uuid.New(), Name: "Test Product", Price: 10.0, Cost: 5.0, CreateInventory: false, } // Mock expectations categoryRepo.On("GetByID", mock.Anything, req.CategoryID).Return(&models.Category{}, nil) productRepo.On("ExistsBySKU", mock.Anything, req.OrganizationID, mock.Anything, mock.Anything).Return(false, nil) productRepo.On("ExistsByName", mock.Anything, req.OrganizationID, req.Name, mock.Anything).Return(false, nil) productRepo.On("Create", mock.Anything, mock.Anything).Return(nil) productRepo.On("GetWithCategory", mock.Anything, mock.Anything).Return(&models.Product{}, nil) // Act result, err := processor.CreateProduct(context.Background(), req) // Assert assert.NoError(t, err) assert.NotNil(t, result) // Verify that inventory was NOT created inventoryRepo.AssertNotCalled(t, "BulkCreate", mock.Anything, mock.Anything) outletRepo.AssertNotCalled(t, "GetByOrganizationID", mock.Anything, mock.Anything) }) } // Mock implementations (simplified for testing) func (m *MockProductRepository) Create(ctx context.Context, product *models.Product) error { args := m.Called(ctx, product) return args.Error(0) } func (m *MockProductRepository) GetByID(ctx context.Context, id uuid.UUID) (*models.Product, error) { args := m.Called(ctx, id) return args.Get(0).(*models.Product), args.Error(1) } func (m *MockProductRepository) GetWithCategory(ctx context.Context, id uuid.UUID) (*models.Product, error) { args := m.Called(ctx, id) return args.Get(0).(*models.Product), args.Error(1) } func (m *MockProductRepository) ExistsBySKU(ctx context.Context, organizationID uuid.UUID, sku string, excludeID *uuid.UUID) (bool, error) { args := m.Called(ctx, organizationID, sku, excludeID) return args.Bool(0), args.Error(1) } func (m *MockProductRepository) ExistsByName(ctx context.Context, organizationID uuid.UUID, name string, excludeID *uuid.UUID) (bool, error) { args := m.Called(ctx, organizationID, name, excludeID) return args.Bool(0), args.Error(1) } func (m *MockCategoryRepository) GetByID(ctx context.Context, id uuid.UUID) (*models.Category, error) { args := m.Called(ctx, id) return args.Get(0).(*models.Category), args.Error(1) } func (m *MockInventoryRepository) BulkCreate(ctx context.Context, inventoryItems []*models.Inventory) error { args := m.Called(ctx, inventoryItems) return args.Error(0) } func (m *MockOutletRepository) GetByOrganizationID(ctx context.Context, organizationID uuid.UUID) ([]*models.Outlet, error) { args := m.Called(ctx, organizationID) return args.Get(0).([]*models.Outlet), args.Error(1) }