291 lines
9.7 KiB
JavaScript
291 lines
9.7 KiB
JavaScript
const fs = require("fs").promises;
|
|
const path = require("path");
|
|
|
|
// 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("CLI/TUI Compatibility", () => {
|
|
const originalEnv = process.env;
|
|
|
|
beforeEach(() => {
|
|
// Reset environment
|
|
jest.resetModules();
|
|
process.env = { ...originalEnv };
|
|
});
|
|
|
|
afterEach(() => {
|
|
// Restore original environment
|
|
process.env = originalEnv;
|
|
});
|
|
|
|
describe("Configuration Compatibility", () => {
|
|
test("should use same configuration system for both CLI and TUI", () => {
|
|
// Set environment variables that both CLI and TUI should use
|
|
process.env.SHOPIFY_SHOP_DOMAIN = "test-shop.myshopify.com";
|
|
process.env.SHOPIFY_ACCESS_TOKEN = "test-token";
|
|
process.env.TARGET_TAG = "test-tag";
|
|
process.env.PRICE_ADJUSTMENT_PERCENTAGE = "10";
|
|
process.env.OPERATION_MODE = "update";
|
|
|
|
// Both CLI and TUI use the same configuration module
|
|
const { getConfig } = require("../../../src/config/environment");
|
|
const config = getConfig();
|
|
|
|
// Verify configuration is loaded correctly
|
|
expect(config.shopDomain).toBe("test-shop.myshopify.com");
|
|
expect(config.accessToken).toBe("test-token");
|
|
expect(config.targetTag).toBe("test-tag");
|
|
expect(config.priceAdjustmentPercentage).toBe(10);
|
|
expect(config.operationMode).toBe("update");
|
|
});
|
|
|
|
test("should handle update mode configuration", () => {
|
|
process.env.SHOPIFY_SHOP_DOMAIN = "test-shop.myshopify.com";
|
|
process.env.SHOPIFY_ACCESS_TOKEN = "test-token";
|
|
process.env.TARGET_TAG = "update-tag";
|
|
process.env.OPERATION_MODE = "update";
|
|
process.env.PRICE_ADJUSTMENT_PERCENTAGE = "15";
|
|
|
|
const { getConfig } = require("../../../src/config/environment");
|
|
const config = getConfig();
|
|
|
|
expect(config.operationMode).toBe("update");
|
|
expect(config.targetTag).toBe("update-tag");
|
|
expect(config.priceAdjustmentPercentage).toBe(15);
|
|
});
|
|
});
|
|
|
|
describe("Service Integration Compatibility", () => {
|
|
test("should use same service classes for both CLI and TUI", () => {
|
|
const ShopifyService = require("../../../src/services/shopify");
|
|
const ProductService = require("../../../src/services/product");
|
|
const ProgressService = require("../../../src/services/progress");
|
|
|
|
// Both CLI and TUI should be able to create the same service instances
|
|
const shopifyService = new ShopifyService();
|
|
const productService = new ProductService();
|
|
const progressService = new ProgressService();
|
|
|
|
expect(shopifyService).toBeDefined();
|
|
expect(productService).toBeDefined();
|
|
expect(progressService).toBeDefined();
|
|
|
|
// Verify services have the same API
|
|
expect(typeof shopifyService.testConnection).toBe("function");
|
|
expect(typeof shopifyService.executeQuery).toBe("function");
|
|
expect(typeof shopifyService.executeMutation).toBe("function");
|
|
|
|
expect(typeof productService.fetchProductsByTag).toBe("function");
|
|
expect(typeof productService.updateProductPrices).toBe("function");
|
|
expect(typeof productService.rollbackProductPrices).toBe("function");
|
|
|
|
expect(typeof progressService.logOperationStart).toBe("function");
|
|
expect(typeof progressService.logProductUpdate).toBe("function");
|
|
expect(typeof progressService.logCompletionSummary).toBe("function");
|
|
});
|
|
});
|
|
|
|
describe("File System Compatibility", () => {
|
|
test("should use same progress file system for both CLI and TUI", () => {
|
|
// Since ProgressService is mocked, we'll test the concept rather than implementation
|
|
const ProgressService = require("../../../src/services/progress");
|
|
|
|
// Both CLI and TUI should be able to create ProgressService instances
|
|
const progressService1 = new ProgressService();
|
|
const progressService2 = new ProgressService();
|
|
|
|
// Both should have the same API
|
|
expect(progressService1).toBeDefined();
|
|
expect(progressService2).toBeDefined();
|
|
expect(typeof progressService1.logOperationStart).toBe("function");
|
|
expect(typeof progressService2.logOperationStart).toBe("function");
|
|
});
|
|
});
|
|
|
|
describe("Entry Point Compatibility", () => {
|
|
test("should have separate entry points that don't conflict", () => {
|
|
// CLI entry point should be importable
|
|
expect(() => {
|
|
const cliModule = require("../../../src/index.js");
|
|
expect(cliModule).toBeDefined();
|
|
}).not.toThrow();
|
|
|
|
// TUI entry point should be importable (but we'll skip the actual import due to JSX issues in tests)
|
|
// Instead, verify the file exists and has the expected structure
|
|
const tuiEntryPath = path.join(__dirname, "../../../src/tui-entry.js");
|
|
expect(() => {
|
|
const fs = require("fs");
|
|
const content = fs.readFileSync(tuiEntryPath, "utf8");
|
|
expect(content).toContain("TuiApplication");
|
|
expect(content).toContain("render");
|
|
}).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe("Package.json Script Compatibility", () => {
|
|
test("should have separate scripts for CLI and TUI", () => {
|
|
const packageJson = require("../../../package.json");
|
|
|
|
// CLI scripts
|
|
expect(packageJson.scripts.start).toBe("node src/index.js");
|
|
expect(packageJson.scripts.update).toContain("node src/index.js");
|
|
expect(packageJson.scripts.rollback).toContain("node src/index.js");
|
|
|
|
// TUI script
|
|
expect(packageJson.scripts.tui).toContain("src/tui-entry.js");
|
|
|
|
// Both should be able to coexist
|
|
expect(packageJson.scripts.start).not.toBe(packageJson.scripts.tui);
|
|
});
|
|
});
|
|
|
|
describe("Operational Compatibility", () => {
|
|
test("should support same operation modes in both interfaces", () => {
|
|
const validModes = ["update", "rollback"];
|
|
|
|
validModes.forEach((mode) => {
|
|
// Reset modules to get fresh config
|
|
jest.resetModules();
|
|
|
|
process.env.SHOPIFY_SHOP_DOMAIN = "test-shop.myshopify.com";
|
|
process.env.SHOPIFY_ACCESS_TOKEN = "test-token";
|
|
process.env.TARGET_TAG = "test-tag";
|
|
process.env.PRICE_ADJUSTMENT_PERCENTAGE = "10";
|
|
process.env.OPERATION_MODE = mode;
|
|
|
|
const { getConfig } = require("../../../src/config/environment");
|
|
const config = getConfig();
|
|
expect(config.operationMode).toBe(mode);
|
|
});
|
|
});
|
|
|
|
test("should handle configuration validation consistently", () => {
|
|
// Test that both CLI and TUI would handle missing configuration the same way
|
|
process.env.SHOPIFY_SHOP_DOMAIN = "test-shop.myshopify.com";
|
|
process.env.SHOPIFY_ACCESS_TOKEN = "test-token";
|
|
process.env.TARGET_TAG = "test-tag";
|
|
process.env.PRICE_ADJUSTMENT_PERCENTAGE = "10";
|
|
process.env.OPERATION_MODE = "update";
|
|
|
|
const { getConfig } = require("../../../src/config/environment");
|
|
|
|
// Valid configuration should work
|
|
expect(() => getConfig()).not.toThrow();
|
|
|
|
// Both CLI and TUI use the same validation logic
|
|
const config = getConfig();
|
|
expect(config).toBeDefined();
|
|
expect(config.shopDomain).toBeDefined();
|
|
expect(config.accessToken).toBeDefined();
|
|
expect(config.targetTag).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe("State Management Compatibility", () => {
|
|
test("should not share state between CLI and TUI instances", () => {
|
|
// CLI and TUI should be independent - no shared global state
|
|
const ShopifyService = require("../../../src/services/shopify");
|
|
|
|
// Create separate instances (as CLI and TUI would)
|
|
const cliService = new ShopifyService();
|
|
const tuiService = new ShopifyService();
|
|
|
|
// They should be separate instances
|
|
expect(cliService).not.toBe(tuiService);
|
|
|
|
// They should be different instances but have same structure
|
|
expect(cliService === tuiService).toBe(false);
|
|
expect(typeof cliService.testConnection).toBe(
|
|
typeof tuiService.testConnection
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Dependency Compatibility", () => {
|
|
test("should use compatible dependencies for both interfaces", () => {
|
|
const packageJson = require("../../../package.json");
|
|
|
|
// Core dependencies that both CLI and TUI use
|
|
const sharedDependencies = [
|
|
"@shopify/shopify-api",
|
|
"dotenv",
|
|
"node-fetch",
|
|
];
|
|
|
|
sharedDependencies.forEach((dep) => {
|
|
expect(packageJson.dependencies[dep]).toBeDefined();
|
|
});
|
|
|
|
// TUI-specific dependencies
|
|
const tuiDependencies = [
|
|
"ink",
|
|
"react",
|
|
"ink-text-input",
|
|
"ink-select-input",
|
|
"ink-spinner",
|
|
];
|
|
|
|
tuiDependencies.forEach((dep) => {
|
|
expect(packageJson.dependencies[dep]).toBeDefined();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Service API Compatibility", () => {
|
|
test("should maintain consistent service APIs for both CLI and TUI", () => {
|
|
// Test that services maintain their expected API structure
|
|
const ShopifyService = require("../../../src/services/shopify");
|
|
const ProductService = require("../../../src/services/product");
|
|
const ProgressService = require("../../../src/services/progress");
|
|
|
|
const shopifyService = new ShopifyService();
|
|
const productService = new ProductService();
|
|
const progressService = new ProgressService();
|
|
|
|
// ShopifyService API
|
|
const shopifyMethods = [
|
|
"testConnection",
|
|
"executeQuery",
|
|
"executeMutation",
|
|
"executeWithRetry",
|
|
"getApiCallLimit",
|
|
];
|
|
|
|
shopifyMethods.forEach((method) => {
|
|
expect(typeof shopifyService[method]).toBe("function");
|
|
});
|
|
|
|
// ProductService API
|
|
const productMethods = [
|
|
"fetchProductsByTag",
|
|
"updateProductPrices",
|
|
"rollbackProductPrices",
|
|
"validateProducts",
|
|
"validateProductsForRollback",
|
|
"getProductSummary",
|
|
];
|
|
|
|
productMethods.forEach((method) => {
|
|
expect(typeof productService[method]).toBe("function");
|
|
});
|
|
|
|
// ProgressService API
|
|
const progressMethods = [
|
|
"logOperationStart",
|
|
"logRollbackStart",
|
|
"logProductUpdate",
|
|
"logRollbackUpdate",
|
|
"logError",
|
|
"logCompletionSummary",
|
|
"logRollbackSummary",
|
|
];
|
|
|
|
progressMethods.forEach((method) => {
|
|
expect(typeof progressService[method]).toBe("function");
|
|
});
|
|
});
|
|
});
|
|
});
|