feat: Add basic support for importing products (#8266)

This commit is contained in:
Stevche Radevski
2024-07-25 11:07:24 +02:00
committed by GitHub
parent a26b7cf253
commit 444a244eab
10 changed files with 520 additions and 115 deletions
@@ -234,118 +234,6 @@ medusaIntegrationTestRunner({
recursive: true,
})
})
// it("should be able to import an exported csv file", async () => {
// const api = useApi()
// const batchPayload = {
// type: "product-export",
// context: {
// batch_size: 1,
// filterable_fields: { collection_id: "test-collection" },
// order: "created_at",
// },
// }
// const batchJobRes = await api.post(
// "/admin/batch-jobs",
// batchPayload,
// adminReqConfig
// )
// let batchJobId = batchJobRes.data.batch_job.id
// expect(batchJobId).toBeTruthy()
// // Pull to check the status until it is completed
// let batchJob
// let shouldContinuePulling = true
// while (shouldContinuePulling) {
// const res = await api.get(
// `/admin/batch-jobs/${batchJobId}`,
// adminReqConfig
// )
// await new Promise((resolve, _) => {
// setTimeout(resolve, 1000)
// })
// batchJob = res.data.batch_job
// shouldContinuePulling = !(
// batchJob.status === "completed" || batchJob.status === "failed"
// )
// }
// expect(batchJob.status).toBe("completed")
// exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
// const isFileExists = (await fs.stat(exportFilePath)).isFile()
// expect(isFileExists).toBeTruthy()
// const data = (await fs.readFile(exportFilePath)).toString()
// const [header, ...lines] = data.split("\r\n").filter((l) => l)
// expect(lines.length).toBe(4)
// const csvLine = lines[0].split(";")
// expect(csvLine[0]).toBe("test-product")
// expect(csvLine[2]).toBe("Test product")
// csvLine[2] = "Updated test product"
// lines.splice(0, 1, csvLine.join(";"))
// await fs.writeFile(exportFilePath, [header, ...lines].join("\r\n"))
// const importBatchJobRes = await api.post(
// "/admin/batch-jobs",
// {
// type: "product-import",
// context: {
// fileKey: exportFilePath,
// },
// },
// adminReqConfig
// )
// batchJobId = importBatchJobRes.data.batch_job.id
// expect(batchJobId).toBeTruthy()
// shouldContinuePulling = true
// while (shouldContinuePulling) {
// const res = await api.get(
// `/admin/batch-jobs/${batchJobId}`,
// adminReqConfig
// )
// await new Promise((resolve, _) => {
// setTimeout(resolve, 1000)
// })
// batchJob = res.data.batch_job
// shouldContinuePulling = !(
// batchJob.status === "completed" || batchJob.status === "failed"
// )
// }
// expect(batchJob.status).toBe("completed")
// const productsResponse = await api.get(
// "/admin/products",
// adminReqConfig
// )
// expect(productsResponse.data.count).toBe(5)
// expect(productsResponse.data.products).toEqual(
// expect.arrayContaining([
// expect.objectContaining({
// id: csvLine[0],
// handle: csvLine[1],
// title: csvLine[2],
// }),
// ])
// )
// })
})
},
})
@@ -60,7 +60,6 @@ medusaIntegrationTestRunner({
"/admin/products",
getProductFixture({
title: "Base product",
type_id: baseType.id,
}),
adminHeaders
)
@@ -72,7 +71,7 @@ medusaIntegrationTestRunner({
})
describe("POST /admin/products/export", () => {
it("should import a products CSV file", async () => {
it("should import a previously exported products CSV file", async () => {
const subscriberExecution = TestEventUtils.waitSubscribersExecution(
"notification.notification.created",
eventBus
@@ -83,6 +82,17 @@ medusaIntegrationTestRunner({
{ encoding: "utf-8" }
)
fileContent = fileContent.replace(
/prod_01J3CRPNVGRZ01A8GH8FQYK10Z/g,
baseProduct.id
)
fileContent = fileContent.replace(
/variant_01J3CRPNW5J6EBVVQP1TN33A58/g,
baseProduct.variants[0].id
)
fileContent = fileContent.replace(/pcol_\w*\d*/g, baseCollection.id)
fileContent = fileContent.replace(/ptyp_\w*\d*/g, baseType.id)
const { form, meta } = getUploadReq({
name: "test.csv",
content: fileContent,
@@ -108,7 +118,189 @@ medusaIntegrationTestRunner({
}),
})
)
const dbProducts = (await api.get("/admin/products", adminHeaders)).data
.products
expect(dbProducts).toHaveLength(2)
expect(dbProducts).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: baseProduct.id,
handle: "base-product",
is_giftcard: false,
thumbnail: "test-image.png",
status: "draft",
description: "test-product-description\ntest line 2",
options: [
expect.objectContaining({
title: "size",
values: expect.arrayContaining([
expect.objectContaining({
value: "small",
}),
expect.objectContaining({
value: "large",
}),
]),
}),
expect.objectContaining({
title: "color",
values: expect.arrayContaining([
expect.objectContaining({
value: "green",
}),
]),
}),
],
images: expect.arrayContaining([
expect.objectContaining({
url: "test-image.png",
}),
expect.objectContaining({
url: "test-image-2.png",
}),
]),
tags: [
expect.objectContaining({
value: "123",
}),
expect.objectContaining({
value: "456",
}),
],
type: expect.objectContaining({
id: baseType.id,
}),
collection: expect.objectContaining({
id: baseCollection.id,
}),
variants: [
expect.objectContaining({
title: "Test variant",
allow_backorder: false,
manage_inventory: true,
prices: [
expect.objectContaining({
currency_code: "usd",
amount: 100,
}),
expect.objectContaining({
currency_code: "eur",
amount: 45,
}),
expect.objectContaining({
currency_code: "dkk",
amount: 30,
}),
],
options: [
expect.objectContaining({
value: "large",
}),
expect.objectContaining({
value: "green",
}),
],
}),
expect.objectContaining({
title: "Test variant 2",
allow_backorder: false,
manage_inventory: true,
// TODO: Since we are doing a product update, there won't be any prices created for the variant
options: [
expect.objectContaining({
value: "small",
}),
expect.objectContaining({
value: "green",
}),
],
}),
],
created_at: expect.any(String),
updated_at: expect.any(String),
}),
expect.objectContaining({
id: expect.any(String),
handle: "proposed-product",
is_giftcard: false,
thumbnail: "test-image.png",
status: "proposed",
description: "test-product-description",
options: [
expect.objectContaining({
title: "size",
values: expect.arrayContaining([
expect.objectContaining({
value: "large",
}),
]),
}),
expect.objectContaining({
title: "color",
values: expect.arrayContaining([
expect.objectContaining({
value: "green",
}),
]),
}),
],
images: expect.arrayContaining([
expect.objectContaining({
url: "test-image.png",
}),
expect.objectContaining({
url: "test-image-2.png",
}),
]),
tags: [
expect.objectContaining({
value: "new-tag",
}),
],
type: expect.objectContaining({
id: baseType.id,
}),
collection: null,
variants: [
expect.objectContaining({
title: "Test variant",
allow_backorder: false,
manage_inventory: true,
prices: [
expect.objectContaining({
currency_code: "usd",
amount: 100,
}),
expect.objectContaining({
currency_code: "eur",
amount: 45,
}),
expect.objectContaining({
currency_code: "dkk",
amount: 30,
}),
],
options: [
expect.objectContaining({
value: "large",
}),
expect.objectContaining({
value: "green",
}),
],
}),
],
created_at: expect.any(String),
updated_at: expect.any(String),
}),
])
)
})
it("should fail on invalid prices being present in the CSV", async () => {})
it("should fail on non-existent fields being present in the CSV", async () => {})
})
},
})