Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 19 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e64d884
initial commit
carlos-r-l-rodrigues Jan 25, 2023
e9e4b81
getconfig dir
carlos-r-l-rodrigues Jan 25, 2023
20c7e8f
template db migrations dir
carlos-r-l-rodrigues Jan 25, 2023
bf1d794
Merge branch 'develop' into feat/run-module-migrations
carlos-r-l-rodrigues Jan 26, 2023
3fd0b3c
Create sweet-windows-float.md
olivermrbl Jan 26, 2023
83761fc
migrate update
carlos-r-l-rodrigues Jan 26, 2023
34a16df
Merge branch 'feat/run-module-migrations' of github.com:medusajs/medu…
carlos-r-l-rodrigues Jan 26, 2023
94acda9
naming
carlos-r-l-rodrigues Jan 26, 2023
e1b1771
add module entities to use-db
carlos-r-l-rodrigues Jan 27, 2023
8a77257
tests and bug fixes
carlos-r-l-rodrigues Jan 31, 2023
a20744a
snapshot
carlos-r-l-rodrigues Jan 31, 2023
c3c77cb
parseFloat
carlos-r-l-rodrigues Jan 31, 2023
c1f6529
Merge branch 'develop' into chore/integration-tests-stock-inventory
carlos-r-l-rodrigues Feb 1, 2023
705def0
Merge branch 'develop' into chore/integration-tests-stock-inventory
carlos-r-l-rodrigues Feb 1, 2023
196108b
Merge branch 'develop' into chore/integration-tests-stock-inventory
carlos-r-l-rodrigues Feb 2, 2023
2c6c327
fix transaction step return
carlos-r-l-rodrigues Feb 2, 2023
ac5a29d
sales channel location fix and cart + inventory tests
carlos-r-l-rodrigues Feb 3, 2023
86d02b3
Merge branch 'develop' into chore/integration-tests-stock-inventory
carlos-r-l-rodrigues Feb 3, 2023
eb87b05
Merge branch 'develop' into chore/integration-tests-stock-inventory
carlos-r-l-rodrigues Feb 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
270 changes: 270 additions & 0 deletions integration-tests/plugins/__tests__/inventory/cart/cart.js
Original file line number Diff line number Diff line change
@@ -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)
})
})
})
Loading