feat(core-flows, product): options checks on product create/update (#9171)

**What**
- validate that variants are unique with respect to options on product update/create and variant update/create
- validate that the product has options upon creation
- ensure variants have the same number of option values as the product has options
- admin error handling
- update tests

---

FIXES FRMW-2707 CC-556
This commit is contained in:
Frane Polić
2024-10-15 11:06:51 +02:00
committed by GitHub
parent 20d19c1d67
commit 48cc00e991
21 changed files with 501 additions and 102 deletions
@@ -71,10 +71,12 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "Test product",
options: [{ title: "size", values: ["large", "small"] }],
variants: [
{
title: "Test variant",
sku: "test-variant",
options: { size: "large" },
prices: [
{
currency_code: "usd",
@@ -93,10 +95,12 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "Extra product",
options: [{ title: "size", values: ["large", "small"] }],
variants: [
{
title: "my variant",
sku: "variant-sku",
options: { size: "large" },
prices: [
{
currency_code: "usd",
@@ -49,6 +49,7 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "test-product",
options: [{ title: "size", values: ["x", "l"] }],
},
adminHeaders
)
@@ -59,6 +60,7 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "test-product1",
options: [{ title: "size", values: ["x", "l"] }],
},
adminHeaders
)
@@ -67,10 +67,12 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "Test product",
options: [{ title: "size", values: ["large", "small"] }],
variants: [
{
title: "Test variant",
sku: "test-variant",
options: { size: "large" },
prices: [
{
currency_code: "usd",
@@ -89,10 +91,12 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "Extra product",
options: [{ title: "size", values: ["large", "small"] }],
variants: [
{
title: "my variant",
sku: "variant-sku",
options: { size: "large" },
prices: [
{
currency_code: "usd",
@@ -839,9 +839,11 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "product 1",
options: [{ title: "size", values: ["large"] }],
variants: [
{
title: "variant 1",
options: { size: "large" },
prices: [{ currency_code: "usd", amount: 100 }],
inventory_items: [
{
@@ -90,10 +90,12 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "Test product",
options: [{ title: "size", values: ["large", "small"] }],
variants: [
{
title: "Test variant",
sku: "test-variant",
options: { size: "large" },
prices: [
{
currency_code: "usd",
@@ -112,10 +114,12 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "Extra product",
options: [{ title: "size", values: ["large", "small"] }],
variants: [
{
title: "my variant",
sku: "variant-sku",
options: { size: "large" },
prices: [
{
currency_code: "usd",
@@ -176,12 +176,12 @@ medusaIntegrationTestRunner({
)
})
it('gets the metadata of a category', async () => {
it("gets the metadata of a category", async () => {
await api.post(
`/admin/product-categories/${productCategory.id}`,
{
metadata: {
test: "test"
test: "test",
},
},
adminHeaders
@@ -193,7 +193,9 @@ medusaIntegrationTestRunner({
)
expect(response.status).toEqual(200)
expect(response.data.product_category.metadata).toEqual({ test: "test" })
expect(response.data.product_category.metadata).toEqual({
test: "test",
})
})
})
@@ -1345,6 +1347,7 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "product 1",
options: [{ title: "size", values: ["x", "l"] }],
categories: [{ id: productCategory.id }],
},
adminHeaders
@@ -1354,6 +1357,7 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "product 2",
options: [{ title: "color", values: ["r", "g"] }],
},
adminHeaders
)
@@ -667,10 +667,12 @@ medusaIntegrationTestRunner({
title: "Test Giftcard",
is_giftcard: true,
description: "test-giftcard-description",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Test variant",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "x" },
},
],
}
@@ -1056,10 +1058,12 @@ medusaIntegrationTestRunner({
const payload = {
title: "Test product - 1",
handle: "test-1",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Custom inventory 1",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "x" },
manage_inventory: true,
inventory_items: [
{
@@ -1097,16 +1101,19 @@ medusaIntegrationTestRunner({
const payload = {
title: "Test product - 1",
handle: "test-1",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Custom inventory 1",
prices: [{ currency_code: "usd", amount: 100 }],
manage_inventory: true,
options: { size: "x" },
inventory_items: [],
},
{
title: "Custom inventory 2",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "l" },
manage_inventory: false,
},
],
@@ -1294,9 +1301,11 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "Test create",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Price with rules",
options: { size: "l" },
prices: [
{
currency_code: "usd",
@@ -1345,10 +1354,12 @@ medusaIntegrationTestRunner({
images: [{ url: "test-image.png" }, { url: "test-image-2.png" }],
collection_id: baseCollection.id,
tags: [{ id: baseTag1.id }, { id: baseTag2.id }],
options: [{ title: "size", values: ["large"] }],
variants: [
{
title: "Test variant",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "large" },
},
],
}
@@ -1375,14 +1386,17 @@ medusaIntegrationTestRunner({
images: [{ url: "test-image.png" }, { url: "test-image-2.png" }],
collection_id: baseCollection.id,
tags: [{ id: baseTag1.id }, { id: baseTag2.id }],
options: [{ title: "size", values: ["l", x] }],
variants: [
{
title: "Test variant 1",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "x" },
},
{
title: "Test variant 2",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "l" },
},
],
}
@@ -1423,10 +1437,12 @@ medusaIntegrationTestRunner({
title: "Test Giftcard",
is_giftcard: true,
description: "test-giftcard-description",
options: [{ title: "size", values: ["large"] }],
variants: [
{
title: "Test variant",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "large" },
},
],
}
@@ -2096,11 +2112,13 @@ medusaIntegrationTestRunner({
const payload = {
title: "Test product - 1",
handle: "test-1",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Custom inventory 1",
prices: [{ currency_code: "usd", amount: 100 }],
manage_inventory: true,
options: { size: "l" },
inventory_items: [
{
inventory_item_id: inventoryItem1.id,
@@ -2207,10 +2225,12 @@ medusaIntegrationTestRunner({
const payload = {
title: "Test product - 1",
handle: "test-1",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Custom inventory 1",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "l" },
manage_inventory: true,
inventory_items: [
{
@@ -2256,10 +2276,12 @@ medusaIntegrationTestRunner({
const payload = {
title: "Test product - 1",
handle: "test-1",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Custom inventory 1",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "l" },
manage_inventory: true,
inventory_items: [
{
@@ -2678,10 +2700,12 @@ medusaIntegrationTestRunner({
const payload = {
title: baseProduct.title,
handle: baseProduct.handle,
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Test variant",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "x" },
},
],
}
@@ -2708,10 +2732,12 @@ medusaIntegrationTestRunner({
title: baseProduct.title,
handle: baseProduct.handle,
description: "test-product-description",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Test variant",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "x" },
},
],
}
@@ -2844,30 +2870,6 @@ medusaIntegrationTestRunner({
).toEqual("Updated variant")
})
it("removes options not present in update", async () => {
const baseVariant = baseProduct.variants[0]
const updatedProduct = (
await api.post(
`/admin/products/${baseProduct.id}/variants/${baseVariant.id}`,
{
title: "Updated variant",
options: {
size: "small",
},
},
adminHeaders
)
).data.product
expect(
updatedProduct.variants.find((v) => v.id === baseVariant.id).options
).toEqual([
expect.objectContaining({
value: "small",
}),
])
})
it("updates multiple options in the same call", async () => {
const baseVariant = baseProduct.variants[0]
const updatedProduct = (
@@ -801,18 +801,24 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "product 1",
options: [
{ title: "size", values: ["large", "medium", "small"] },
],
variants: [
{
title: "variant 1",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "large" },
},
{
title: "variant 2",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "small" },
},
{
title: "variant 3",
prices: [{ currency_code: "usd", amount: 100 }],
options: { size: "medium" },
},
],
},
@@ -517,12 +517,18 @@ medusaIntegrationTestRunner({
;[product3, [variant3]] = await createProducts({
title: "product not in price list",
status: ProductStatus.PUBLISHED,
variants: [{ title: "test variant 3", prices: [] }],
options: [{ title: "size", values: ["large", "small"] }],
variants: [
{ title: "test variant 3", prices: [], options: { size: "large" } },
],
})
;[product4, [variant4]] = await createProducts({
title: "draft product",
status: ProductStatus.DRAFT,
variants: [{ title: "test variant 4", prices: [] }],
options: [{ title: "size", values: ["large", "small"] }],
variants: [
{ title: "test variant 4", prices: [], options: { size: "large" } },
],
})
const defaultSalesChannel = await createSalesChannel(
@@ -1135,10 +1141,17 @@ medusaIntegrationTestRunner({
;[product, [variant]] = await createProducts({
title: "test product 1",
status: ProductStatus.PUBLISHED,
options: [{ title: "size", values: ["large"] }],
variants: [
{
title: "test variant 1",
prices: [{ amount: 3000, currency_code: "usd" }],
prices: [
{
amount: 3000,
currency_code: "usd",
options: { size: "large" },
},
],
},
],
})
@@ -1331,7 +1331,10 @@ medusaIntegrationTestRunner({
const product1 = (
await api.post(
"/admin/products",
{ title: "Test product 1" },
{
title: "Test product 1",
options: [{ title: "size", values: ["large", "small"] }],
},
adminHeaders
)
).data.product
@@ -1339,7 +1342,10 @@ medusaIntegrationTestRunner({
const product2 = (
await api.post(
"/admin/products",
{ title: "Test product 2" },
{
title: "Test product 2",
options: [{ title: "size", values: ["large", "small"] }],
},
adminHeaders
)
).data.product
@@ -30,10 +30,12 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "Test product",
options: [{ title: "size", values: ["x", "l"] }],
variants: [
{
title: "Test variant",
sku: "test-variant",
options: { size: "l" },
prices: [
{
currency_code: "usd",
@@ -327,6 +327,7 @@ medusaIntegrationTestRunner({
"/admin/products",
{
title: "test name",
options: [{ title: "size", values: ["large"] }],
},
adminHeaders
)