const path = require("path") const { LineItemAdjustment } = require("@medusajs/medusa") const setupServer = require("../../../environment-helpers/setup-server") const { useApi } = require("../../../environment-helpers/use-api") const { initDb, useDb } = require("../../../environment-helpers/use-db") const cartSeeder = require("../../../helpers/cart-seeder") const { simpleCartFactory, simpleLineItemFactory, } = require("../../../factories") const { simpleDiscountFactory, } = require("../../../factories/simple-discount-factory") jest.setTimeout(30000) describe("Line Item Adjustments", () => { let dbConnection let medusaProcess const doAfterEach = async () => { const db = useDb() return await db.teardown() } beforeAll(async () => { const cwd = path.resolve(path.join(__dirname, "..", "..")) dbConnection = await initDb({ cwd }) medusaProcess = await setupServer({ cwd }) }) afterAll(async () => { const db = useDb() await db.shutdown() medusaProcess.kill() }) describe("Tests database constraints", () => { let cart let discount const lineItemId = "line-test" beforeEach(async () => { await cartSeeder(dbConnection) discount = await simpleDiscountFactory(dbConnection, { code: "MEDUSATEST", id: "discount-test", rule: { value: 100, type: "fixed", allocation: "total", }, regions: ["test-region"], }) cart = await simpleCartFactory( dbConnection, { customer: "test-customer", id: "cart-test", line_items: [ { id: lineItemId, variant_id: "test-variant", cart_id: "cart-test", unit_price: 1000, quantity: 1, adjustments: [ { amount: 10, discount_id: discount.id, description: "discount", item_id: lineItemId, }, ], }, ], region: "test-region", shipping_address: { address_1: "test", country_code: "us", first_name: "chris", last_name: "rock", postal_code: "101", }, shipping_methods: [ { shipping_option: "test-option", }, ], }, 100 ) }) afterEach(async () => { await doAfterEach() }) describe("Given an existing line item, a discount, and a line item adjustment for both", () => { describe("When creating an adjustment for another line item w. same discount", () => { test("Then should create an adjustment", async () => { const createLineItemWithAdjustment = async () => { return await simpleLineItemFactory(dbConnection, { id: "line-test-2", variant_id: "test-variant-quantity", cart_id: "test-cart", unit_price: 1000, quantity: 1, adjustments: [ { amount: 10, discount_id: discount.id, description: "discount", item_id: "line-test-2", }, ], }) } await expect(createLineItemWithAdjustment()).resolves.toEqual( expect.anything() ) }) }) describe("When creating an adjustment for another line item w. null discount", () => { test("Then should create an adjustment", async () => { const createAdjustmentNullDiscount = async () => { return await dbConnection.manager.insert(LineItemAdjustment, { id: "lia-1", item_id: lineItemId, amount: 35, description: "custom discount", discount_id: null, }) } await expect(createAdjustmentNullDiscount()).resolves.toEqual( expect.anything() ) }) }) describe("When creating multiple adjustments w. a null discount_id", () => { test("Then should create multiple adjustments", async () => { const createAdjustmentsNullDiscount = async () => { await dbConnection.manager.insert(LineItemAdjustment, { id: "lia-1", item_id: lineItemId, amount: 35, description: "custom discount", discount_id: null, }) return await dbConnection.manager.insert(LineItemAdjustment, { id: "lia-2", item_id: lineItemId, amount: 100, description: "custom discount", discount_id: null, }) } await expect(createAdjustmentsNullDiscount()).resolves.toEqual( expect.anything() ) }) }) describe("When creating an adjustment w. for same line item and different discount", () => { test("Then should create an adjustment", async () => { const createAdjustment = async () => { await simpleDiscountFactory(dbConnection, { code: "ANOTHER", id: "discount-2", rule: { value: 10, type: "percentage", allocation: "item", }, regions: ["test-region"], }) return await dbConnection.manager.insert(LineItemAdjustment, { id: "lia-1", item_id: lineItemId, amount: 10, description: "discount", discount_id: "discount-2", }) } await expect(createAdjustment()).resolves.toEqual(expect.anything()) }) }) describe("When creating an adjustment w. existing line item and discount pair", () => { test("Then should throw a duplicate error", async () => { const createDuplicateAdjustment = async () => await dbConnection.manager.insert(LineItemAdjustment, { id: "lia-1", item_id: lineItemId, amount: 20, description: "discount", discount_id: discount.id, }) await expect(createDuplicateAdjustment()).rejects.toEqual( expect.objectContaining({ code: "23505" }) ) }) }) }) }) describe("When refreshing adjustments make sure that only adjustments associated with a Medusa Discount are deleted", () => { let cart let discount const lineItemId = "line-test" beforeEach(async () => { await cartSeeder(dbConnection) discount = await simpleDiscountFactory(dbConnection, { code: "MEDUSATEST", id: "discount-test", rule: { value: 100, type: "fixed", allocation: "total", }, regions: ["test-region"], }) cart = await simpleCartFactory( dbConnection, { customer: "test-customer", id: "cart-test", line_items: [ { id: lineItemId, variant_id: "test-variant", cart_id: "cart-test", unit_price: 1000, quantity: 1, adjustments: [ { amount: 10, discount_id: discount.id, description: "discount", item_id: lineItemId, }, { // this one shouldn't be deleted because it's // not associated with a Medusa Discount, i.e. // it's created by a third party system, for example, // a custom promotions engine amount: 20, description: "custom adjustment without discount", item_id: lineItemId, }, ], }, ], region: "test-region", }, 100 ) }) afterEach(async () => { await doAfterEach() }) it("Delete only adjustments of the removed discount and keep 'custom' adjustments", async () => { const api = useApi() const response = await api.delete( `/store/carts/${cart.id}/discounts/${discount.code}` ) expect(response.status).toEqual(200) expect(response.data.cart.items[0].adjustments.length).toEqual(1) expect(response.data.cart.items[0].adjustments[0]).toMatchObject({ amount: 20, description: "custom adjustment without discount", item_id: lineItemId, }) }) }) })