Closes #13163 I have a few questions about expected behaviour, since this currently breaks some tests: - Many tests use the productModule to create products, with default status == "draft", and use the addToCart workflow which now throws. Should I change all breaking tests to specify status == "published" whne creating the product? The alternative would be to check the status in the store API route before the workflow but 1. it would be an extra query and 2. the addToCart workflow is only used in the store currently, and even if it was to be used admin-side, it still doesn't make sense to add a draft product to cart - After this PR an unpublished product would give the same error as a variant that doesn't exist. While imho this is correct, the thrown error (for both) is "Items do not have a price" which doesn't make much sense(i believe the workflows goes through with an empty variants list and then errors at the price check point). Should I throw a different error when a variant doesn't exists/isn't published? --- > [!NOTE] > Enforces that only variants from published products can be added to carts, adds status fetching, refines errors, and updates tests to use ProductStatus.PUBLISHED. > > - **Core Flows**: > - addToCart: Validate variants exist and belong to `product.status = PUBLISHED`; throw clear `INVALID_DATA` when not found/unpublished. > - Data fetching: Include `product.status` in `cart` and `order` variant field selections. > - **Tests/Fixtures**: > - Update integration tests to set `status: ProductStatus.PUBLISHED` when creating products and import `ProductStatus` where needed. > - Add cases for unpublished products and non-existent variants producing the new error message. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit ca72532e957964d2d8e6bcecbb0905054c677ded. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup>
919 lines
24 KiB
TypeScript
919 lines
24 KiB
TypeScript
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
|
import {
|
|
ContainerRegistrationKeys,
|
|
Modules,
|
|
ProductStatus,
|
|
RuleOperator,
|
|
} from "@medusajs/utils"
|
|
import {
|
|
adminHeaders,
|
|
createAdminUser,
|
|
} from "../../../helpers/create-admin-user"
|
|
import { setupTaxStructure } from "../../../modules/__tests__/fixtures/tax"
|
|
|
|
jest.setTimeout(300000)
|
|
|
|
medusaIntegrationTestRunner({
|
|
testSuite: ({ dbConnection, getContainer, api }) => {
|
|
let order, order2
|
|
let returnShippingOption
|
|
let outboundShippingOption
|
|
let shippingProfile
|
|
let fulfillmentSet
|
|
let returnReason
|
|
let inventoryItem
|
|
let inventoryItemExtra
|
|
let inventoryItemExtra2
|
|
let location
|
|
let productExtra
|
|
let productExtra2
|
|
const shippingProviderId = "manual_test-provider"
|
|
|
|
beforeEach(async () => {
|
|
const container = getContainer()
|
|
await createAdminUser(dbConnection, adminHeaders, container)
|
|
|
|
const region = (
|
|
await api.post(
|
|
"/admin/regions",
|
|
{
|
|
name: "test-region",
|
|
currency_code: "usd",
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.region
|
|
|
|
shippingProfile = (
|
|
await api.post(
|
|
`/admin/shipping-profiles`,
|
|
{
|
|
name: "Test",
|
|
type: "default",
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.shipping_profile
|
|
|
|
const customer = (
|
|
await api.post(
|
|
"/admin/customers",
|
|
{
|
|
first_name: "joe",
|
|
email: "joe@admin.com",
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.customer
|
|
|
|
const salesChannel = (
|
|
await api.post(
|
|
"/admin/sales-channels",
|
|
{
|
|
name: "Test channel",
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.sales_channel
|
|
|
|
const product = (
|
|
await api.post(
|
|
"/admin/products",
|
|
{
|
|
title: "Test product",
|
|
status: ProductStatus.PUBLISHED,
|
|
shipping_profile_id: shippingProfile.id,
|
|
options: [{ title: "size", values: ["large", "small"] }],
|
|
variants: [
|
|
{
|
|
title: "Test variant",
|
|
sku: "test-variant",
|
|
options: { size: "large" },
|
|
prices: [
|
|
{
|
|
currency_code: "usd",
|
|
amount: 10,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.product
|
|
|
|
productExtra = (
|
|
await api.post(
|
|
"/admin/products",
|
|
{
|
|
title: "Extra product",
|
|
status: ProductStatus.PUBLISHED,
|
|
shipping_profile_id: shippingProfile.id,
|
|
options: [{ title: "size", values: ["large", "small"] }],
|
|
variants: [
|
|
{
|
|
title: "my variant",
|
|
sku: "variant-sku",
|
|
options: { size: "large" },
|
|
prices: [
|
|
{
|
|
currency_code: "usd",
|
|
amount: 123456.1234657890123456789,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.product
|
|
|
|
productExtra2 = (
|
|
await api.post(
|
|
"/admin/products",
|
|
{
|
|
title: "Extra product 2, same price",
|
|
status: ProductStatus.PUBLISHED,
|
|
shipping_profile_id: shippingProfile.id,
|
|
options: [{ title: "size", values: ["large", "small"] }],
|
|
variants: [
|
|
{
|
|
title: "my variant 2",
|
|
sku: "variant-sku-2",
|
|
options: { size: "large" },
|
|
prices: [
|
|
{
|
|
currency_code: "usd",
|
|
amount: 25,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.product
|
|
|
|
returnReason = (
|
|
await api.post(
|
|
"/admin/return-reasons",
|
|
{
|
|
value: "return-reason-test",
|
|
label: "Test return reason",
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.return_reason
|
|
|
|
const orderModule = container.resolve(Modules.ORDER)
|
|
|
|
order = await orderModule.createOrders({
|
|
region_id: region.id,
|
|
email: "foo@bar.com",
|
|
items: [
|
|
{
|
|
title: "Custom Item 2",
|
|
variant_id: product.variants[0].id,
|
|
quantity: 2,
|
|
unit_price: 25,
|
|
},
|
|
],
|
|
sales_channel_id: salesChannel.id,
|
|
shipping_address: {
|
|
first_name: "Test",
|
|
last_name: "Test",
|
|
address_1: "Test",
|
|
city: "Test",
|
|
country_code: "US",
|
|
postal_code: "12345",
|
|
phone: "12345",
|
|
},
|
|
billing_address: {
|
|
first_name: "Test",
|
|
last_name: "Test",
|
|
address_1: "Test",
|
|
city: "Test",
|
|
country_code: "US",
|
|
postal_code: "12345",
|
|
},
|
|
shipping_methods: [
|
|
{
|
|
name: "Test shipping method",
|
|
amount: 10,
|
|
data: {},
|
|
tax_lines: [
|
|
{
|
|
description: "shipping Tax 1",
|
|
tax_rate_id: "tax_usa_shipping",
|
|
code: "code",
|
|
rate: 10,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
currency_code: "usd",
|
|
customer_id: customer.id,
|
|
})
|
|
|
|
order2 = await orderModule.createOrders({
|
|
region_id: region.id,
|
|
email: "foo@bar2.com",
|
|
items: [
|
|
{
|
|
title: "Custom Iasdasd2",
|
|
quantity: 1,
|
|
unit_price: 20,
|
|
},
|
|
],
|
|
sales_channel_id: salesChannel.id,
|
|
shipping_address: {
|
|
first_name: "Test",
|
|
last_name: "Test",
|
|
address_1: "Test",
|
|
city: "Test",
|
|
country_code: "US",
|
|
postal_code: "12345",
|
|
phone: "12345",
|
|
},
|
|
billing_address: {
|
|
first_name: "Test",
|
|
last_name: "Test",
|
|
address_1: "Test",
|
|
city: "Test",
|
|
country_code: "US",
|
|
postal_code: "12345",
|
|
},
|
|
currency_code: "usd",
|
|
customer_id: customer.id,
|
|
})
|
|
|
|
location = (
|
|
await api.post(
|
|
`/admin/stock-locations`,
|
|
{
|
|
name: "Test location",
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.stock_location
|
|
|
|
location = (
|
|
await api.post(
|
|
`/admin/stock-locations/${location.id}/fulfillment-sets?fields=*fulfillment_sets`,
|
|
{
|
|
name: "Test",
|
|
type: "test-type",
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.stock_location
|
|
|
|
fulfillmentSet = (
|
|
await api.post(
|
|
`/admin/fulfillment-sets/${location.fulfillment_sets[0].id}/service-zones`,
|
|
{
|
|
name: "Test",
|
|
geo_zones: [{ type: "country", country_code: "us" }],
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.fulfillment_set
|
|
|
|
inventoryItem = (
|
|
await api.post(
|
|
`/admin/inventory-items`,
|
|
{ sku: "inv-1234" },
|
|
adminHeaders
|
|
)
|
|
).data.inventory_item
|
|
|
|
await api.post(
|
|
`/admin/inventory-items/${inventoryItem.id}/location-levels`,
|
|
{
|
|
location_id: location.id,
|
|
stocked_quantity: 2,
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
inventoryItemExtra = (
|
|
await api.get(`/admin/inventory-items?sku=variant-sku`, adminHeaders)
|
|
).data.inventory_items[0]
|
|
|
|
inventoryItemExtra2 = (
|
|
await api.get(`/admin/inventory-items?sku=variant-sku-2`, adminHeaders)
|
|
).data.inventory_items[0]
|
|
|
|
await api.post(
|
|
`/admin/inventory-items/${inventoryItemExtra.id}/location-levels`,
|
|
{
|
|
location_id: location.id,
|
|
stocked_quantity: 4,
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/inventory-items/${inventoryItemExtra2.id}/location-levels`,
|
|
{
|
|
location_id: location.id,
|
|
stocked_quantity: 2,
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
const remoteLink = container.resolve(
|
|
ContainerRegistrationKeys.REMOTE_LINK
|
|
)
|
|
|
|
await remoteLink.create([
|
|
{
|
|
[Modules.STOCK_LOCATION]: {
|
|
stock_location_id: location.id,
|
|
},
|
|
[Modules.FULFILLMENT]: {
|
|
fulfillment_provider_id: shippingProviderId,
|
|
},
|
|
},
|
|
{
|
|
[Modules.STOCK_LOCATION]: {
|
|
stock_location_id: location.id,
|
|
},
|
|
[Modules.FULFILLMENT]: {
|
|
fulfillment_set_id: fulfillmentSet.id,
|
|
},
|
|
},
|
|
{
|
|
[Modules.SALES_CHANNEL]: {
|
|
sales_channel_id: salesChannel.id,
|
|
},
|
|
[Modules.STOCK_LOCATION]: {
|
|
stock_location_id: location.id,
|
|
},
|
|
},
|
|
{
|
|
[Modules.PRODUCT]: {
|
|
variant_id: product.variants[0].id,
|
|
},
|
|
[Modules.INVENTORY]: {
|
|
inventory_item_id: inventoryItem.id,
|
|
},
|
|
},
|
|
{
|
|
[Modules.PRODUCT]: {
|
|
variant_id: productExtra.variants[0].id,
|
|
},
|
|
[Modules.INVENTORY]: {
|
|
inventory_item_id: inventoryItemExtra.id,
|
|
},
|
|
},
|
|
{
|
|
[Modules.PRODUCT]: {
|
|
variant_id: productExtra2.variants[0].id,
|
|
},
|
|
[Modules.INVENTORY]: {
|
|
inventory_item_id: inventoryItemExtra2.id,
|
|
},
|
|
},
|
|
])
|
|
|
|
// create reservation for inventory item that is initially on the order
|
|
const inventoryModule = container.resolve(Modules.INVENTORY)
|
|
await inventoryModule.createReservationItems([
|
|
{
|
|
inventory_item_id: inventoryItem.id,
|
|
location_id: location.id,
|
|
quantity: 2,
|
|
line_item_id: order.items[0].id,
|
|
},
|
|
])
|
|
|
|
const shippingOptionPayload = {
|
|
name: "Return shipping",
|
|
service_zone_id: fulfillmentSet.service_zones[0].id,
|
|
shipping_profile_id: shippingProfile.id,
|
|
provider_id: shippingProviderId,
|
|
price_type: "flat",
|
|
type: {
|
|
label: "Test type",
|
|
description: "Test description",
|
|
code: "test-code",
|
|
},
|
|
prices: [
|
|
{
|
|
currency_code: "usd",
|
|
amount: 1000,
|
|
},
|
|
],
|
|
rules: [
|
|
{
|
|
operator: RuleOperator.EQ,
|
|
attribute: "is_return",
|
|
value: "true",
|
|
},
|
|
],
|
|
}
|
|
|
|
const outboundShippingOptionPayload = {
|
|
name: "Oubound shipping",
|
|
service_zone_id: fulfillmentSet.service_zones[0].id,
|
|
shipping_profile_id: shippingProfile.id,
|
|
provider_id: shippingProviderId,
|
|
price_type: "flat",
|
|
type: {
|
|
label: "Test type",
|
|
description: "Test description",
|
|
code: "test-code",
|
|
},
|
|
prices: [
|
|
{
|
|
currency_code: "usd",
|
|
amount: 20,
|
|
},
|
|
],
|
|
rules: [
|
|
{
|
|
operator: RuleOperator.EQ,
|
|
attribute: "is_return",
|
|
value: "false",
|
|
},
|
|
{
|
|
operator: RuleOperator.EQ,
|
|
attribute: "enabled_in_store",
|
|
value: "true",
|
|
},
|
|
],
|
|
}
|
|
outboundShippingOption = (
|
|
await api.post(
|
|
"/admin/shipping-options",
|
|
outboundShippingOptionPayload,
|
|
adminHeaders
|
|
)
|
|
).data.shipping_option
|
|
|
|
returnShippingOption = (
|
|
await api.post(
|
|
"/admin/shipping-options",
|
|
shippingOptionPayload,
|
|
adminHeaders
|
|
)
|
|
).data.shipping_option
|
|
|
|
const item = order.items[0]
|
|
|
|
await api.post(
|
|
`/admin/orders/${order.id}/fulfillments`,
|
|
{
|
|
items: [
|
|
{
|
|
id: item.id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/orders/${order2.id}/fulfillments`,
|
|
{
|
|
items: [
|
|
{
|
|
id: order2.items[0].id,
|
|
quantity: 1,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await setupTaxStructure(container.resolve(Modules.TAX))
|
|
})
|
|
|
|
describe("Exchanges lifecycle", () => {
|
|
it("test full exchange flow", async () => {
|
|
const orderBefore = (
|
|
await api.get(`/admin/orders/${order.id}`, adminHeaders)
|
|
).data.order
|
|
|
|
let result = await api.post(
|
|
"/admin/exchanges",
|
|
{
|
|
order_id: order.id,
|
|
description: "Test",
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
expect(result.data.exchange.created_by).toEqual(expect.any(String))
|
|
|
|
const exchangeId = result.data.exchange.id
|
|
|
|
const item = order.items[0]
|
|
|
|
result = await api.post(
|
|
`/admin/exchanges/${exchangeId}/inbound/items`,
|
|
{
|
|
items: [
|
|
{
|
|
id: item.id,
|
|
reason_id: returnReason.id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
// New Item
|
|
result = await api.post(
|
|
`/admin/exchanges/${exchangeId}/outbound/items`,
|
|
{
|
|
items: [
|
|
{
|
|
variant_id: productExtra2.variants[0].id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
result = await api.post(
|
|
`/admin/exchanges/${exchangeId}/request`,
|
|
{},
|
|
adminHeaders
|
|
)
|
|
const returnId = result.data.exchange.return_id
|
|
|
|
result = (await api.get(`/admin/orders/${order.id}`, adminHeaders)).data
|
|
.order
|
|
|
|
expect(orderBefore.total).toBe(61)
|
|
expect(result.total).toBe(112)
|
|
|
|
// receive return
|
|
await api.post(`/admin/returns/${returnId}/receive`, {}, adminHeaders)
|
|
await api.post(
|
|
`/admin/returns/${returnId}/receive-items`,
|
|
{
|
|
items: [
|
|
{
|
|
id: item.id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/returns/${returnId}/receive/confirm`,
|
|
{},
|
|
adminHeaders
|
|
)
|
|
|
|
result = (await api.get(`/admin/orders/${order.id}`, adminHeaders)).data
|
|
.order
|
|
|
|
expect(orderBefore.total).toBe(61)
|
|
expect(result.total).toBe(62) // +1 is from taxes of the new item
|
|
})
|
|
|
|
it("Full flow with 2 orders", async () => {
|
|
let result = await api.post(
|
|
"/admin/exchanges",
|
|
{
|
|
order_id: order.id,
|
|
description: "Test",
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
expect(result.data.exchange.created_by).toEqual(expect.any(String))
|
|
|
|
const exchangeId = result.data.exchange.id
|
|
|
|
let r2 = await api.post(
|
|
"/admin/exchanges",
|
|
{
|
|
order_id: order2.id,
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
const exchangeId2 = r2.data.exchange.id
|
|
const item2 = order2.items[0]
|
|
|
|
result = await api.post(
|
|
`/admin/exchanges/${exchangeId2}/inbound/items`,
|
|
{
|
|
items: [
|
|
{
|
|
id: item2.id,
|
|
quantity: 1,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchangeId2}/inbound/shipping-method`,
|
|
{
|
|
shipping_option_id: returnShippingOption.id,
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
const { response } = await api
|
|
.post(`/admin/exchanges/${exchangeId2}/request`, {}, adminHeaders)
|
|
.catch((e) => e)
|
|
|
|
expect(response.data).toEqual({
|
|
type: "invalid_data",
|
|
message:
|
|
"Order exchange request should have at least 1 item inbound and 1 item outbound",
|
|
})
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchangeId2}/outbound/items`,
|
|
{
|
|
items: [
|
|
{
|
|
variant_id: productExtra.variants[0].id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchangeId2}/request`,
|
|
{},
|
|
adminHeaders
|
|
)
|
|
|
|
const item = order.items[0]
|
|
|
|
result = await api.post(
|
|
`/admin/exchanges/${exchangeId}/inbound/items`,
|
|
{
|
|
items: [
|
|
{
|
|
id: item.id,
|
|
reason_id: returnReason.id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchangeId}/inbound/shipping-method`,
|
|
{
|
|
shipping_option_id: returnShippingOption.id,
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
// updated the requested quantity
|
|
const updateReturnItemActionId =
|
|
result.data.order_preview.items[0].actions[0].id
|
|
|
|
result = await api.post(
|
|
`/admin/exchanges/${exchangeId}/inbound/items/${updateReturnItemActionId}`,
|
|
{
|
|
quantity: 1,
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
// New Items
|
|
result = await api.post(
|
|
`/admin/exchanges/${exchangeId}/outbound/items`,
|
|
{
|
|
items: [
|
|
{
|
|
variant_id: productExtra.variants[0].id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
result = await api.post(
|
|
`/admin/exchanges/${exchangeId}/request`,
|
|
{},
|
|
adminHeaders
|
|
)
|
|
|
|
result = (
|
|
await api.get(
|
|
`/admin/exchanges?fields=+metadata,*additional_items`,
|
|
adminHeaders
|
|
)
|
|
).data.exchanges
|
|
|
|
expect(result).toHaveLength(2)
|
|
expect(result[0].additional_items).toHaveLength(1)
|
|
expect(result[0].canceled_at).toBeNull()
|
|
|
|
const return_ = (
|
|
await api.get(
|
|
`/admin/returns/${result[0].return_id}?fields=*fulfillments`,
|
|
adminHeaders
|
|
)
|
|
).data.return
|
|
|
|
expect(return_.fulfillments).toHaveLength(1)
|
|
expect(return_.fulfillments[0].canceled_at).toBeNull()
|
|
|
|
// all exchange return fulfillments should be canceled before canceling the exchange
|
|
await api.post(
|
|
`/admin/fulfillments/${return_.fulfillments[0].id}/cancel`,
|
|
{},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchangeId}/cancel`,
|
|
{},
|
|
adminHeaders
|
|
)
|
|
|
|
result = (
|
|
await api.get(
|
|
`/admin/exchanges?fields=*additional_items`,
|
|
adminHeaders
|
|
)
|
|
).data.exchanges
|
|
expect(result[0].canceled_at).toBeDefined()
|
|
})
|
|
|
|
describe("with inbound and outbound items", () => {
|
|
let exchange
|
|
let orderPreview
|
|
|
|
beforeEach(async () => {
|
|
exchange = (
|
|
await api.post(
|
|
"/admin/exchanges",
|
|
{
|
|
order_id: order.id,
|
|
description: "Test",
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.exchange
|
|
|
|
const item = order.items[0]
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchange.id}/inbound/items`,
|
|
{
|
|
items: [
|
|
{
|
|
id: item.id,
|
|
reason_id: returnReason.id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchange.id}/inbound/shipping-method`,
|
|
{ shipping_option_id: returnShippingOption.id },
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchange.id}/outbound/items`,
|
|
{
|
|
items: [
|
|
{
|
|
variant_id: productExtra.variants[0].id,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchange.id}/outbound/shipping-method`,
|
|
{ shipping_option_id: outboundShippingOption.id },
|
|
adminHeaders
|
|
)
|
|
|
|
orderPreview = (
|
|
await api.get(`/admin/orders/${order.id}/preview`, adminHeaders)
|
|
).data.order
|
|
})
|
|
|
|
it("should remove outbound shipping method when outbound items are completely removed", async () => {
|
|
orderPreview = (
|
|
await api.get(`/admin/orders/${order.id}/preview`, adminHeaders)
|
|
).data.order
|
|
|
|
const exchangeItems = orderPreview.items.filter(
|
|
(item) =>
|
|
!!item.actions?.find((action) => action.action === "ITEM_ADD")
|
|
)
|
|
|
|
const exchangeShippingMethods = orderPreview.shipping_methods.filter(
|
|
(item) =>
|
|
!!item.actions?.find(
|
|
(action) =>
|
|
action.action === "SHIPPING_ADD" && !action.return_id
|
|
)
|
|
)
|
|
|
|
expect(exchangeItems).toHaveLength(1)
|
|
expect(exchangeShippingMethods).toHaveLength(1)
|
|
|
|
await api.delete(
|
|
`/admin/exchanges/${exchange.id}/outbound/items/${exchangeItems[0].actions[0].id}`,
|
|
adminHeaders
|
|
)
|
|
|
|
orderPreview = (
|
|
await api.get(`/admin/orders/${order.id}/preview`, adminHeaders)
|
|
).data.order
|
|
|
|
const updatedExchangeItems = orderPreview.items.filter(
|
|
(item) =>
|
|
!!item.actions?.find((action) => action.action === "ITEM_ADD")
|
|
)
|
|
|
|
const updatedClaimShippingMethods =
|
|
orderPreview.shipping_methods.filter(
|
|
(item) =>
|
|
!!item.actions?.find(
|
|
(action) =>
|
|
action.action === "SHIPPING_ADD" && !action.return_id
|
|
)
|
|
)
|
|
|
|
expect(updatedExchangeItems).toHaveLength(0)
|
|
expect(updatedClaimShippingMethods).toHaveLength(0)
|
|
})
|
|
|
|
it("should remove inbound shipping method when inbound items are completely removed", async () => {
|
|
orderPreview = (
|
|
await api.get(`/admin/orders/${order.id}/preview`, adminHeaders)
|
|
).data.order
|
|
|
|
const exchangeItems = orderPreview.items.filter(
|
|
(item) =>
|
|
!!item.actions?.find((action) => action.action === "RETURN_ITEM")
|
|
)
|
|
|
|
const exchangeShippingMethods = orderPreview.shipping_methods.filter(
|
|
(item) =>
|
|
!!item.actions?.find(
|
|
(action) =>
|
|
action.action === "SHIPPING_ADD" && !!action.return_id
|
|
)
|
|
)
|
|
|
|
expect(exchangeItems).toHaveLength(1)
|
|
expect(exchangeShippingMethods).toHaveLength(1)
|
|
|
|
await api.delete(
|
|
`/admin/exchanges/${exchange.id}/inbound/items/${exchangeItems[0].actions[0].id}`,
|
|
adminHeaders
|
|
)
|
|
|
|
orderPreview = (
|
|
await api.get(`/admin/orders/${order.id}/preview`, adminHeaders)
|
|
).data.order
|
|
|
|
const updatedExchangeItems = orderPreview.items.filter(
|
|
(item) =>
|
|
!!item.actions?.find((action) => action.action === "RETURN_ITEM")
|
|
)
|
|
|
|
const updatedClaimShippingMethods =
|
|
orderPreview.shipping_methods.filter(
|
|
(item) =>
|
|
!!item.actions?.find(
|
|
(action) =>
|
|
action.action === "SHIPPING_ADD" && !!action.return_id
|
|
)
|
|
)
|
|
|
|
expect(updatedExchangeItems).toHaveLength(0)
|
|
expect(updatedClaimShippingMethods).toHaveLength(0)
|
|
})
|
|
})
|
|
})
|
|
},
|
|
})
|