Chore/integration tests modules utils (#6581)
new wrapper for medusa integration tests. for now it is only applied to the modules directory, but it could be used in the api integration tests or any other integrations that requires a db and a server up and running. It is not perfect, but I wanted to have something working and centralised before improving it, also avoiding too many conflicts with other prs
This commit is contained in:
+151
-165
@@ -1,17 +1,12 @@
|
||||
import { PricingModuleService } from "@medusajs/pricing"
|
||||
import { ProductModuleService } from "@medusajs/product"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
@@ -25,180 +20,171 @@ const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("POST /admin/products/:id/variants", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
medusaIntegrationTestRunner({
|
||||
env,
|
||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||
describe.skip("POST /admin/products/:id/variants", () => {
|
||||
let appContainer
|
||||
let product
|
||||
let variant
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
})
|
||||
beforeAll(async () => {
|
||||
appContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a product variant with its price sets and prices through the workflow", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant create",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
material: "boo",
|
||||
mid_code: "234asdfadsf",
|
||||
hs_code: "asdfasdf234",
|
||||
origin_country: "DE",
|
||||
sku: "asdf",
|
||||
ean: "234",
|
||||
upc: "234",
|
||||
barcode: "asdf",
|
||||
inventory_quantity: 234,
|
||||
manage_inventory: true,
|
||||
allow_backorder: true,
|
||||
weight: 234,
|
||||
width: 234,
|
||||
height: 234,
|
||||
length: 234,
|
||||
metadata: { asdf: "asdf" },
|
||||
options: [{ option_id: "test-product-option-1", value: "test option" }],
|
||||
}
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
let response = await api.post(
|
||||
`/admin/products/${product.id}/variants`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
it("should create a product variant with its price sets and prices through the workflow", async () => {
|
||||
const data = {
|
||||
title: "test variant create",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
material: "boo",
|
||||
mid_code: "234asdfadsf",
|
||||
hs_code: "asdfasdf234",
|
||||
origin_country: "DE",
|
||||
sku: "asdf",
|
||||
ean: "234",
|
||||
upc: "234",
|
||||
barcode: "asdf",
|
||||
inventory_quantity: 234,
|
||||
manage_inventory: true,
|
||||
allow_backorder: true,
|
||||
weight: 234,
|
||||
width: 234,
|
||||
height: 234,
|
||||
length: 234,
|
||||
metadata: { asdf: "asdf" },
|
||||
options: [
|
||||
{ option_id: "test-product-option-1", value: "test option" },
|
||||
],
|
||||
}
|
||||
|
||||
let response = await api.post(
|
||||
`/admin/products/${product.id}/variants`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: "test variant create",
|
||||
prices: expect.arrayContaining([
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
id: expect.any(String),
|
||||
title: "test variant create",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should compensate creating product variants when error throws in future step", async () => {
|
||||
jest
|
||||
.spyOn(PricingModuleService.prototype, "create")
|
||||
.mockImplementation(() => {
|
||||
throw new Error("Random Error")
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
const productSpy = jest.spyOn(
|
||||
ProductModuleService.prototype,
|
||||
"deleteVariants"
|
||||
)
|
||||
it("should compensate creating product variants when error throws in future step", async () => {
|
||||
jest
|
||||
.spyOn(PricingModuleService.prototype, "create")
|
||||
.mockImplementation(() => {
|
||||
throw new Error("Random Error")
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant create",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
material: "boo",
|
||||
mid_code: "234asdfadsf",
|
||||
hs_code: "asdfasdf234",
|
||||
origin_country: "DE",
|
||||
sku: "asdf",
|
||||
ean: "234",
|
||||
upc: "234",
|
||||
barcode: "asdf",
|
||||
inventory_quantity: 234,
|
||||
manage_inventory: true,
|
||||
allow_backorder: true,
|
||||
weight: 234,
|
||||
width: 234,
|
||||
height: 234,
|
||||
length: 234,
|
||||
metadata: { asdf: "asdf" },
|
||||
options: [{ option_id: "test-product-option-1", value: "test option" }],
|
||||
}
|
||||
const productSpy = jest.spyOn(
|
||||
ProductModuleService.prototype,
|
||||
"deleteVariants"
|
||||
)
|
||||
|
||||
await api
|
||||
.post(`/admin/products/${product.id}/variants`, data, adminHeaders)
|
||||
.catch((e) => e)
|
||||
const data = {
|
||||
title: "test variant create",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
material: "boo",
|
||||
mid_code: "234asdfadsf",
|
||||
hs_code: "asdfasdf234",
|
||||
origin_country: "DE",
|
||||
sku: "asdf",
|
||||
ean: "234",
|
||||
upc: "234",
|
||||
barcode: "asdf",
|
||||
inventory_quantity: 234,
|
||||
manage_inventory: true,
|
||||
allow_backorder: true,
|
||||
weight: 234,
|
||||
width: 234,
|
||||
height: 234,
|
||||
length: 234,
|
||||
metadata: { asdf: "asdf" },
|
||||
options: [
|
||||
{ option_id: "test-product-option-1", value: "test option" },
|
||||
],
|
||||
}
|
||||
|
||||
expect(productSpy).toBeCalledWith([expect.any(String)])
|
||||
await api
|
||||
.post(`/admin/products/${product.id}/variants`, data, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
const getProductResponse = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(getProductResponse.data.product.variants).toHaveLength(1)
|
||||
})
|
||||
expect(productSpy).toBeCalledWith([expect.any(String)])
|
||||
|
||||
const getProductResponse = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(getProductResponse.data.product.variants).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import productSeeder from "../../../../helpers/product-seeder"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleSalesChannelFactory,
|
||||
} from "../../../../factories"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { medusaIntegrationTestRunner } from "medusa-test-utils/dist"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
@@ -26,469 +13,448 @@ const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("/admin/products", () => {
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
let medusaContainer
|
||||
medusaIntegrationTestRunner({
|
||||
env,
|
||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||
describe("/admin/products", () => {
|
||||
let medusaContainer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env })
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
medusaContainer = getContainer()
|
||||
})
|
||||
beforeAll(async () => {
|
||||
medusaContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders, medusaContainer)
|
||||
|
||||
describe("POST /admin/products", () => {
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
// await productSeeder(dbConnection)
|
||||
// await createDefaultRuleTypes(medusaContainer)
|
||||
// await simpleSalesChannelFactory(dbConnection, {
|
||||
// name: "Default channel",
|
||||
// id: "default-channel",
|
||||
// is_default: true,
|
||||
// })
|
||||
})
|
||||
|
||||
// await productSeeder(dbConnection)
|
||||
// await createDefaultRuleTypes(medusaContainer)
|
||||
// await simpleSalesChannelFactory(dbConnection, {
|
||||
// name: "Default channel",
|
||||
// id: "default-channel",
|
||||
// is_default: true,
|
||||
// })
|
||||
})
|
||||
describe("POST /admin/products", () => {
|
||||
it("should create a product", async () => {
|
||||
const payload = {
|
||||
title: "Test",
|
||||
description: "test-product-description",
|
||||
// type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
// collection_id: "test-collection",
|
||||
// tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
// prices: [
|
||||
// {
|
||||
// currency_code: "usd",
|
||||
// amount: 100,
|
||||
// },
|
||||
// {
|
||||
// currency_code: "eur",
|
||||
// amount: 45,
|
||||
// },
|
||||
// {
|
||||
// currency_code: "dkk",
|
||||
// amount: 30,
|
||||
// },
|
||||
// ],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
it("should create a product", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test",
|
||||
description: "test-product-description",
|
||||
// type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
// collection_id: "test-collection",
|
||||
// tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
// prices: [
|
||||
// {
|
||||
// currency_code: "usd",
|
||||
// amount: 100,
|
||||
// },
|
||||
// {
|
||||
// currency_code: "eur",
|
||||
// amount: 45,
|
||||
// },
|
||||
// {
|
||||
// currency_code: "dkk",
|
||||
// amount: 30,
|
||||
// },
|
||||
// ],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^prod_*/),
|
||||
title: "Test",
|
||||
discountable: true,
|
||||
is_giftcard: false,
|
||||
handle: "test",
|
||||
status: "draft",
|
||||
// profile_id: expect.stringMatching(/^sp_*/),
|
||||
thumbnail: "test-image.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
})
|
||||
)
|
||||
|
||||
expect(response?.data.product.images).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
url: "test-image.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
url: "test-image-2.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
console.log(response?.data.product)
|
||||
|
||||
expect(response?.data.product.variants).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^variant_*/),
|
||||
title: "Test variant",
|
||||
// product_id: expect.stringMatching(/^prod_*/),
|
||||
updated_at: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
// prices: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// id: expect.stringMatching(/^ma_*/),
|
||||
// currency_code: "usd",
|
||||
// amount: 100,
|
||||
// // TODO: enable this in the Pricing Module PR
|
||||
// // created_at: expect.any(String),
|
||||
// // updated_at: expect.any(String),
|
||||
// // variant_id: expect.stringMatching(/^variant_*/),
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// id: expect.stringMatching(/^ma_*/),
|
||||
// currency_code: "eur",
|
||||
// amount: 45,
|
||||
// // TODO: enable this in the Pricing Module PR
|
||||
// // created_at: expect.any(String),
|
||||
// // updated_at: expect.any(String),
|
||||
// // variant_id: expect.stringMatching(/^variant_*/),
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// id: expect.stringMatching(/^ma_*/),
|
||||
// currency_code: "dkk",
|
||||
// amount: 30,
|
||||
// // TODO: enable this in the Pricing Module PR
|
||||
// // created_at: expect.any(String),
|
||||
// // updated_at: expect.any(String),
|
||||
// // variant_id: expect.stringMatching(/^variant_*/),
|
||||
// }),
|
||||
// ]),
|
||||
// options: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// value: "large",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
// option_id: expect.stringMatching(/^opt_*/),
|
||||
// id: expect.stringMatching(/^optval_*/),
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// value: "green",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
// option_id: expect.stringMatching(/^opt_*/),
|
||||
// id: expect.stringMatching(/^optval_*/),
|
||||
// }),
|
||||
// ]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(response?.data.product.options).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^opt_*/),
|
||||
// product_id: expect.stringMatching(/^prod_*/),
|
||||
title: "size",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^opt_*/),
|
||||
// product_id: expect.stringMatching(/^prod_*/),
|
||||
title: "color",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
// tags: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// id: expect.any(String),
|
||||
// value: "123",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// id: expect.any(String),
|
||||
// value: "456",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// }),
|
||||
// ]),
|
||||
// type: expect.objectContaining({
|
||||
// value: "test-type",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// }),
|
||||
// collection: expect.objectContaining({
|
||||
// id: "test-collection",
|
||||
// title: "Test collection",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// }),
|
||||
})
|
||||
|
||||
it("should create a product that is not discountable", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test",
|
||||
discountable: false,
|
||||
description: "test-product-description",
|
||||
// type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
// collection_id: "test-collection",
|
||||
// tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
discountable: false,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should sets the variant ranks when creating a product", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test product - 1",
|
||||
description: "test-product-description 1",
|
||||
// type: { value: "test-type 1" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
// collection_id: "test-collection",
|
||||
// tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant 1",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const creationResponse = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(creationResponse?.status).toEqual(200)
|
||||
|
||||
const productId = creationResponse?.data.product.id
|
||||
|
||||
const response = await api
|
||||
.get(
|
||||
`/admin/products/${productId}?fields=title,variants.title`,
|
||||
adminHeaders
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test product - 1",
|
||||
variants: [
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test variant 1",
|
||||
}),
|
||||
id: expect.stringMatching(/^prod_*/),
|
||||
title: "Test",
|
||||
discountable: true,
|
||||
is_giftcard: false,
|
||||
handle: "test",
|
||||
status: "draft",
|
||||
// profile_id: expect.stringMatching(/^sp_*/),
|
||||
thumbnail: "test-image.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
})
|
||||
)
|
||||
|
||||
expect(response?.data.product.images).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
url: "test-image.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
url: "test-image-2.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
console.log(response?.data.product)
|
||||
|
||||
expect(response?.data.product.variants).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^variant_*/),
|
||||
title: "Test variant",
|
||||
// product_id: expect.stringMatching(/^prod_*/),
|
||||
updated_at: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
// prices: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// id: expect.stringMatching(/^ma_*/),
|
||||
// currency_code: "usd",
|
||||
// amount: 100,
|
||||
// // TODO: enable this in the Pricing Module PR
|
||||
// // created_at: expect.any(String),
|
||||
// // updated_at: expect.any(String),
|
||||
// // variant_id: expect.stringMatching(/^variant_*/),
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// id: expect.stringMatching(/^ma_*/),
|
||||
// currency_code: "eur",
|
||||
// amount: 45,
|
||||
// // TODO: enable this in the Pricing Module PR
|
||||
// // created_at: expect.any(String),
|
||||
// // updated_at: expect.any(String),
|
||||
// // variant_id: expect.stringMatching(/^variant_*/),
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// id: expect.stringMatching(/^ma_*/),
|
||||
// currency_code: "dkk",
|
||||
// amount: 30,
|
||||
// // TODO: enable this in the Pricing Module PR
|
||||
// // created_at: expect.any(String),
|
||||
// // updated_at: expect.any(String),
|
||||
// // variant_id: expect.stringMatching(/^variant_*/),
|
||||
// }),
|
||||
// ]),
|
||||
// options: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// value: "large",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
// option_id: expect.stringMatching(/^opt_*/),
|
||||
// id: expect.stringMatching(/^optval_*/),
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// value: "green",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
// option_id: expect.stringMatching(/^opt_*/),
|
||||
// id: expect.stringMatching(/^optval_*/),
|
||||
// }),
|
||||
// ]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(response?.data.product.options).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^opt_*/),
|
||||
// product_id: expect.stringMatching(/^prod_*/),
|
||||
title: "size",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^opt_*/),
|
||||
// product_id: expect.stringMatching(/^prod_*/),
|
||||
title: "color",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
// tags: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// id: expect.any(String),
|
||||
// value: "123",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// id: expect.any(String),
|
||||
// value: "456",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// }),
|
||||
// ]),
|
||||
// type: expect.objectContaining({
|
||||
// value: "test-type",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// }),
|
||||
// collection: expect.objectContaining({
|
||||
// id: "test-collection",
|
||||
// title: "Test collection",
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// }),
|
||||
})
|
||||
|
||||
it("should create a product that is not discountable", async () => {
|
||||
const payload = {
|
||||
title: "Test",
|
||||
discountable: false,
|
||||
description: "test-product-description",
|
||||
// type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
// collection_id: "test-collection",
|
||||
// tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test variant 2",
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a giftcard", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test Giftcard",
|
||||
is_giftcard: true,
|
||||
description: "test-giftcard-description",
|
||||
options: [{ title: "Denominations" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "100" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
discountable: false,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
it("should sets the variant ranks when creating a product", async () => {
|
||||
const payload = {
|
||||
title: "Test product - 1",
|
||||
description: "test-product-description 1",
|
||||
// type: { value: "test-type 1" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
// collection_id: "test-collection",
|
||||
// tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant 1",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test Giftcard",
|
||||
discountable: false,
|
||||
const creationResponse = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(creationResponse?.status).toEqual(200)
|
||||
|
||||
const productId = creationResponse?.data.product.id
|
||||
|
||||
const response = await api
|
||||
.get(
|
||||
`/admin/products/${productId}?fields=title,variants.title`,
|
||||
adminHeaders
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test product - 1",
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
title: "Test variant 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "Test variant 2",
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create variants with inventory items", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
it("should create a giftcard", async () => {
|
||||
const payload = {
|
||||
title: "Test Giftcard",
|
||||
is_giftcard: true,
|
||||
description: "test-giftcard-description",
|
||||
options: [{ title: "Denominations" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "100" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/products`,
|
||||
{
|
||||
title: "Test product - 1",
|
||||
description: "test-product-description 1",
|
||||
// type: { value: "test-type 1" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
// collection_id: "test-collection",
|
||||
// tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test Giftcard",
|
||||
discountable: false,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create variants with inventory items", async () => {
|
||||
const response = await api.post(
|
||||
`/admin/products`,
|
||||
{
|
||||
title: "Test variant 1",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
title: "Test product - 1",
|
||||
description: "test-product-description 1",
|
||||
// type: { value: "test-type 1" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
// collection_id: "test-collection",
|
||||
// tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant 1",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
inventory_quantity: 10,
|
||||
// prices: [{ currency_code: "usd", amount: 100 }],
|
||||
// options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
// const variantIds = response.data.product.variants.map(
|
||||
// (v: { id: string }) => v.id
|
||||
// )
|
||||
// const variantIds = response.data.product.variants.map(
|
||||
// (v: { id: string }) => v.id
|
||||
// )
|
||||
|
||||
// const variantInventoryService = medusaContainer.resolve(
|
||||
// "productVariantInventoryService"
|
||||
// )
|
||||
// const inventory = await variantInventoryService.listByVariant(variantIds)
|
||||
// const variantInventoryService = medusaContainer.resolve(
|
||||
// "productVariantInventoryService"
|
||||
// )
|
||||
// const inventory = await variantInventoryService.listByVariant(variantIds)
|
||||
|
||||
// expect(inventory).toHaveLength(2)
|
||||
// expect(inventory).toContainEqual(
|
||||
// expect.objectContaining({
|
||||
// variant_id: variantIds[0],
|
||||
// required_quantity: 1,
|
||||
// })
|
||||
// )
|
||||
// expect(inventory).toContainEqual(
|
||||
// expect.objectContaining({
|
||||
// variant_id: variantIds[1],
|
||||
// required_quantity: 1,
|
||||
// })
|
||||
// )
|
||||
// expect(inventory).toHaveLength(2)
|
||||
// expect(inventory).toContainEqual(
|
||||
// expect.objectContaining({
|
||||
// variant_id: variantIds[0],
|
||||
// required_quantity: 1,
|
||||
// })
|
||||
// )
|
||||
// expect(inventory).toContainEqual(
|
||||
// expect.objectContaining({
|
||||
// variant_id: variantIds[1],
|
||||
// required_quantity: 1,
|
||||
// })
|
||||
// )
|
||||
})
|
||||
|
||||
// it("should create prices with region_id and currency_code context", async () => {
|
||||
// const api = useApi()! as AxiosInstance
|
||||
|
||||
// const data = {
|
||||
// title: "test product",
|
||||
// options: [{ title: "test-option" }],
|
||||
// variants: [
|
||||
// {
|
||||
// title: "test variant",
|
||||
// prices: [
|
||||
// {
|
||||
// amount: 66600,
|
||||
// region_id: "test-region",
|
||||
// },
|
||||
// {
|
||||
// amount: 55500,
|
||||
// currency_code: "usd",
|
||||
// },
|
||||
// ],
|
||||
// options: [{ value: "test-option" }],
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
|
||||
// let response = await api.post(
|
||||
// "/admin/products?relations=variants.prices",
|
||||
// data,
|
||||
// adminHeaders
|
||||
// )
|
||||
|
||||
// expect(response.status).toEqual(200)
|
||||
// expect(response.data).toEqual({
|
||||
// product: expect.objectContaining({
|
||||
// id: expect.any(String),
|
||||
// title: "test product",
|
||||
// variants: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// id: expect.any(String),
|
||||
// title: "test variant",
|
||||
// prices: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// amount: 66600,
|
||||
// currency_code: "usd",
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// amount: 55500,
|
||||
// currency_code: "usd",
|
||||
// }),
|
||||
// ]),
|
||||
// }),
|
||||
// ]),
|
||||
// }),
|
||||
// })
|
||||
|
||||
// const pricingModuleService: IPricingModuleService = appContainer.resolve(
|
||||
// "pricingModuleService"
|
||||
// )
|
||||
|
||||
// const [_, count] = await pricingModuleService.listAndCount()
|
||||
// expect(count).toEqual(1)
|
||||
// })
|
||||
})
|
||||
})
|
||||
|
||||
// it("should create prices with region_id and currency_code context", async () => {
|
||||
// const api = useApi()! as AxiosInstance
|
||||
|
||||
// const data = {
|
||||
// title: "test product",
|
||||
// options: [{ title: "test-option" }],
|
||||
// variants: [
|
||||
// {
|
||||
// title: "test variant",
|
||||
// prices: [
|
||||
// {
|
||||
// amount: 66600,
|
||||
// region_id: "test-region",
|
||||
// },
|
||||
// {
|
||||
// amount: 55500,
|
||||
// currency_code: "usd",
|
||||
// },
|
||||
// ],
|
||||
// options: [{ value: "test-option" }],
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
|
||||
// let response = await api.post(
|
||||
// "/admin/products?relations=variants.prices",
|
||||
// data,
|
||||
// adminHeaders
|
||||
// )
|
||||
|
||||
// expect(response.status).toEqual(200)
|
||||
// expect(response.data).toEqual({
|
||||
// product: expect.objectContaining({
|
||||
// id: expect.any(String),
|
||||
// title: "test product",
|
||||
// variants: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// id: expect.any(String),
|
||||
// title: "test variant",
|
||||
// prices: expect.arrayContaining([
|
||||
// expect.objectContaining({
|
||||
// amount: 66600,
|
||||
// currency_code: "usd",
|
||||
// }),
|
||||
// expect.objectContaining({
|
||||
// amount: 55500,
|
||||
// currency_code: "usd",
|
||||
// }),
|
||||
// ]),
|
||||
// }),
|
||||
// ]),
|
||||
// }),
|
||||
// })
|
||||
|
||||
// const pricingModuleService: IPricingModuleService = appContainer.resolve(
|
||||
// "pricingModuleService"
|
||||
// )
|
||||
|
||||
// const [_, count] = await pricingModuleService.listAndCount()
|
||||
// expect(count).toEqual(1)
|
||||
// })
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -24,6 +24,10 @@ const env: Record<any, any> = {
|
||||
|
||||
jest.setTimeout(180000)
|
||||
|
||||
// TODO SEE to use new test runner medusaIntegrationTestRunner({
|
||||
// env,
|
||||
// testSuite: ({ dbConnection, getContainer, api }) => {})
|
||||
|
||||
describe.skip("Batch job of product-export type", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
@@ -56,6 +56,10 @@ const env: Record<any, any> = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
// TODO SEE to use new test runner medusaIntegrationTestRunner({
|
||||
// env,
|
||||
// testSuite: ({ dbConnection, getContainer, api }) => {})
|
||||
|
||||
describe.skip("Product import batch job", () => {
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
|
||||
@@ -0,0 +1,659 @@
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import productSeeder from "../../../../helpers/product-seeder"
|
||||
|
||||
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
|
||||
import { MedusaV2Flag } from "@medusajs/utils"
|
||||
import { AxiosInstance } from "axios"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleSalesChannelFactory,
|
||||
} from "../../../../factories"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
// TODO SEE to use new test runner medusaIntegrationTestRunner({
|
||||
// env,
|
||||
// testSuite: ({ dbConnection, getContainer, api }) => {})
|
||||
|
||||
describe.skip("/admin/products", () => {
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
let medusaContainer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env })
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
medusaContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
it("Should have loaded the product module", function () {
|
||||
const productRegistrationName =
|
||||
ModulesDefinition[Modules.PRODUCT].registrationName
|
||||
expect(
|
||||
medusaContainer.hasRegistration(productRegistrationName)
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should have enabled workflows feature flag", function () {
|
||||
const flagRouter = medusaContainer.resolve("featureFlagRouter")
|
||||
|
||||
const workflowsFlag = flagRouter.isFeatureEnabled(MedusaV2Flag.key)
|
||||
|
||||
expect(workflowsFlag).toBe(true)
|
||||
})
|
||||
|
||||
describe("POST /admin/products", () => {
|
||||
beforeEach(async () => {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(medusaContainer)
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "Default channel",
|
||||
id: "default-channel",
|
||||
is_default: true,
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a product", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test",
|
||||
description: "test-product-description",
|
||||
type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
prices: [
|
||||
{
|
||||
currency_code: "usd",
|
||||
amount: 100,
|
||||
},
|
||||
{
|
||||
currency_code: "eur",
|
||||
amount: 45,
|
||||
},
|
||||
{
|
||||
currency_code: "dkk",
|
||||
amount: 30,
|
||||
},
|
||||
],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^prod_*/),
|
||||
title: "Test",
|
||||
discountable: true,
|
||||
is_giftcard: false,
|
||||
handle: "test",
|
||||
status: "draft",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
profile_id: expect.stringMatching(/^sp_*/),
|
||||
images: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
url: "test-image.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
url: "test-image-2.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
]),
|
||||
thumbnail: "test-image.png",
|
||||
tags: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: "123",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: "456",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
]),
|
||||
type: expect.objectContaining({
|
||||
value: "test-type",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
collection: expect.objectContaining({
|
||||
id: "test-collection",
|
||||
title: "Test collection",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^opt_*/),
|
||||
product_id: expect.stringMatching(/^prod_*/),
|
||||
title: "size",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^opt_*/),
|
||||
product_id: expect.stringMatching(/^prod_*/),
|
||||
title: "color",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
]),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^variant_*/),
|
||||
product_id: expect.stringMatching(/^prod_*/),
|
||||
updated_at: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
title: "Test variant",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^ma_*/),
|
||||
currency_code: "usd",
|
||||
amount: 100,
|
||||
// TODO: enable this in the Pricing Module PR
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^ma_*/),
|
||||
currency_code: "eur",
|
||||
amount: 45,
|
||||
// TODO: enable this in the Pricing Module PR
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^ma_*/),
|
||||
currency_code: "dkk",
|
||||
amount: 30,
|
||||
// TODO: enable this in the Pricing Module PR
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
}),
|
||||
]),
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: "large",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
variant_id: expect.stringMatching(/^variant_*/),
|
||||
option_id: expect.stringMatching(/^opt_*/),
|
||||
id: expect.stringMatching(/^optval_*/),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
value: "green",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
variant_id: expect.stringMatching(/^variant_*/),
|
||||
option_id: expect.stringMatching(/^opt_*/),
|
||||
id: expect.stringMatching(/^optval_*/),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a product that is not discountable", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test",
|
||||
discountable: false,
|
||||
description: "test-product-description",
|
||||
type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
discountable: false,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should sets the variant ranks when creating a product", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test product - 1",
|
||||
description: "test-product-description 1",
|
||||
type: { value: "test-type 1" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant 1",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const creationResponse = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(creationResponse?.status).toEqual(200)
|
||||
|
||||
const productId = creationResponse?.data.product.id
|
||||
|
||||
const response = await api
|
||||
.get(`/admin/products/${productId}`, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test product - 1",
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
title: "Test variant 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "Test variant 2",
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a giftcard", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test Giftcard",
|
||||
is_giftcard: true,
|
||||
description: "test-giftcard-description",
|
||||
options: [{ title: "Denominations" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "100" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test Giftcard",
|
||||
discountable: false,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create variants with inventory items", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/products`,
|
||||
{
|
||||
title: "Test product - 1",
|
||||
description: "test-product-description 1",
|
||||
type: { value: "test-type 1" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant 1",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
{ headers: { "x-medusa-access-token": "test_token" } }
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const variantIds = response.data.product.variants.map(
|
||||
(v: { id: string }) => v.id
|
||||
)
|
||||
|
||||
const variantInventoryService = medusaContainer.resolve(
|
||||
"productVariantInventoryService"
|
||||
)
|
||||
const inventory = await variantInventoryService.listByVariant(variantIds)
|
||||
|
||||
expect(inventory).toHaveLength(2)
|
||||
expect(inventory).toContainEqual(
|
||||
expect.objectContaining({
|
||||
variant_id: variantIds[0],
|
||||
required_quantity: 1,
|
||||
})
|
||||
)
|
||||
expect(inventory).toContainEqual(
|
||||
expect.objectContaining({
|
||||
variant_id: variantIds[1],
|
||||
required_quantity: 1,
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/products/:id", () => {
|
||||
const toUpdateWithSalesChannels = "to-update-with-sales-channels"
|
||||
const toUpdateWithVariants = "to-update-with-variants"
|
||||
const toUpdate = "to-update"
|
||||
|
||||
beforeEach(async () => {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(medusaContainer)
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "Default channel",
|
||||
id: "default-channel",
|
||||
is_default: true,
|
||||
})
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "Channel 3",
|
||||
id: "channel-3",
|
||||
is_default: true,
|
||||
})
|
||||
|
||||
await simpleProductFactory(dbConnection, {
|
||||
title: "To update product",
|
||||
id: toUpdate,
|
||||
})
|
||||
|
||||
await simpleProductFactory(dbConnection, {
|
||||
title: "To update product with channels",
|
||||
id: toUpdateWithSalesChannels,
|
||||
sales_channels: [
|
||||
{ name: "channel 1", id: "channel-1" },
|
||||
{ name: "channel 2", id: "channel-2" },
|
||||
],
|
||||
})
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "To be added",
|
||||
id: "to-be-added",
|
||||
})
|
||||
|
||||
await simpleProductFactory(dbConnection, {
|
||||
title: "To update product with variants",
|
||||
id: toUpdateWithVariants,
|
||||
variants: [
|
||||
{
|
||||
id: "variant-1",
|
||||
title: "Variant 1",
|
||||
},
|
||||
{
|
||||
id: "variant-2",
|
||||
title: "Variant 2",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should do a basic product update", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post(`/admin/products/${toUpdate}`, payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: toUpdate,
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update product and also update a variant and create a variant", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
variants: [
|
||||
{
|
||||
id: "variant-1",
|
||||
title: "Variant 1 updated",
|
||||
},
|
||||
{
|
||||
title: "Variant 3",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post(`/admin/products/${toUpdateWithVariants}`, payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: toUpdateWithVariants,
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "variant-1",
|
||||
title: "Variant 1 updated",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "Variant 3",
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update product's sales channels", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
sales_channels: [{ id: "channel-2" }, { id: "channel-3" }],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
`/admin/products/${toUpdateWithSalesChannels}?expand=sales_channels`,
|
||||
payload,
|
||||
adminHeaders
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: toUpdateWithSalesChannels,
|
||||
sales_channels: [
|
||||
expect.objectContaining({ id: "channel-2" }),
|
||||
expect.objectContaining({ id: "channel-3" }),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update inventory when variants are updated", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const variantInventoryService = medusaContainer.resolve(
|
||||
"productVariantInventoryService"
|
||||
)
|
||||
|
||||
const payload = {
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
variants: [
|
||||
{
|
||||
id: "variant-1",
|
||||
title: "Variant 1 updated",
|
||||
},
|
||||
{
|
||||
title: "Variant 3",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post(`/admin/products/${toUpdateWithVariants}`, payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
let inventory = await variantInventoryService.listInventoryItemsByVariant(
|
||||
"variant-2"
|
||||
)
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: toUpdateWithVariants,
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "variant-1",
|
||||
title: "Variant 1 updated",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "Variant 3",
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
expect(inventory).toEqual([]) // no inventory items for removed variant
|
||||
|
||||
inventory = await variantInventoryService.listInventoryItemsByVariant(
|
||||
response?.data.product.variants.find((v) => v.title === "Variant 3").id
|
||||
)
|
||||
|
||||
expect(inventory).toEqual([
|
||||
expect.objectContaining({ id: expect.any(String) }),
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,17 +1,16 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
import {initDb, useDb} from "../../../../environment-helpers/use-db"
|
||||
import {simpleProductFactory, simpleRegionFactory,} from "../../../../factories"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import {AxiosInstance} from "axios"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import {
|
||||
createDefaultRuleTypes
|
||||
} from "../../../helpers/create-default-rule-types"
|
||||
import {createVariantPriceSet} from "../../../helpers/create-variant-price-set"
|
||||
import {getContainer} from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import {startBootstrapApp} from "../../../../environment-helpers/bootstrap-app"
|
||||
import {useApi} from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
@@ -25,6 +24,10 @@ const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
// TODO SEE to use new test runner medusaIntegrationTestRunner({
|
||||
// env,
|
||||
// testSuite: ({ dbConnection, getContainer, api }) => {})
|
||||
|
||||
describe.skip("POST /admin/products/:id/variants/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
|
||||
@@ -23,6 +23,10 @@ const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
// TODO SEE to use new test runner medusaIntegrationTestRunner({
|
||||
// env,
|
||||
// testSuite: ({ dbConnection, getContainer, api }) => {})
|
||||
|
||||
describe.skip("POST /admin/products/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
|
||||
Reference in New Issue
Block a user