const ShopifyService = require("../../../src/services/shopify"); const ProductService = require("../../../src/services/product"); const ProgressService = require("../../../src/services/progress"); // Mock the services to avoid actual API calls during testing jest.mock("../../../src/services/shopify"); jest.mock("../../../src/services/product"); jest.mock("../../../src/services/progress"); describe("TUI ProductService and ProgressService Integration", () => { let mockShopifyService; let mockProductService; let mockProgressService; beforeEach(() => { // Reset all mocks jest.clearAllMocks(); // Create mock ShopifyService instance mockShopifyService = { testConnection: jest.fn(), executeQuery: jest.fn(), executeMutation: jest.fn(), executeWithRetry: jest.fn(), }; // Create mock ProductService instance mockProductService = { fetchProductsByTag: jest.fn(), updateProductPrices: jest.fn(), rollbackProductPrices: jest.fn(), validateProducts: jest.fn(), validateProductsForRollback: jest.fn(), getProductSummary: jest.fn(), }; // Create mock ProgressService instance mockProgressService = { logOperationStart: jest.fn(), logRollbackStart: jest.fn(), logProductUpdate: jest.fn(), logRollbackUpdate: jest.fn(), logError: jest.fn(), logCompletionSummary: jest.fn(), logRollbackSummary: jest.fn(), }; // Mock the service constructors ShopifyService.mockImplementation(() => mockShopifyService); ProductService.mockImplementation(() => mockProductService); ProgressService.mockImplementation(() => mockProgressService); }); describe("ProductService Integration", () => { test("should fetch products by tag", async () => { const mockProducts = [ { id: "product1", title: "Test Product 1", variants: [{ id: "variant1", price: 10.0 }], }, ]; mockProductService.fetchProductsByTag.mockResolvedValue(mockProducts); const service = new ProductService(); const products = await service.fetchProductsByTag("test-tag"); expect(mockProductService.fetchProductsByTag).toHaveBeenCalledWith( "test-tag" ); expect(products).toEqual(mockProducts); }); test("should update product prices", async () => { const mockProducts = [ { id: "product1", title: "Test Product 1", variants: [{ id: "variant1", price: 10.0 }], }, ]; const mockResults = { totalProducts: 1, totalVariants: 1, successfulUpdates: 1, failedUpdates: 0, errors: [], }; mockProductService.updateProductPrices.mockResolvedValue(mockResults); const service = new ProductService(); const results = await service.updateProductPrices(mockProducts, 10); expect(mockProductService.updateProductPrices).toHaveBeenCalledWith( mockProducts, 10 ); expect(results).toEqual(mockResults); }); test("should rollback product prices", async () => { const mockProducts = [ { id: "product1", title: "Test Product 1", variants: [{ id: "variant1", price: 11.0, compareAtPrice: 10.0 }], }, ]; const mockResults = { totalProducts: 1, totalVariants: 1, successfulRollbacks: 1, failedRollbacks: 0, skippedVariants: 0, errors: [], }; mockProductService.rollbackProductPrices.mockResolvedValue(mockResults); const service = new ProductService(); const results = await service.rollbackProductPrices(mockProducts); expect(mockProductService.rollbackProductPrices).toHaveBeenCalledWith( mockProducts ); expect(results).toEqual(mockResults); }); test("should validate products", async () => { const mockProducts = [ { id: "product1", title: "Test Product 1", variants: [{ id: "variant1", price: 10.0 }], }, ]; mockProductService.validateProducts.mockResolvedValue(mockProducts); const service = new ProductService(); const validProducts = await service.validateProducts(mockProducts); expect(mockProductService.validateProducts).toHaveBeenCalledWith( mockProducts ); expect(validProducts).toEqual(mockProducts); }); test("should validate products for rollback", async () => { const mockProducts = [ { id: "product1", title: "Test Product 1", variants: [{ id: "variant1", price: 11.0, compareAtPrice: 10.0 }], }, ]; mockProductService.validateProductsForRollback.mockResolvedValue( mockProducts ); const service = new ProductService(); const validProducts = await service.validateProductsForRollback( mockProducts ); expect( mockProductService.validateProductsForRollback ).toHaveBeenCalledWith(mockProducts); expect(validProducts).toEqual(mockProducts); }); test("should get product summary", () => { const mockProducts = [ { id: "product1", title: "Test Product 1", variants: [{ id: "variant1", price: 10.0 }], }, ]; const mockSummary = { totalProducts: 1, totalVariants: 1, priceRange: { min: 10.0, max: 10.0 }, }; mockProductService.getProductSummary.mockReturnValue(mockSummary); const service = new ProductService(); const summary = service.getProductSummary(mockProducts); expect(mockProductService.getProductSummary).toHaveBeenCalledWith( mockProducts ); expect(summary).toEqual(mockSummary); }); }); describe("ProgressService Integration", () => { test("should log operation start", async () => { const mockConfig = { targetTag: "test-tag", priceAdjustmentPercentage: 10, }; mockProgressService.logOperationStart.mockResolvedValue(); const service = new ProgressService(); await service.logOperationStart(mockConfig); expect(mockProgressService.logOperationStart).toHaveBeenCalledWith( mockConfig ); }); test("should log rollback start", async () => { const mockConfig = { targetTag: "test-tag" }; mockProgressService.logRollbackStart.mockResolvedValue(); const service = new ProgressService(); await service.logRollbackStart(mockConfig); expect(mockProgressService.logRollbackStart).toHaveBeenCalledWith( mockConfig ); }); test("should log product update", async () => { const mockEntry = { productId: "product1", productTitle: "Test Product", variantId: "variant1", oldPrice: 10.0, newPrice: 11.0, compareAtPrice: 10.0, }; mockProgressService.logProductUpdate.mockResolvedValue(); const service = new ProgressService(); await service.logProductUpdate(mockEntry); expect(mockProgressService.logProductUpdate).toHaveBeenCalledWith( mockEntry ); }); test("should log rollback update", async () => { const mockEntry = { productId: "product1", productTitle: "Test Product", variantId: "variant1", oldPrice: 11.0, newPrice: 10.0, compareAtPrice: 10.0, }; mockProgressService.logRollbackUpdate.mockResolvedValue(); const service = new ProgressService(); await service.logRollbackUpdate(mockEntry); expect(mockProgressService.logRollbackUpdate).toHaveBeenCalledWith( mockEntry ); }); test("should log error", async () => { const mockEntry = { productId: "product1", productTitle: "Test Product", variantId: "variant1", errorMessage: "Test error", }; mockProgressService.logError.mockResolvedValue(); const service = new ProgressService(); await service.logError(mockEntry); expect(mockProgressService.logError).toHaveBeenCalledWith(mockEntry); }); test("should log completion summary", async () => { const mockSummary = { totalProducts: 1, successfulUpdates: 1, failedUpdates: 0, startTime: new Date(), }; mockProgressService.logCompletionSummary.mockResolvedValue(); const service = new ProgressService(); await service.logCompletionSummary(mockSummary); expect(mockProgressService.logCompletionSummary).toHaveBeenCalledWith( mockSummary ); }); test("should log rollback summary", async () => { const mockSummary = { totalProducts: 1, totalVariants: 1, successfulRollbacks: 1, failedRollbacks: 0, skippedVariants: 0, startTime: new Date(), }; mockProgressService.logRollbackSummary.mockResolvedValue(); const service = new ProgressService(); await service.logRollbackSummary(mockSummary); expect(mockProgressService.logRollbackSummary).toHaveBeenCalledWith( mockSummary ); }); }); describe("Service Integration Workflow", () => { test("should support complete update workflow", async () => { // Mock the complete workflow const mockProducts = [ { id: "product1", title: "Test Product 1", variants: [{ id: "variant1", price: 10.0 }], }, ]; const mockConfig = { targetTag: "test-tag", priceAdjustmentPercentage: 10, }; const mockResults = { totalProducts: 1, totalVariants: 1, successfulUpdates: 1, failedUpdates: 0, errors: [], }; mockProductService.fetchProductsByTag.mockResolvedValue(mockProducts); mockProductService.validateProducts.mockResolvedValue(mockProducts); mockProductService.updateProductPrices.mockResolvedValue(mockResults); mockProgressService.logOperationStart.mockResolvedValue(); mockProgressService.logCompletionSummary.mockResolvedValue(); const productService = new ProductService(); const progressService = new ProgressService(); // Execute workflow await progressService.logOperationStart(mockConfig); const fetchedProducts = await productService.fetchProductsByTag( mockConfig.targetTag ); const validProducts = await productService.validateProducts( fetchedProducts ); const results = await productService.updateProductPrices( validProducts, mockConfig.priceAdjustmentPercentage ); await progressService.logCompletionSummary(results); // Verify workflow execution expect(mockProgressService.logOperationStart).toHaveBeenCalledWith( mockConfig ); expect(mockProductService.fetchProductsByTag).toHaveBeenCalledWith( mockConfig.targetTag ); expect(mockProductService.validateProducts).toHaveBeenCalledWith( mockProducts ); expect(mockProductService.updateProductPrices).toHaveBeenCalledWith( mockProducts, mockConfig.priceAdjustmentPercentage ); expect(mockProgressService.logCompletionSummary).toHaveBeenCalledWith( mockResults ); }); test("should support complete rollback workflow", async () => { // Mock the complete rollback workflow const mockProducts = [ { id: "product1", title: "Test Product 1", variants: [{ id: "variant1", price: 11.0, compareAtPrice: 10.0 }], }, ]; const mockConfig = { targetTag: "test-tag" }; const mockResults = { totalProducts: 1, totalVariants: 1, successfulRollbacks: 1, failedRollbacks: 0, skippedVariants: 0, errors: [], }; mockProductService.fetchProductsByTag.mockResolvedValue(mockProducts); mockProductService.validateProductsForRollback.mockResolvedValue( mockProducts ); mockProductService.rollbackProductPrices.mockResolvedValue(mockResults); mockProgressService.logRollbackStart.mockResolvedValue(); mockProgressService.logRollbackSummary.mockResolvedValue(); const productService = new ProductService(); const progressService = new ProgressService(); // Execute rollback workflow await progressService.logRollbackStart(mockConfig); const fetchedProducts = await productService.fetchProductsByTag( mockConfig.targetTag ); const validProducts = await productService.validateProductsForRollback( fetchedProducts ); const results = await productService.rollbackProductPrices(validProducts); await progressService.logRollbackSummary(results); // Verify rollback workflow execution expect(mockProgressService.logRollbackStart).toHaveBeenCalledWith( mockConfig ); expect(mockProductService.fetchProductsByTag).toHaveBeenCalledWith( mockConfig.targetTag ); expect( mockProductService.validateProductsForRollback ).toHaveBeenCalledWith(mockProducts); expect(mockProductService.rollbackProductPrices).toHaveBeenCalledWith( mockProducts ); expect(mockProgressService.logRollbackSummary).toHaveBeenCalledWith( mockResults ); }); }); });