This commit enforces proper SKU validation, uses the SKU as the Shopify handle, and implements ID-based product updates to allow renaming. It also extracts the IShop interface for TDD.
107 lines
4.1 KiB
TypeScript
107 lines
4.1 KiB
TypeScript
import { Product } from "./Product";
|
|
import { MockSpreadsheetService } from "./services/MockSpreadsheetService";
|
|
import { MockShop } from "./test/MockShop";
|
|
|
|
describe("Product Logic (TDD)", () => {
|
|
let mockService: MockSpreadsheetService;
|
|
let mockShop: MockShop;
|
|
|
|
beforeEach(() => {
|
|
mockService = new MockSpreadsheetService({
|
|
product_inventory: [
|
|
["sku", "title", "price", "shopify_id", "product_type"], // Headers
|
|
["TEST-SKU-1", "Test Product", 10.99, "", "Type A"] // Data
|
|
],
|
|
values: [
|
|
["product_type", "shopify_category", "ebay_category_id"],
|
|
["Type A", "Category A", "123"]
|
|
]
|
|
});
|
|
mockShop = new MockShop();
|
|
});
|
|
|
|
test("UpdateShopifyProduct should abort if SKU is invalid", () => {
|
|
// Setup invalid SKU
|
|
mockService.setSheetData("product_inventory", [
|
|
["sku", "title"],
|
|
["?", "Invalid Product"]
|
|
]);
|
|
// Allow empty sku to be passed to constructor logic check, but Product constructor throws if sku not found.
|
|
// So we pass a valid sku that exists in sheet, but looks invalid?
|
|
// The requirement is "based on the product's title... If I have a placeholder value... ensure products are not created until they have a valid SKU".
|
|
// In `Product.ts`, constructor takes `sku`.
|
|
// If I pass `?` and it's in the sheet, it constructs.
|
|
|
|
const product = new Product("?", mockService);
|
|
|
|
// Attempt update
|
|
product.UpdateShopifyProduct(mockShop);
|
|
|
|
// Verify no calls to creating product
|
|
// We expect MatchToShopifyProduct might be called (read only), but NOT productSet (writ)
|
|
// Actually our plan said "abort operation" at start of UpdateShopifyProduct.
|
|
expect(mockShop.productSetCalledWith).toBeNull();
|
|
});
|
|
|
|
test("ToShopifyProductSet should set handle to SKU", () => {
|
|
const product = new Product("TEST-SKU-1", mockService);
|
|
const sps = product.ToShopifyProductSet();
|
|
|
|
// We expect sps to have a 'handle' property equal to the sku
|
|
// This will fail compilation initially as ShopifyProductSetInput doesn't have handle
|
|
expect((sps as any).handle).toBe("TEST-SKU-1");
|
|
});
|
|
|
|
test("MatchToShopifyProduct should verify ID if present", () => {
|
|
// Setup data with shopify_id
|
|
mockService.setSheetData("product_inventory", [
|
|
["sku", "shopify_id"],
|
|
["TEST-SKU-OLD", "123456789"]
|
|
]);
|
|
const product = new Product("TEST-SKU-OLD", mockService);
|
|
|
|
// Mock the response for GetProductById
|
|
mockShop.mockProductById = {
|
|
id: "123456789",
|
|
title: "Old Title",
|
|
variants: { nodes: [{ id: "gid://shopify/ProductVariant/123456789", sku: "TEST-SKU-OLD" }] },
|
|
options: [{ id: "opt1", optionValues: [{ id: "optval1" }] }]
|
|
};
|
|
|
|
// We need to call Match, but it's called inside Update usually.
|
|
// We can call it directly for testing.
|
|
product.MatchToShopifyProduct(mockShop);
|
|
|
|
// Expect GetProductById to have been called
|
|
expect(mockShop.getProductByIdCalledWith).toBe("123456789");
|
|
expect(product.shopify_id).toBe("123456789");
|
|
});
|
|
|
|
test("MatchToShopifyProduct should fall back to SKU if ID lookup fails", () => {
|
|
// Setup data with shopify_id that is invalid
|
|
mockService.setSheetData("product_inventory", [
|
|
["sku", "shopify_id"],
|
|
["TEST-SKU-FAIL", "999999999"]
|
|
]);
|
|
const product = new Product("TEST-SKU-FAIL", mockService);
|
|
|
|
// Mock ID lookup failure (returns null/undefined)
|
|
mockShop.mockProductById = null;
|
|
|
|
// Mock SKU lookup success
|
|
mockShop.mockProductBySku = {
|
|
id: "555555555",
|
|
title: "Found By SKU",
|
|
variants: { nodes: [{ id: "gid://shopify/ProductVariant/555555555", sku: "TEST-SKU-FAIL" }] },
|
|
options: [{ id: "opt2", optionValues: [{ id: "optval2" }] }]
|
|
};
|
|
|
|
product.MatchToShopifyProduct(mockShop);
|
|
|
|
expect(mockShop.getProductByIdCalledWith).toBe("999999999");
|
|
// Should fall back to SKU
|
|
expect(mockShop.getProductBySkuCalledWith).toBe("TEST-SKU-FAIL");
|
|
expect(product.shopify_id).toBe("555555555");
|
|
});
|
|
});
|