Implemented Rollback Functionality
This commit is contained in:
@@ -109,6 +109,47 @@ describe("ProgressService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("logRollbackStart", () => {
|
||||
test("should create progress file and log rollback operation start", async () => {
|
||||
const config = {
|
||||
targetTag: "rollback-tag",
|
||||
};
|
||||
|
||||
await progressService.logRollbackStart(config);
|
||||
|
||||
// Check that file was created
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
expect(content).toContain("# Shopify Price Update Progress Log");
|
||||
expect(content).toContain("## Price Rollback Operation -");
|
||||
expect(content).toContain("Target Tag: rollback-tag");
|
||||
expect(content).toContain("Operation Mode: rollback");
|
||||
expect(content).toContain("**Configuration:**");
|
||||
expect(content).toContain("**Progress:**");
|
||||
});
|
||||
|
||||
test("should distinguish rollback from update operations in logs", async () => {
|
||||
const updateConfig = {
|
||||
targetTag: "update-tag",
|
||||
priceAdjustmentPercentage: 10,
|
||||
};
|
||||
|
||||
const rollbackConfig = {
|
||||
targetTag: "rollback-tag",
|
||||
};
|
||||
|
||||
await progressService.logOperationStart(updateConfig);
|
||||
await progressService.logRollbackStart(rollbackConfig);
|
||||
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
expect(content).toContain("## Price Update Operation -");
|
||||
expect(content).toContain("Price Adjustment: 10%");
|
||||
expect(content).toContain("## Price Rollback Operation -");
|
||||
expect(content).toContain("Operation Mode: rollback");
|
||||
});
|
||||
});
|
||||
|
||||
describe("logProductUpdate", () => {
|
||||
test("should log successful product update", async () => {
|
||||
// First create the file
|
||||
@@ -182,6 +223,97 @@ describe("ProgressService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("logRollbackUpdate", () => {
|
||||
test("should log successful rollback operation", async () => {
|
||||
// First create the file
|
||||
await progressService.logRollbackStart({
|
||||
targetTag: "rollback-test",
|
||||
});
|
||||
|
||||
const entry = {
|
||||
productId: "gid://shopify/Product/123456789",
|
||||
productTitle: "Rollback Test Product",
|
||||
variantId: "gid://shopify/ProductVariant/987654321",
|
||||
oldPrice: 1000.0,
|
||||
compareAtPrice: 750.0,
|
||||
newPrice: 750.0,
|
||||
};
|
||||
|
||||
await progressService.logRollbackUpdate(entry);
|
||||
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
expect(content).toContain(
|
||||
"🔄 **Rollback Test Product** (gid://shopify/Product/123456789)"
|
||||
);
|
||||
expect(content).toContain(
|
||||
"Variant: gid://shopify/ProductVariant/987654321"
|
||||
);
|
||||
expect(content).toContain("Price: $1000 → $750 (from Compare At: $750)");
|
||||
expect(content).toContain("Rolled back:");
|
||||
});
|
||||
|
||||
test("should distinguish rollback from update entries", async () => {
|
||||
await progressService.logRollbackStart({
|
||||
targetTag: "test",
|
||||
});
|
||||
|
||||
const updateEntry = {
|
||||
productId: "gid://shopify/Product/123",
|
||||
productTitle: "Update Product",
|
||||
variantId: "gid://shopify/ProductVariant/456",
|
||||
oldPrice: 750.0,
|
||||
newPrice: 1000.0,
|
||||
};
|
||||
|
||||
const rollbackEntry = {
|
||||
productId: "gid://shopify/Product/789",
|
||||
productTitle: "Rollback Product",
|
||||
variantId: "gid://shopify/ProductVariant/012",
|
||||
oldPrice: 1000.0,
|
||||
compareAtPrice: 750.0,
|
||||
newPrice: 750.0,
|
||||
};
|
||||
|
||||
await progressService.logProductUpdate(updateEntry);
|
||||
await progressService.logRollbackUpdate(rollbackEntry);
|
||||
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
// Update entry should use checkmark
|
||||
expect(content).toContain("✅ **Update Product**");
|
||||
expect(content).toContain("Updated:");
|
||||
|
||||
// Rollback entry should use rollback emoji
|
||||
expect(content).toContain("🔄 **Rollback Product**");
|
||||
expect(content).toContain("from Compare At:");
|
||||
expect(content).toContain("Rolled back:");
|
||||
});
|
||||
|
||||
test("should handle products with special characters in rollback", async () => {
|
||||
await progressService.logRollbackStart({
|
||||
targetTag: "test",
|
||||
});
|
||||
|
||||
const entry = {
|
||||
productId: "gid://shopify/Product/123",
|
||||
productTitle: 'Rollback Product with "Quotes" & Special Chars!',
|
||||
variantId: "gid://shopify/ProductVariant/456",
|
||||
oldPrice: 500.0,
|
||||
compareAtPrice: 400.0,
|
||||
newPrice: 400.0,
|
||||
};
|
||||
|
||||
await progressService.logRollbackUpdate(entry);
|
||||
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
expect(content).toContain(
|
||||
'**Rollback Product with "Quotes" & Special Chars!**'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("logError", () => {
|
||||
test("should log error with all details", async () => {
|
||||
await progressService.logOperationStart({
|
||||
@@ -325,6 +457,123 @@ describe("ProgressService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("logRollbackSummary", () => {
|
||||
test("should log rollback completion summary with all statistics", async () => {
|
||||
await progressService.logRollbackStart({
|
||||
targetTag: "rollback-test",
|
||||
});
|
||||
|
||||
const startTime = new Date(Date.now() - 8000); // 8 seconds ago
|
||||
const summary = {
|
||||
totalProducts: 5,
|
||||
totalVariants: 8,
|
||||
eligibleVariants: 6,
|
||||
successfulRollbacks: 5,
|
||||
failedRollbacks: 1,
|
||||
skippedVariants: 2,
|
||||
startTime: startTime,
|
||||
};
|
||||
|
||||
await progressService.logRollbackSummary(summary);
|
||||
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
expect(content).toContain("**Rollback Summary:**");
|
||||
expect(content).toContain("Total Products Processed: 5");
|
||||
expect(content).toContain("Total Variants Processed: 8");
|
||||
expect(content).toContain("Eligible Variants: 6");
|
||||
expect(content).toContain("Successful Rollbacks: 5");
|
||||
expect(content).toContain("Failed Rollbacks: 1");
|
||||
expect(content).toContain("Skipped Variants: 2 (no compare-at price)");
|
||||
expect(content).toContain("Duration: 8 seconds");
|
||||
expect(content).toContain("Completed:");
|
||||
expect(content).toContain("---");
|
||||
});
|
||||
|
||||
test("should handle rollback summary without start time", async () => {
|
||||
await progressService.logRollbackStart({
|
||||
targetTag: "test",
|
||||
});
|
||||
|
||||
const summary = {
|
||||
totalProducts: 3,
|
||||
totalVariants: 5,
|
||||
eligibleVariants: 5,
|
||||
successfulRollbacks: 5,
|
||||
failedRollbacks: 0,
|
||||
skippedVariants: 0,
|
||||
};
|
||||
|
||||
await progressService.logRollbackSummary(summary);
|
||||
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
expect(content).toContain("Duration: Unknown seconds");
|
||||
});
|
||||
|
||||
test("should distinguish rollback summary from update summary", async () => {
|
||||
await progressService.logRollbackStart({
|
||||
targetTag: "test",
|
||||
});
|
||||
|
||||
const updateSummary = {
|
||||
totalProducts: 5,
|
||||
successfulUpdates: 4,
|
||||
failedUpdates: 1,
|
||||
startTime: new Date(Date.now() - 5000),
|
||||
};
|
||||
|
||||
const rollbackSummary = {
|
||||
totalProducts: 3,
|
||||
totalVariants: 6,
|
||||
eligibleVariants: 4,
|
||||
successfulRollbacks: 3,
|
||||
failedRollbacks: 1,
|
||||
skippedVariants: 2,
|
||||
startTime: new Date(Date.now() - 3000),
|
||||
};
|
||||
|
||||
await progressService.logCompletionSummary(updateSummary);
|
||||
await progressService.logRollbackSummary(rollbackSummary);
|
||||
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
// Should contain both summary types
|
||||
expect(content).toContain("**Summary:**");
|
||||
expect(content).toContain("Successful Updates: 4");
|
||||
expect(content).toContain("**Rollback Summary:**");
|
||||
expect(content).toContain("Successful Rollbacks: 3");
|
||||
expect(content).toContain("Skipped Variants: 2 (no compare-at price)");
|
||||
});
|
||||
|
||||
test("should handle zero rollback statistics", async () => {
|
||||
await progressService.logRollbackStart({
|
||||
targetTag: "test",
|
||||
});
|
||||
|
||||
const summary = {
|
||||
totalProducts: 0,
|
||||
totalVariants: 0,
|
||||
eligibleVariants: 0,
|
||||
successfulRollbacks: 0,
|
||||
failedRollbacks: 0,
|
||||
skippedVariants: 0,
|
||||
startTime: new Date(),
|
||||
};
|
||||
|
||||
await progressService.logRollbackSummary(summary);
|
||||
|
||||
const content = await fs.readFile(testFilePath, "utf8");
|
||||
|
||||
expect(content).toContain("Total Products Processed: 0");
|
||||
expect(content).toContain("Total Variants Processed: 0");
|
||||
expect(content).toContain("Eligible Variants: 0");
|
||||
expect(content).toContain("Successful Rollbacks: 0");
|
||||
expect(content).toContain("Failed Rollbacks: 0");
|
||||
expect(content).toContain("Skipped Variants: 0");
|
||||
});
|
||||
});
|
||||
|
||||
describe("categorizeError", () => {
|
||||
test("should categorize rate limiting errors", () => {
|
||||
const testCases = [
|
||||
|
||||
Reference in New Issue
Block a user