feat(medusa,stock-location,inventory): Integration tests (#3149)

This commit is contained in:
Carlos R. L. Rodrigues
2023-02-06 09:02:43 -03:00
committed by GitHub
parent 71fdd28198
commit 923ccece24
17 changed files with 2019 additions and 32 deletions
@@ -0,0 +1,270 @@
const path = require("path")
const { bootstrapApp } = require("../../../../helpers/bootstrap-app")
const { initDb, useDb } = require("../../../../helpers/use-db")
const { setPort, useApi } = require("../../../../helpers/use-api")
const adminSeeder = require("../../../helpers/admin-seeder")
const cartSeeder = require("../../../helpers/cart-seeder")
const { simpleProductFactory } = require("../../../../api/factories")
const { simpleSalesChannelFactory } = require("../../../../api/factories")
jest.setTimeout(30000)
const adminHeaders = { headers: { Authorization: "Bearer test_token" } }
describe("/store/carts", () => {
let express
let appContainer
let dbConnection
let variantId
let inventoryItemId
let locationId
const doAfterEach = async () => {
const db = useDb()
return await db.teardown()
}
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
dbConnection = await initDb({ cwd })
const { container, app, port } = await bootstrapApp({ cwd })
appContainer = container
setPort(port)
express = app.listen(port, (err) => {
process.send(port)
})
})
afterAll(async () => {
const db = useDb()
await db.shutdown()
express.close()
})
afterEach(async () => {
jest.clearAllMocks()
const db = useDb()
return await db.teardown()
})
describe("POST /store/carts/:id", () => {
beforeEach(async () => {
await simpleSalesChannelFactory(dbConnection, {
id: "test-channel",
is_default: true,
})
await adminSeeder(dbConnection)
await cartSeeder(dbConnection, { sales_channel_id: "test-channel" })
await simpleProductFactory(
dbConnection,
{
id: "product1",
sales_channels: [{ id: "test-channel" }],
variants: [],
},
100
)
const api = useApi()
// Add payment provider
await api.post(
`/admin/regions/test-region/payment-providers`,
{
provider_id: "test-pay",
},
adminHeaders
)
const prodVarInventoryService = appContainer.resolve(
"productVariantInventoryService"
)
const response = await api.post(
`/admin/products/product1/variants`,
{
title: "Test Variant w. inventory",
sku: "MY_SKU",
material: "material",
origin_country: "UK",
hs_code: "hs001",
mid_code: "mids",
weight: 300,
length: 100,
height: 200,
width: 150,
options: [
{
option_id: "product1-option",
value: "SS",
},
],
manage_inventory: true,
prices: [{ currency_code: "usd", amount: 2300 }],
},
adminHeaders
)
const variant = response.data.product.variants[0]
variantId = variant.id
const inventoryItems =
await prodVarInventoryService.listInventoryItemsByVariant(variantId)
inventoryItemId = inventoryItems[0].id
// Add Stock location
const stockRes = await api.post(
`/admin/stock-locations`,
{
name: "Fake Warehouse",
},
adminHeaders
)
locationId = stockRes.data.stock_location.id
// Add stock level
await api.post(
`/admin/inventory-items/${inventoryItemId}/location-levels`,
{
location_id: locationId,
stocked_quantity: 5,
},
adminHeaders
)
// Associate Stock Location with sales channel
await api.post(
`/admin/sales-channels/test-channel/stock-locations`,
{
location_id: locationId,
},
adminHeaders
)
})
afterEach(async () => {
await doAfterEach()
})
it("reserve quantity when completing the cart", async () => {
const api = useApi()
const cartId = "test-cart"
// Add standard line item to cart
await api.post(
`/store/carts/${cartId}/line-items`,
{
variant_id: variantId,
quantity: 3,
},
{ withCredentials: true }
)
await api.post(`/store/carts/${cartId}/payment-sessions`)
await api.post(`/store/carts/${cartId}/payment-session`, {
provider_id: "test-pay",
})
const getRes = await api.post(`/store/carts/${cartId}/complete`)
expect(getRes.status).toEqual(200)
expect(getRes.data.type).toEqual("order")
const inventoryService = appContainer.resolve("inventoryService")
const stockLevel = await inventoryService.retrieveInventoryLevel(
inventoryItemId,
locationId
)
expect(stockLevel.location_id).toEqual(locationId)
expect(stockLevel.inventory_item_id).toEqual(inventoryItemId)
expect(stockLevel.reserved_quantity).toEqual(3)
expect(stockLevel.stocked_quantity).toEqual(5)
})
it("fails to add a item on the cart if the inventory isn't enough", async () => {
const api = useApi()
const cartId = "test-cart"
// Add standard line item to cart
const addCart = await api
.post(
`/store/carts/${cartId}/line-items`,
{
variant_id: variantId,
quantity: 6,
},
{ withCredentials: true }
)
.catch((e) => e)
expect(addCart.response.status).toEqual(400)
expect(addCart.response.data.code).toEqual("insufficient_inventory")
expect(addCart.response.data.message).toEqual(
`Variant with id: ${variantId} does not have the required inventory`
)
})
it("fails to complete cart with items inventory not covered", async () => {
const api = useApi()
const cartId = "test-cart"
// Add standard line item to cart
await api.post(
`/store/carts/${cartId}/line-items`,
{
variant_id: variantId,
quantity: 5,
},
{ withCredentials: true }
)
await api.post(`/store/carts/${cartId}/payment-sessions`)
await api.post(`/store/carts/${cartId}/payment-session`, {
provider_id: "test-pay",
})
// Another proccess reserves items before the cart is completed
const inventoryService = appContainer.resolve("inventoryService")
inventoryService.createReservationItem({
line_item_id: "line_item_123",
inventory_item_id: inventoryItemId,
location_id: locationId,
quantity: 2,
})
const completeCartRes = await api
.post(`/store/carts/${cartId}/complete`)
.catch((e) => e)
expect(completeCartRes.response.status).toEqual(409)
expect(completeCartRes.response.data.code).toEqual(
"insufficient_inventory"
)
expect(completeCartRes.response.data.message).toEqual(
`Variant with id: ${variantId} does not have the required inventory`
)
const stockLevel = await inventoryService.retrieveInventoryLevel(
inventoryItemId,
locationId
)
expect(stockLevel.location_id).toEqual(locationId)
expect(stockLevel.inventory_item_id).toEqual(inventoryItemId)
expect(stockLevel.reserved_quantity).toEqual(2)
expect(stockLevel.stocked_quantity).toEqual(5)
})
})
})