feat(core-flows, types): update shipping methods upon cart ops (#10382)
* feat(core-flows,framework,medusa): list shipping options pass in cart as pricing context * chore: add test for shipping options returning free shipping * feat(core-flows, types): update shipping methods upon cart ops * chore: fix specs * chore: fix bugs + specs * Update update-shipping-methods.ts Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> * Update mutations.ts Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> * chore: undo refresh changes * chore: merge with latest * chore: address PR comments * chore: fix conflicts * chore: fix specs * chore: address reviews --------- Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
@@ -302,7 +302,107 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id/line-items", () => {
|
||||
let shippingOption
|
||||
|
||||
beforeEach(async () => {
|
||||
const stockLocation = (
|
||||
await api.post(
|
||||
`/admin/stock-locations`,
|
||||
{ name: "test location" },
|
||||
adminHeaders
|
||||
)
|
||||
).data.stock_location
|
||||
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/sales-channels`,
|
||||
{ add: [salesChannel.id] },
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const shippingProfile = (
|
||||
await api.post(
|
||||
`/admin/shipping-profiles`,
|
||||
{ name: `test-${stockLocation.id}`, type: "default" },
|
||||
adminHeaders
|
||||
)
|
||||
).data.shipping_profile
|
||||
|
||||
const fulfillmentSets = (
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/fulfillment-sets?fields=*fulfillment_sets`,
|
||||
{
|
||||
name: `Test-${shippingProfile.id}`,
|
||||
type: "test-type",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.stock_location.fulfillment_sets
|
||||
|
||||
const fulfillmentSet = (
|
||||
await api.post(
|
||||
`/admin/fulfillment-sets/${fulfillmentSets[0].id}/service-zones`,
|
||||
{
|
||||
name: `Test-${shippingProfile.id}`,
|
||||
geo_zones: [
|
||||
{ type: "country", country_code: "it" },
|
||||
{ type: "country", country_code: "us" },
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.fulfillment_set
|
||||
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/fulfillment-providers`,
|
||||
{ add: ["manual_test-provider"] },
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
shippingOption = (
|
||||
await api.post(
|
||||
`/admin/shipping-options`,
|
||||
{
|
||||
name: `Shipping`,
|
||||
service_zone_id: fulfillmentSet.service_zones[0].id,
|
||||
shipping_profile_id: shippingProfile.id,
|
||||
provider_id: "manual_test-provider",
|
||||
price_type: "flat",
|
||||
type: {
|
||||
label: "Test type",
|
||||
description: "Test description",
|
||||
code: "test-code",
|
||||
},
|
||||
prices: [
|
||||
{ currency_code: "usd", amount: 1000 },
|
||||
{
|
||||
currency_code: "usd",
|
||||
amount: 0,
|
||||
rules: [
|
||||
{
|
||||
attribute: "item_total",
|
||||
operator: "gt",
|
||||
value: 5000,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
rules: [
|
||||
{
|
||||
attribute: "enabled_in_store",
|
||||
value: '"true"',
|
||||
operator: "eq",
|
||||
},
|
||||
{
|
||||
attribute: "is_return",
|
||||
value: "false",
|
||||
operator: "eq",
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.shipping_option
|
||||
|
||||
cart = (
|
||||
await api.post(
|
||||
`/store/carts`,
|
||||
@@ -362,6 +462,101 @@ medusaIntegrationTestRunner({
|
||||
)
|
||||
})
|
||||
|
||||
describe("with custom shipping options prices", () => {
|
||||
beforeEach(async () => {
|
||||
cart = (
|
||||
await api.post(
|
||||
`/store/carts`,
|
||||
{
|
||||
currency_code: "usd",
|
||||
sales_channel_id: salesChannel.id,
|
||||
region_id: region.id,
|
||||
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
|
||||
promo_codes: [promotion.code],
|
||||
},
|
||||
storeHeadersWithCustomer
|
||||
)
|
||||
).data.cart
|
||||
})
|
||||
|
||||
it("should update shipping method amount when cart totals change", async () => {
|
||||
let response = await api.post(
|
||||
`/store/carts/${cart.id}/shipping-methods`,
|
||||
{ option_id: shippingOption.id },
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
shipping_methods: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: 1000,
|
||||
is_tax_inclusive: true,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
response = await api.post(
|
||||
`/store/carts/${cart.id}/line-items`,
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 100,
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
shipping_methods: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: 0,
|
||||
is_tax_inclusive: true,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should remove shipping methods when they are no longer valid for the cart", async () => {
|
||||
let response = await api.post(
|
||||
`/store/carts/${cart.id}/shipping-methods`,
|
||||
{ option_id: shippingOption.id },
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
shipping_methods: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: 1000,
|
||||
is_tax_inclusive: true,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
response = await api.post(
|
||||
`/store/carts/${cart.id}`,
|
||||
{ region_id: noAutomaticRegion.id },
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
shipping_methods: expect.arrayContaining([]),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("should add item to cart with tax lines multiple times", async () => {
|
||||
let response = await api.post(
|
||||
`/store/carts/${cart.id}/line-items`,
|
||||
@@ -1529,6 +1724,222 @@ medusaIntegrationTestRunner({
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id/shipping-methods", () => {
|
||||
let shippingOption
|
||||
|
||||
beforeEach(async () => {
|
||||
const stockLocation = (
|
||||
await api.post(
|
||||
`/admin/stock-locations`,
|
||||
{ name: "test location" },
|
||||
adminHeaders
|
||||
)
|
||||
).data.stock_location
|
||||
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/sales-channels`,
|
||||
{ add: [salesChannel.id] },
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const shippingProfile = (
|
||||
await api.post(
|
||||
`/admin/shipping-profiles`,
|
||||
{ name: `test-${stockLocation.id}`, type: "default" },
|
||||
adminHeaders
|
||||
)
|
||||
).data.shipping_profile
|
||||
|
||||
const fulfillmentSets = (
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/fulfillment-sets?fields=*fulfillment_sets`,
|
||||
{
|
||||
name: `Test-${shippingProfile.id}`,
|
||||
type: "test-type",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.stock_location.fulfillment_sets
|
||||
|
||||
const fulfillmentSet = (
|
||||
await api.post(
|
||||
`/admin/fulfillment-sets/${fulfillmentSets[0].id}/service-zones`,
|
||||
{
|
||||
name: `Test-${shippingProfile.id}`,
|
||||
geo_zones: [
|
||||
{ type: "country", country_code: "it" },
|
||||
{ type: "country", country_code: "us" },
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.fulfillment_set
|
||||
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/fulfillment-providers`,
|
||||
{ add: ["manual_test-provider"] },
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
shippingOption = (
|
||||
await api.post(
|
||||
`/admin/shipping-options`,
|
||||
{
|
||||
name: `Test shipping option ${fulfillmentSet.id}`,
|
||||
service_zone_id: fulfillmentSet.service_zones[0].id,
|
||||
shipping_profile_id: shippingProfile.id,
|
||||
provider_id: "manual_test-provider",
|
||||
price_type: "flat",
|
||||
type: {
|
||||
label: "Test type",
|
||||
description: "Test description",
|
||||
code: "test-code",
|
||||
},
|
||||
prices: [
|
||||
{ currency_code: "usd", amount: 1000 },
|
||||
{
|
||||
currency_code: "usd",
|
||||
amount: 500,
|
||||
rules: [
|
||||
{
|
||||
attribute: "item_total",
|
||||
operator: "gt",
|
||||
value: 3000,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
rules: [
|
||||
{
|
||||
attribute: "enabled_in_store",
|
||||
value: '"true"',
|
||||
operator: "eq",
|
||||
},
|
||||
{
|
||||
attribute: "is_return",
|
||||
value: "false",
|
||||
operator: "eq",
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.shipping_option
|
||||
|
||||
cart = (
|
||||
await api.post(
|
||||
`/store/carts?fields=+total`,
|
||||
{
|
||||
currency_code: "usd",
|
||||
sales_channel_id: salesChannel.id,
|
||||
region_id: region.id,
|
||||
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
|
||||
},
|
||||
storeHeadersWithCustomer
|
||||
)
|
||||
).data.cart
|
||||
})
|
||||
|
||||
it("should add shipping method to cart", async () => {
|
||||
let response = await api.post(
|
||||
`/store/carts/${cart.id}/shipping-methods`,
|
||||
{ option_id: shippingOption.id },
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
shipping_methods: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: 1000,
|
||||
is_tax_inclusive: true,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
// Total is over the amount 3000 to enable the second pricing rule
|
||||
const cart2 = (
|
||||
await api.post(
|
||||
`/store/carts?fields=+total`,
|
||||
{
|
||||
currency_code: "usd",
|
||||
sales_channel_id: salesChannel.id,
|
||||
region_id: region.id,
|
||||
items: [{ variant_id: product.variants[0].id, quantity: 5 }],
|
||||
},
|
||||
storeHeadersWithCustomer
|
||||
)
|
||||
).data.cart
|
||||
|
||||
response = await api.post(
|
||||
`/store/carts/${cart2.id}/shipping-methods`,
|
||||
{ option_id: shippingOption.id },
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart2.id,
|
||||
shipping_methods: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: 500,
|
||||
is_tax_inclusive: true,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw when prices are not setup for shipping option", async () => {
|
||||
cart = (
|
||||
await api.post(
|
||||
`/store/carts?fields=+total`,
|
||||
{
|
||||
currency_code: "eur",
|
||||
sales_channel_id: salesChannel.id,
|
||||
region_id: region.id,
|
||||
items: [{ variant_id: product.variants[0].id, quantity: 5 }],
|
||||
},
|
||||
storeHeadersWithCustomer
|
||||
)
|
||||
).data.cart
|
||||
|
||||
let { response } = await api
|
||||
.post(
|
||||
`/store/carts/${cart.id}/shipping-methods`,
|
||||
{ option_id: shippingOption.id },
|
||||
storeHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.data).toEqual({
|
||||
type: "invalid_data",
|
||||
message: `Shipping options with IDs ${shippingOption.id} do not have a price`,
|
||||
})
|
||||
})
|
||||
|
||||
it("should throw when shipping option id is not found", async () => {
|
||||
let { response } = await api
|
||||
.post(
|
||||
`/store/carts/${cart.id}/shipping-methods`,
|
||||
{ option_id: "does-not-exist" },
|
||||
storeHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(400)
|
||||
expect(response.data).toEqual({
|
||||
type: "invalid_data",
|
||||
message: "Shipping Options are invalid for cart.",
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -152,12 +152,12 @@ medusaIntegrationTestRunner({
|
||||
amount: 500,
|
||||
rules: [
|
||||
{
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "gte",
|
||||
value: 100,
|
||||
},
|
||||
{
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "lte",
|
||||
value: 200,
|
||||
},
|
||||
@@ -220,12 +220,12 @@ medusaIntegrationTestRunner({
|
||||
rules_count: 2,
|
||||
price_rules: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "gte",
|
||||
value: "100",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "lte",
|
||||
value: "200",
|
||||
}),
|
||||
@@ -329,7 +329,7 @@ medusaIntegrationTestRunner({
|
||||
amount: 500,
|
||||
rules: [
|
||||
{
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "gt",
|
||||
value: 200,
|
||||
},
|
||||
@@ -380,7 +380,7 @@ medusaIntegrationTestRunner({
|
||||
rules_count: 2,
|
||||
price_rules: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "gt",
|
||||
value: "200",
|
||||
}),
|
||||
@@ -460,7 +460,7 @@ medusaIntegrationTestRunner({
|
||||
amount: 500,
|
||||
rules: [
|
||||
{
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "not_whitelisted",
|
||||
value: 100,
|
||||
},
|
||||
@@ -498,7 +498,7 @@ medusaIntegrationTestRunner({
|
||||
amount: 500,
|
||||
rules: [
|
||||
{
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "gt",
|
||||
value: "string",
|
||||
},
|
||||
@@ -628,7 +628,7 @@ medusaIntegrationTestRunner({
|
||||
amount: 5,
|
||||
rules: [
|
||||
{
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "gt",
|
||||
value: 200,
|
||||
},
|
||||
@@ -704,7 +704,7 @@ medusaIntegrationTestRunner({
|
||||
amount: 5,
|
||||
price_rules: [
|
||||
expect.objectContaining({
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
operator: "gt",
|
||||
value: "200",
|
||||
}),
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
||||
import {
|
||||
IFulfillmentModuleService,
|
||||
IRegionModuleService,
|
||||
} from "@medusajs/types"
|
||||
import { ContainerRegistrationKeys, Modules } from "@medusajs/utils"
|
||||
import {
|
||||
createAdminUser,
|
||||
generatePublishableKey,
|
||||
@@ -20,9 +15,6 @@ medusaIntegrationTestRunner({
|
||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||
describe("Store: Shipping Option API", () => {
|
||||
let appContainer
|
||||
let fulfillmentModule: IFulfillmentModuleService
|
||||
let regionService: IRegionModuleService
|
||||
|
||||
let salesChannel
|
||||
let region
|
||||
let regionTwo
|
||||
@@ -36,8 +28,6 @@ medusaIntegrationTestRunner({
|
||||
|
||||
beforeAll(async () => {
|
||||
appContainer = getContainer()
|
||||
fulfillmentModule = appContainer.resolve(Modules.FULFILLMENT)
|
||||
regionService = appContainer.resolve(Modules.REGION)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -45,31 +35,27 @@ medusaIntegrationTestRunner({
|
||||
storeHeaders = generateStoreHeaders({ publishableKey })
|
||||
|
||||
await createAdminUser(dbConnection, adminHeaders, appContainer)
|
||||
const remoteLinkService = appContainer.resolve(
|
||||
ContainerRegistrationKeys.REMOTE_LINK
|
||||
)
|
||||
|
||||
region = await regionService.createRegions({
|
||||
name: "Test region",
|
||||
countries: ["US"],
|
||||
currency_code: "usd",
|
||||
})
|
||||
region = (
|
||||
await api.post(
|
||||
"/admin/regions",
|
||||
{ name: "US", currency_code: "usd", countries: ["US"] },
|
||||
adminHeaders
|
||||
)
|
||||
).data.region
|
||||
|
||||
regionTwo = await regionService.createRegions({
|
||||
name: "Test region two",
|
||||
countries: ["DK"],
|
||||
currency_code: "dkk",
|
||||
})
|
||||
|
||||
await api.post(
|
||||
"/admin/price-preferences",
|
||||
{
|
||||
attribute: "region_id",
|
||||
value: regionTwo.id,
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
regionTwo = (
|
||||
await api.post(
|
||||
"/admin/regions",
|
||||
{
|
||||
name: "Test region two",
|
||||
currency_code: "dkk",
|
||||
countries: ["DK"],
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.region
|
||||
|
||||
salesChannel = (
|
||||
await api.post(
|
||||
@@ -116,22 +102,39 @@ medusaIntegrationTestRunner({
|
||||
stockLocation = (
|
||||
await api.post(
|
||||
`/admin/stock-locations`,
|
||||
{
|
||||
name: "test location",
|
||||
},
|
||||
{ name: "test location" },
|
||||
adminHeaders
|
||||
)
|
||||
).data.stock_location
|
||||
|
||||
shippingProfile = await fulfillmentModule.createShippingProfiles({
|
||||
name: "Test",
|
||||
type: "default",
|
||||
})
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/sales-channels`,
|
||||
{ add: [salesChannel.id] },
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
fulfillmentSet = await fulfillmentModule.createFulfillmentSets({
|
||||
name: "Test",
|
||||
type: "test-type",
|
||||
service_zones: [
|
||||
shippingProfile = (
|
||||
await api.post(
|
||||
`/admin/shipping-profiles`,
|
||||
{ name: "Test", type: "default" },
|
||||
adminHeaders
|
||||
)
|
||||
).data.shipping_profile
|
||||
|
||||
const fulfillmentSets = (
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/fulfillment-sets?fields=*fulfillment_sets`,
|
||||
{
|
||||
name: "Test",
|
||||
type: "test-type",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.stock_location.fulfillment_sets
|
||||
|
||||
fulfillmentSet = (
|
||||
await api.post(
|
||||
`/admin/fulfillment-sets/${fulfillmentSets[0].id}/service-zones`,
|
||||
{
|
||||
name: "Test",
|
||||
geo_zones: [
|
||||
@@ -139,27 +142,9 @@ medusaIntegrationTestRunner({
|
||||
{ type: "country", country_code: "dk" },
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLinkService.create([
|
||||
{
|
||||
[Modules.SALES_CHANNEL]: {
|
||||
sales_channel_id: salesChannel.id,
|
||||
},
|
||||
[Modules.STOCK_LOCATION]: {
|
||||
stock_location_id: stockLocation.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
[Modules.STOCK_LOCATION]: {
|
||||
stock_location_id: stockLocation.id,
|
||||
},
|
||||
[Modules.FULFILLMENT]: {
|
||||
fulfillment_set_id: fulfillmentSet.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
adminHeaders
|
||||
)
|
||||
).data.fulfillment_set
|
||||
|
||||
await api.post(
|
||||
`/admin/stock-locations/${stockLocation.id}/fulfillment-providers`,
|
||||
@@ -196,7 +181,7 @@ medusaIntegrationTestRunner({
|
||||
rules: [
|
||||
{
|
||||
operator: "gt",
|
||||
attribute: "total",
|
||||
attribute: "item_total",
|
||||
value: 2000,
|
||||
},
|
||||
],
|
||||
@@ -246,8 +231,11 @@ medusaIntegrationTestRunner({
|
||||
expect.objectContaining({
|
||||
id: shippingOption.id,
|
||||
name: "Test shipping option",
|
||||
amount: 1100,
|
||||
price_type: "flat",
|
||||
amount: 1100,
|
||||
calculated_price: expect.objectContaining({
|
||||
calculated_amount: 1100,
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
@@ -272,8 +260,12 @@ medusaIntegrationTestRunner({
|
||||
id: shippingOption.id,
|
||||
name: "Test shipping option",
|
||||
amount: 500,
|
||||
price_type: "flat",
|
||||
is_tax_inclusive: true,
|
||||
calculated_price: expect.objectContaining({
|
||||
calculated_amount: 500,
|
||||
is_calculated_price_tax_inclusive: true,
|
||||
}),
|
||||
price_type: "flat",
|
||||
})
|
||||
)
|
||||
})
|
||||
@@ -313,6 +305,9 @@ medusaIntegrationTestRunner({
|
||||
name: "Test shipping option",
|
||||
// Free shipping due to cart total being greater than 2000
|
||||
amount: 0,
|
||||
calculated_price: expect.objectContaining({
|
||||
calculated_amount: 0,
|
||||
}),
|
||||
price_type: "flat",
|
||||
})
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,6 @@ import {
|
||||
Modules,
|
||||
ProductStatus,
|
||||
PromotionType,
|
||||
RuleOperator,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
createAdminUser,
|
||||
@@ -715,221 +714,6 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
})
|
||||
|
||||
it("should add item to cart", async () => {
|
||||
const customer = await customerModule.createCustomers({
|
||||
email: "tony@stark-industries.com",
|
||||
})
|
||||
|
||||
const salesChannel = await scModule.createSalesChannels({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const [productWithSpecialTax] = await productModule.createProducts([
|
||||
{
|
||||
// This product ID is setup in the tax structure fixture (setupTaxStructure)
|
||||
id: "product_id_1",
|
||||
title: "Test product",
|
||||
variants: [{ title: "Test variant", manage_inventory: false }],
|
||||
} as any,
|
||||
])
|
||||
|
||||
const [productWithDefaultTax] = await productModule.createProducts([
|
||||
{
|
||||
title: "Test product default tax",
|
||||
variants: [
|
||||
{ title: "Test variant default tax", manage_inventory: false },
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
await api.post(
|
||||
"/admin/price-preferences",
|
||||
{
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const cart = await cartModule.createCarts({
|
||||
currency_code: "usd",
|
||||
customer_id: customer.id,
|
||||
sales_channel_id: salesChannel.id,
|
||||
region_id: region.id,
|
||||
shipping_address: {
|
||||
customer_id: customer.id,
|
||||
address_1: "test address 1",
|
||||
address_2: "test address 2",
|
||||
city: "SF",
|
||||
country_code: "US",
|
||||
province: "CA",
|
||||
postal_code: "94016",
|
||||
},
|
||||
items: [
|
||||
{
|
||||
id: "item-1",
|
||||
unit_price: 2000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_mat",
|
||||
} as any,
|
||||
],
|
||||
})
|
||||
|
||||
const appliedPromotion = await promotionModule.createPromotions({
|
||||
code: "PROMOTION_APPLIED",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "across",
|
||||
value: 300,
|
||||
apply_to_quantity: 2,
|
||||
currency_code: "usd",
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "product_id",
|
||||
operator: "in",
|
||||
values: ["prod_mat", productWithSpecialTax.id],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const [lineItemAdjustment] = await cartModule.addLineItemAdjustments([
|
||||
{
|
||||
code: appliedPromotion.code!,
|
||||
amount: 300,
|
||||
item_id: "item-1",
|
||||
promotion_id: appliedPromotion.id,
|
||||
},
|
||||
])
|
||||
|
||||
const [priceSet, priceSetDefaultTax] =
|
||||
await pricingModule.createPriceSets([
|
||||
{
|
||||
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||
},
|
||||
{
|
||||
prices: [{ amount: 2000, currency_code: "usd" }],
|
||||
},
|
||||
])
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
variant_id: productWithSpecialTax.variants[0].id,
|
||||
},
|
||||
[Modules.PRICING]: { price_set_id: priceSet.id },
|
||||
},
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
variant_id: productWithDefaultTax.variants[0].id,
|
||||
},
|
||||
[Modules.PRICING]: { price_set_id: priceSetDefaultTax.id },
|
||||
},
|
||||
{
|
||||
[Modules.CART]: { cart_id: cart.id },
|
||||
[Modules.PROMOTION]: { promotion_id: appliedPromotion.id },
|
||||
},
|
||||
])
|
||||
|
||||
let response = await api.post(
|
||||
`/store/carts/${cart.id}/line-items`,
|
||||
{
|
||||
variant_id: productWithSpecialTax.variants[0].id,
|
||||
quantity: 1,
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
currency_code: "usd",
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
unit_price: 3000,
|
||||
is_tax_inclusive: true,
|
||||
quantity: 1,
|
||||
title: "Test variant",
|
||||
tax_lines: [
|
||||
expect.objectContaining({
|
||||
description: "CA Reduced Rate for Products",
|
||||
code: "CAREDUCE_PROD",
|
||||
rate: 3,
|
||||
provider_id: "system",
|
||||
}),
|
||||
],
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
code: "PROMOTION_APPLIED",
|
||||
amount: 177.86561264822134,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
expect.objectContaining({
|
||||
unit_price: 2000,
|
||||
is_tax_inclusive: false,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
tax_lines: [
|
||||
expect.objectContaining({
|
||||
code: "CADEFAULT",
|
||||
description: "CA Default Rate",
|
||||
provider_id: "system",
|
||||
rate: 5,
|
||||
}),
|
||||
],
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
id: expect.not.stringContaining(lineItemAdjustment.id),
|
||||
code: "PROMOTION_APPLIED",
|
||||
amount: 122.13438735177866,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
response = await api.post(
|
||||
`/store/carts/${cart.id}/line-items`,
|
||||
{
|
||||
variant_id: productWithDefaultTax.variants[0].id,
|
||||
quantity: 1,
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
currency_code: "usd",
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
unit_price: 2000,
|
||||
is_tax_inclusive: true,
|
||||
quantity: 1,
|
||||
title: "Test variant default tax",
|
||||
tax_lines: [
|
||||
// Uses the california default rate
|
||||
expect.objectContaining({
|
||||
description: "CA Default Rate",
|
||||
code: "CADEFAULT",
|
||||
rate: 5,
|
||||
provider_id: "system",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("adding an existing variant should update or create line item depending on metadata", async () => {
|
||||
const product = (
|
||||
await api.post(`/admin/products`, productData, adminHeaders)
|
||||
@@ -1304,102 +1088,6 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id/shipping-methods", () => {
|
||||
it("should add a shipping methods to a cart", async () => {
|
||||
const cart = await cartModule.createCarts({
|
||||
currency_code: "usd",
|
||||
shipping_address: { country_code: "us" },
|
||||
items: [],
|
||||
})
|
||||
|
||||
const shippingProfile =
|
||||
await fulfillmentModule.createShippingProfiles({
|
||||
name: "Test",
|
||||
type: "default",
|
||||
})
|
||||
|
||||
const fulfillmentSet = await fulfillmentModule.createFulfillmentSets({
|
||||
name: "Test",
|
||||
type: "test-type",
|
||||
service_zones: [
|
||||
{
|
||||
name: "Test",
|
||||
geo_zones: [{ type: "country", country_code: "us" }],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await api.post(
|
||||
"/admin/price-preferences",
|
||||
{
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const priceSet = await pricingModule.createPriceSets({
|
||||
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||
})
|
||||
|
||||
const shippingOption = await fulfillmentModule.createShippingOptions({
|
||||
name: "Test shipping option",
|
||||
service_zone_id: fulfillmentSet.service_zones[0].id,
|
||||
shipping_profile_id: shippingProfile.id,
|
||||
provider_id: "manual_test-provider",
|
||||
price_type: "flat",
|
||||
type: {
|
||||
label: "Test type",
|
||||
description: "Test description",
|
||||
code: "test-code",
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
operator: RuleOperator.EQ,
|
||||
attribute: "is_return",
|
||||
value: "false",
|
||||
},
|
||||
{
|
||||
operator: RuleOperator.EQ,
|
||||
attribute: "enabled_in_store",
|
||||
value: "true",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
[Modules.FULFILLMENT]: { shipping_option_id: shippingOption.id },
|
||||
[Modules.PRICING]: { price_set_id: priceSet.id },
|
||||
},
|
||||
])
|
||||
|
||||
let response = await api.post(
|
||||
`/store/carts/${cart.id}/shipping-methods`,
|
||||
{ option_id: shippingOption.id },
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
shipping_methods: [
|
||||
{
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: 3000,
|
||||
is_tax_inclusive: true,
|
||||
id: expect.any(String),
|
||||
tax_lines: [],
|
||||
adjustments: [],
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id/complete", () => {
|
||||
let salesChannel
|
||||
let product
|
||||
|
||||
Reference in New Issue
Block a user