338 lines
8.8 KiB
JavaScript
338 lines
8.8 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
/**
|
||
|
|
* Test Products API with Color Variants
|
||
|
|
* Tests the new product creation and management features
|
||
|
|
*/
|
||
|
|
|
||
|
|
const axios = require("axios");
|
||
|
|
|
||
|
|
const API_URL = process.env.API_URL || "http://localhost:5000/api";
|
||
|
|
|
||
|
|
// Test data
|
||
|
|
const testProduct = {
|
||
|
|
name: "Vibrant Sunset Canvas Art",
|
||
|
|
shortdescription: "Beautiful hand-painted sunset artwork on premium canvas",
|
||
|
|
description:
|
||
|
|
"<p>This stunning piece captures the beauty of a <strong>vibrant sunset</strong> over the ocean. Hand-painted with premium acrylics on gallery-wrapped canvas.</p><p><strong>Features:</strong></p><ul><li>Gallery-wrapped canvas</li><li>Ready to hang</li><li>Signed by artist</li></ul>",
|
||
|
|
price: 249.99,
|
||
|
|
stockquantity: 10,
|
||
|
|
category: "Canvas Art",
|
||
|
|
sku: "ART-SUNSET-001",
|
||
|
|
weight: 2.5,
|
||
|
|
dimensions: "24x36 inches",
|
||
|
|
material: "Acrylic on Canvas",
|
||
|
|
isactive: true,
|
||
|
|
isfeatured: true,
|
||
|
|
isbestseller: false,
|
||
|
|
images: [
|
||
|
|
{
|
||
|
|
image_url: "/uploads/products/sunset-main.jpg",
|
||
|
|
color_variant: "Original",
|
||
|
|
alt_text: "Vibrant Sunset Canvas - Main View",
|
||
|
|
display_order: 0,
|
||
|
|
is_primary: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
image_url: "/uploads/products/sunset-blue.jpg",
|
||
|
|
color_variant: "Ocean Blue",
|
||
|
|
alt_text: "Vibrant Sunset Canvas - Blue Variant",
|
||
|
|
display_order: 1,
|
||
|
|
is_primary: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
image_url: "/uploads/products/sunset-warm.jpg",
|
||
|
|
color_variant: "Warm Tones",
|
||
|
|
alt_text: "Vibrant Sunset Canvas - Warm Variant",
|
||
|
|
display_order: 2,
|
||
|
|
is_primary: false,
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
|
||
|
|
let createdProductId = null;
|
||
|
|
let sessionCookie = null;
|
||
|
|
|
||
|
|
async function login() {
|
||
|
|
try {
|
||
|
|
console.log("🔐 Logging in...");
|
||
|
|
const response = await axios.post(
|
||
|
|
`${API_URL}/auth/login`,
|
||
|
|
{
|
||
|
|
email: process.env.ADMIN_EMAIL || "admin@skyartshop.com",
|
||
|
|
password: process.env.ADMIN_PASSWORD || "admin123",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
headers: { "Content-Type": "application/json" },
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
sessionCookie = response.headers["set-cookie"];
|
||
|
|
console.log("✅ Login successful\n");
|
||
|
|
return true;
|
||
|
|
} catch (error) {
|
||
|
|
console.error("❌ Login failed:", error.response?.data || error.message);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function createProduct() {
|
||
|
|
try {
|
||
|
|
console.log("📦 Creating new product...");
|
||
|
|
console.log("Product name:", testProduct.name);
|
||
|
|
console.log(
|
||
|
|
"Color variants:",
|
||
|
|
testProduct.images.map((img) => img.color_variant).join(", ")
|
||
|
|
);
|
||
|
|
|
||
|
|
const response = await axios.post(
|
||
|
|
`${API_URL}/admin/products`,
|
||
|
|
testProduct,
|
||
|
|
{
|
||
|
|
headers: {
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
Cookie: sessionCookie,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
if (response.data.success) {
|
||
|
|
createdProductId = response.data.product.id;
|
||
|
|
console.log("✅ Product created successfully!");
|
||
|
|
console.log("Product ID:", createdProductId);
|
||
|
|
console.log("Images count:", response.data.product.images?.length || 0);
|
||
|
|
console.log("");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error(
|
||
|
|
"❌ Product creation failed:",
|
||
|
|
error.response?.data || error.message
|
||
|
|
);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function getProduct() {
|
||
|
|
try {
|
||
|
|
console.log("📖 Fetching product details...");
|
||
|
|
|
||
|
|
const response = await axios.get(
|
||
|
|
`${API_URL}/admin/products/${createdProductId}`,
|
||
|
|
{
|
||
|
|
headers: { Cookie: sessionCookie },
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
if (response.data.success) {
|
||
|
|
const product = response.data.product;
|
||
|
|
console.log("✅ Product retrieved successfully!");
|
||
|
|
console.log("Name:", product.name);
|
||
|
|
console.log("Price:", product.price);
|
||
|
|
console.log("SKU:", product.sku);
|
||
|
|
console.log("Stock:", product.stockquantity);
|
||
|
|
console.log("Active:", product.isactive);
|
||
|
|
console.log("Featured:", product.isfeatured);
|
||
|
|
console.log("Images:");
|
||
|
|
|
||
|
|
if (product.images && product.images.length > 0) {
|
||
|
|
product.images.forEach((img, idx) => {
|
||
|
|
console.log(
|
||
|
|
` ${idx + 1}. ${img.color_variant || "Default"} - ${
|
||
|
|
img.image_url
|
||
|
|
} ${img.is_primary ? "(Primary)" : ""}`
|
||
|
|
);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
console.log("");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error(
|
||
|
|
"❌ Failed to fetch product:",
|
||
|
|
error.response?.data || error.message
|
||
|
|
);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function updateProduct() {
|
||
|
|
try {
|
||
|
|
console.log("✏️ Updating product...");
|
||
|
|
|
||
|
|
const updateData = {
|
||
|
|
price: 199.99,
|
||
|
|
stockquantity: 15,
|
||
|
|
isbestseller: true,
|
||
|
|
images: [
|
||
|
|
...testProduct.images,
|
||
|
|
{
|
||
|
|
image_url: "/uploads/products/sunset-purple.jpg",
|
||
|
|
color_variant: "Purple Haze",
|
||
|
|
alt_text: "Vibrant Sunset Canvas - Purple Variant",
|
||
|
|
display_order: 3,
|
||
|
|
is_primary: false,
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
|
||
|
|
const response = await axios.put(
|
||
|
|
`${API_URL}/admin/products/${createdProductId}`,
|
||
|
|
updateData,
|
||
|
|
{
|
||
|
|
headers: {
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
Cookie: sessionCookie,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
if (response.data.success) {
|
||
|
|
console.log("✅ Product updated successfully!");
|
||
|
|
console.log("New price:", response.data.product.price);
|
||
|
|
console.log("New stock:", response.data.product.stockquantity);
|
||
|
|
console.log("Bestseller:", response.data.product.isbestseller);
|
||
|
|
console.log("Total images:", response.data.product.images?.length || 0);
|
||
|
|
console.log("");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error(
|
||
|
|
"❌ Product update failed:",
|
||
|
|
error.response?.data || error.message
|
||
|
|
);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function listProducts() {
|
||
|
|
try {
|
||
|
|
console.log("📋 Listing all products...");
|
||
|
|
|
||
|
|
const response = await axios.get(`${API_URL}/admin/products`, {
|
||
|
|
headers: { Cookie: sessionCookie },
|
||
|
|
});
|
||
|
|
|
||
|
|
if (response.data.success) {
|
||
|
|
console.log(`✅ Found ${response.data.products.length} products`);
|
||
|
|
response.data.products.forEach((p, idx) => {
|
||
|
|
console.log(
|
||
|
|
`${idx + 1}. ${p.name} - $${p.price} (${p.image_count || 0} images)`
|
||
|
|
);
|
||
|
|
});
|
||
|
|
console.log("");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error(
|
||
|
|
"❌ Failed to list products:",
|
||
|
|
error.response?.data || error.message
|
||
|
|
);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function getPublicProduct() {
|
||
|
|
try {
|
||
|
|
console.log("🌐 Fetching product from public API...");
|
||
|
|
|
||
|
|
const response = await axios.get(
|
||
|
|
`${API_URL}/public/products/${createdProductId}`
|
||
|
|
);
|
||
|
|
|
||
|
|
if (response.data.success) {
|
||
|
|
const product = response.data.product;
|
||
|
|
console.log("✅ Public product retrieved!");
|
||
|
|
console.log("Name:", product.name);
|
||
|
|
console.log(
|
||
|
|
"Short description:",
|
||
|
|
product.shortdescription?.substring(0, 50) + "..."
|
||
|
|
);
|
||
|
|
console.log("Color variants available:");
|
||
|
|
|
||
|
|
const variants = [
|
||
|
|
...new Set(
|
||
|
|
product.images?.map((img) => img.color_variant).filter(Boolean)
|
||
|
|
),
|
||
|
|
];
|
||
|
|
variants.forEach((variant) => {
|
||
|
|
console.log(` - ${variant}`);
|
||
|
|
});
|
||
|
|
console.log("");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error(
|
||
|
|
"❌ Failed to fetch public product:",
|
||
|
|
error.response?.data || error.message
|
||
|
|
);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function deleteProduct() {
|
||
|
|
try {
|
||
|
|
console.log("🗑️ Deleting test product...");
|
||
|
|
|
||
|
|
const response = await axios.delete(
|
||
|
|
`${API_URL}/admin/products/${createdProductId}`,
|
||
|
|
{
|
||
|
|
headers: { Cookie: sessionCookie },
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
if (response.data.success) {
|
||
|
|
console.log("✅ Product deleted successfully!");
|
||
|
|
console.log("");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error(
|
||
|
|
"❌ Product deletion failed:",
|
||
|
|
error.response?.data || error.message
|
||
|
|
);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function runTests() {
|
||
|
|
console.log("=".repeat(60));
|
||
|
|
console.log(" PRODUCTS API TEST - Color Variants & Rich Text");
|
||
|
|
console.log("=".repeat(60));
|
||
|
|
console.log("");
|
||
|
|
|
||
|
|
const steps = [
|
||
|
|
{ name: "Login", fn: login },
|
||
|
|
{ name: "Create Product", fn: createProduct },
|
||
|
|
{ name: "Get Product", fn: getProduct },
|
||
|
|
{ name: "Update Product", fn: updateProduct },
|
||
|
|
{ name: "List Products", fn: listProducts },
|
||
|
|
{ name: "Get Public Product", fn: getPublicProduct },
|
||
|
|
{ name: "Delete Product", fn: deleteProduct },
|
||
|
|
];
|
||
|
|
|
||
|
|
let passed = 0;
|
||
|
|
let failed = 0;
|
||
|
|
|
||
|
|
for (const step of steps) {
|
||
|
|
const success = await step.fn();
|
||
|
|
if (success) {
|
||
|
|
passed++;
|
||
|
|
} else {
|
||
|
|
failed++;
|
||
|
|
console.log(`⚠️ Stopping tests due to failure in: ${step.name}\n`);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log("=".repeat(60));
|
||
|
|
console.log(`TEST RESULTS: ${passed} passed, ${failed} failed`);
|
||
|
|
console.log("=".repeat(60));
|
||
|
|
|
||
|
|
process.exit(failed > 0 ? 1 : 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
runTests().catch((error) => {
|
||
|
|
console.error("Fatal error:", error);
|
||
|
|
process.exit(1);
|
||
|
|
});
|