feat(core-flows,types,utils,medusa): Translate tax lines (#14359)

* Include locale field for traslations on tax line workflows

* Translate tax lines in getItemTaxLinesStep with new util

* Update tax calculation context, so that we pass locale to third party tax providers if they want to return translated tax rates

* Apply translations to tax lines on product and variant tax middlewares

* Cart management translations tests

* Update tax lines when order locale gets updated

* Add changeset

* Get tranlsated tax lines step

* Fix wording

* Mutate ref directly

* Update order tax lines translations upon order locale change

* Claims translations tests

* Update tax lines upon draft order locale update

* Exchange tests for tax lines translations

* Order edits test for tax line translation

* Add tests for shipping methods tax line translations on various order flows

* Returns shipping method translations tests

* Execute update in parallel

* Use TranslationFeatureFlag.key

* Fix feature flag import

* Add @medusajs/medusa dependency for feature flag usage

* Revert "Add @medusajs/medusa dependency for feature flag usage"

This reverts commit e8897aed0a88f83c1034ac73e817e4222250a2c9.

* Use feature flag string directly

* Fix test

* Parallelize tax line translations application
This commit is contained in:
Nicolas Gorga
2026-01-13 15:12:42 -03:00
committed by GitHub
parent 28fae96cee
commit cec8b8e428
23 changed files with 2032 additions and 164 deletions

View File

@@ -31,6 +31,8 @@ medusaIntegrationTestRunner({
let product: { id: string; variants: { id: string; title: string }[] }
let salesChannel: { id: string }
let shippingProfile: { id: string }
let taxRegion: { id: string }
let taxRate: { id: string; name: string }
beforeAll(async () => {
appContainer = getContainer()
@@ -85,6 +87,59 @@ medusaIntegrationTestRunner({
)
).data.region
// Create tax region and tax rate for tax line translations
taxRegion = (
await api.post(
"/admin/tax-regions",
{
country_code: "us",
provider_id: "tp_system",
},
adminHeaders
)
).data.tax_region
// Create the default tax rate
taxRate = (
await api.post(
"/admin/tax-rates",
{
tax_region_id: taxRegion.id,
name: "US Sales Tax",
rate: 5,
code: "US_SALES_TAX",
is_default: true,
},
adminHeaders
)
).data.tax_rate
// Create translations for tax rate name
await api.post(
"/admin/translations/batch",
{
create: [
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "fr-FR",
translations: {
name: "Taxe de vente US",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "de-DE",
translations: {
name: "US Umsatzsteuer",
},
},
],
},
adminHeaders
)
// Create product with description for translation
product = (
await api.post(
@@ -516,6 +571,255 @@ medusaIntegrationTestRunner({
})
})
describe("Tax line translations", () => {
it("should translate tax line descriptions when creating a cart with locale", async () => {
const response = await api.post(
`/store/carts`,
{
currency_code: "usd",
sales_channel_id: salesChannel.id,
region_id: region.id,
locale: "fr-FR",
shipping_address: shippingAddressData,
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
},
storeHeaders
)
expect(response.status).toEqual(200)
expect(response.data.cart.items[0]).toEqual(
expect.objectContaining({
tax_lines: expect.arrayContaining([
expect.objectContaining({
description: "Taxe de vente US",
rate: 5,
}),
]),
})
)
})
it("should use original tax line description when no locale is provided", async () => {
const response = await api.post(
`/store/carts`,
{
currency_code: "usd",
sales_channel_id: salesChannel.id,
region_id: region.id,
shipping_address: shippingAddressData,
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
},
storeHeaders
)
expect(response.status).toEqual(200)
expect(response.data.cart.items[0]).toEqual(
expect.objectContaining({
tax_lines: expect.arrayContaining([
expect.objectContaining({
description: "US Sales Tax",
rate: 5,
}),
]),
})
)
})
it("should translate tax line descriptions when adding items to cart with locale", async () => {
const cartResponse = await api.post(
`/store/carts`,
{
currency_code: "usd",
sales_channel_id: salesChannel.id,
region_id: region.id,
locale: "de-DE",
shipping_address: shippingAddressData,
},
storeHeaders
)
const cart = cartResponse.data.cart
const addItemResponse = await api.post(
`/store/carts/${cart.id}/line-items`,
{
variant_id: product.variants[0].id,
quantity: 1,
},
storeHeaders
)
expect(addItemResponse.status).toEqual(200)
expect(addItemResponse.data.cart.items[0]).toEqual(
expect.objectContaining({
tax_lines: expect.arrayContaining([
expect.objectContaining({
description: "US Umsatzsteuer",
rate: 5,
}),
]),
})
)
})
it("should re-translate tax line descriptions when cart locale is updated", async () => {
const cartResponse = await api.post(
`/store/carts`,
{
currency_code: "usd",
sales_channel_id: salesChannel.id,
region_id: region.id,
locale: "fr-FR",
shipping_address: shippingAddressData,
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
},
storeHeaders
)
const cart = cartResponse.data.cart
// Verify French translation
expect(cart.items[0].tax_lines[0].description).toEqual(
"Taxe de vente US"
)
// Update locale to German
const updateResponse = await api.post(
`/store/carts/${cart.id}`,
{
locale: "de-DE",
},
storeHeaders
)
expect(updateResponse.status).toEqual(200)
// Fetch updated cart
const updatedCartResponse = await api.get(
`/store/carts/${cart.id}`,
storeHeaders
)
const updatedCart = updatedCartResponse.data.cart
// Verify German translation
expect(updatedCart.items[0]).toEqual(
expect.objectContaining({
tax_lines: expect.arrayContaining([
expect.objectContaining({
description: "US Umsatzsteuer",
rate: 5,
}),
]),
})
)
})
it("should revert to original tax line description when locale has no translation", async () => {
const cartResponse = await api.post(
`/store/carts`,
{
currency_code: "usd",
sales_channel_id: salesChannel.id,
region_id: region.id,
locale: "fr-FR",
shipping_address: shippingAddressData,
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
},
storeHeaders
)
const cart = cartResponse.data.cart
// Verify French translation exists
expect(cart.items[0].tax_lines[0].description).toEqual(
"Taxe de vente US"
)
// Update to locale without translation
const updateResponse = await api.post(
`/store/carts/${cart.id}`,
{
locale: "ja-JP",
},
storeHeaders
)
expect(updateResponse.status).toEqual(200)
// Fetch updated cart
const updatedCartResponse = await api.get(
`/store/carts/${cart.id}`,
storeHeaders
)
const updatedCart = updatedCartResponse.data.cart
// Should revert to original description
expect(updatedCart.items[0]).toEqual(
expect.objectContaining({
tax_lines: expect.arrayContaining([
expect.objectContaining({
description: "US Sales Tax",
rate: 5,
}),
]),
})
)
})
it("should translate tax lines for all items when multiple items are added", async () => {
const cartResponse = await api.post(
`/store/carts`,
{
currency_code: "usd",
sales_channel_id: salesChannel.id,
region_id: region.id,
locale: "fr-FR",
shipping_address: shippingAddressData,
},
storeHeaders
)
const cart = cartResponse.data.cart
// Add first item
await api.post(
`/store/carts/${cart.id}/line-items`,
{
variant_id: product.variants[0].id,
quantity: 1,
},
storeHeaders
)
// Add second item
const response = await api.post(
`/store/carts/${cart.id}/line-items`,
{
variant_id: product.variants[1].id,
quantity: 1,
},
storeHeaders
)
expect(response.status).toEqual(200)
expect(response.data.cart.items).toHaveLength(2)
// Both items should have translated tax lines
response.data.cart.items.forEach((item: any) => {
expect(item.tax_lines).toEqual(
expect.arrayContaining([
expect.objectContaining({
description: "Taxe de vente US",
rate: 5,
}),
])
)
})
})
})
describe("POST /store/carts/:id/shipping-methods (shipping method translation)", () => {
let shippingOption

View File

@@ -1,7 +1,9 @@
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
import { MedusaContainer } from "@medusajs/types"
import {
ClaimReason,
ClaimType,
ContainerRegistrationKeys,
Modules,
ProductStatus,
RuleOperator,
@@ -10,6 +12,7 @@ import {
adminHeaders,
createAdminUser,
} from "../../../helpers/create-admin-user"
import { setupTaxStructure } from "../../../modules/__tests__/fixtures"
jest.setTimeout(60000)
@@ -17,36 +20,34 @@ process.env.MEDUSA_FF_TRANSLATION = "true"
medusaIntegrationTestRunner({
testSuite: ({ dbConnection, getContainer, api }) => {
let appContainer: MedusaContainer
let order
let customer
let returnShippingOption
let outboundShippingOption
let shippingProfile
let fulfillmentSet
let inventoryItem
let location
let salesChannel
let region
let product
let productExtra
let shippingProfile
let stockLocation
let location
let fulfillmentSet
let inventoryItem
let inventoryItemExtra
let taxRate
let salesChannel
let region
let customer
let shippingOption
let returnShippingOption
let outboundShippingOption
const shippingProviderId = "manual_test-provider"
beforeEach(async () => {
const container = getContainer()
await createAdminUser(dbConnection, adminHeaders, container)
appContainer = getContainer()
await createAdminUser(dbConnection, adminHeaders, appContainer)
customer = (
await api.post(
"/admin/customers",
{
first_name: "joe",
email: "joe@admin.com",
},
adminHeaders
)
).data.customer
const taxStructure = await setupTaxStructure(
appContainer.resolve(Modules.TAX)
)
// Set up supported locales in the store
const storeModule = container.resolve(Modules.STORE)
const storeModule = appContainer.resolve(Modules.STORE)
const [defaultStore] = await storeModule.listStores(
{},
{ select: ["id"], take: 1 }
@@ -59,10 +60,34 @@ medusaIntegrationTestRunner({
],
})
region = (
await api.post(
"/admin/regions",
{
name: "test-region",
currency_code: "usd",
},
adminHeaders
)
).data.region
customer = (
await api.post(
"/admin/customers",
{
first_name: "joe",
email: "joe@admin.com",
},
adminHeaders
)
).data.customer
salesChannel = (
await api.post(
"/admin/sales-channels",
{ name: "Webshop", description: "channel" },
{
name: "Test channel",
},
adminHeaders
)
).data.sales_channel
@@ -70,21 +95,13 @@ medusaIntegrationTestRunner({
shippingProfile = (
await api.post(
`/admin/shipping-profiles`,
{ name: "Test", type: "default" },
adminHeaders
)
).data.shipping_profile
region = (
await api.post(
"/admin/regions",
{
name: "Test Region",
currency_code: "usd",
name: "Test",
type: "default",
},
adminHeaders
)
).data.region
).data.shipping_profile
location = (
await api.post(
@@ -154,7 +171,6 @@ medusaIntegrationTestRunner({
title: "Extra variant",
sku: "extra-variant",
options: { size: "large" },
manage_inventory: false,
prices: [{ currency_code: "usd", amount: 50 }],
},
],
@@ -163,7 +179,7 @@ medusaIntegrationTestRunner({
)
).data.product
location = (
stockLocation = (
await api.post(
`/admin/stock-locations/${location.id}/fulfillment-sets?fields=*fulfillment_sets`,
{ name: "Test", type: "test-type" },
@@ -173,7 +189,7 @@ medusaIntegrationTestRunner({
fulfillmentSet = (
await api.post(
`/admin/fulfillment-sets/${location.fulfillment_sets[0].id}/service-zones`,
`/admin/fulfillment-sets/${stockLocation.fulfillment_sets[0].id}/service-zones`,
{
name: "Test",
geo_zones: [{ type: "country", country_code: "us" }],
@@ -182,12 +198,55 @@ medusaIntegrationTestRunner({
)
).data.fulfillment_set
inventoryItemExtra = (
await api.get(`/admin/inventory-items?sku=extra-variant`, adminHeaders)
).data.inventory_items[0]
await api.post(
`/admin/stock-locations/${location.id}/fulfillment-providers`,
{ add: ["manual_test-provider"] },
`/admin/inventory-items/${inventoryItemExtra.id}/location-levels`,
{
location_id: location.id,
stocked_quantity: 10,
},
adminHeaders
)
const remoteLink = appContainer.resolve(
ContainerRegistrationKeys.REMOTE_LINK
)
await api.post(
`/admin/stock-locations/${stockLocation.id}/fulfillment-providers`,
{ add: [shippingProviderId] },
adminHeaders
)
shippingOption = (
await api.post(
"/admin/shipping-options",
{
name: "Test shipping option",
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: 10,
},
],
rules: [],
},
adminHeaders
)
).data.shipping_option
returnShippingOption = (
await api.post(
"/admin/shipping-options",
@@ -222,7 +281,7 @@ medusaIntegrationTestRunner({
name: "Outbound shipping",
service_zone_id: fulfillmentSet.service_zones[0].id,
shipping_profile_id: shippingProfile.id,
provider_id: "manual_test-provider",
provider_id: shippingProviderId,
price_type: "flat",
type: {
label: "Test type",
@@ -242,11 +301,78 @@ medusaIntegrationTestRunner({
)
).data.shipping_option
// Create translations for shipping options
await remoteLink.create([
{
[Modules.STOCK_LOCATION]: {
stock_location_id: stockLocation.id,
},
[Modules.FULFILLMENT]: {
fulfillment_provider_id: shippingProviderId,
},
},
{
[Modules.STOCK_LOCATION]: {
stock_location_id: stockLocation.id,
},
[Modules.FULFILLMENT]: {
fulfillment_set_id: fulfillmentSet.id,
},
},
{
[Modules.SALES_CHANNEL]: {
sales_channel_id: salesChannel.id,
},
[Modules.STOCK_LOCATION]: {
stock_location_id: stockLocation.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,
},
},
])
const taxRatesResponse = await api.get(
`/admin/tax-rates?tax_region_id=${taxStructure.us.children.cal.province.id}`,
adminHeaders
)
taxRate = taxRatesResponse.data.tax_rates.find(
(rate: { code: string }) => rate.code === "CADEFAULT"
)
// Create translations for tax rates and shipping options
await api.post(
"/admin/translations/batch",
{
create: [
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "fr-FR",
translations: {
name: "Taux par défaut CA",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "de-DE",
translations: {
name: "CA Standardsteuersatz",
},
},
{
reference_id: returnShippingOption.id,
reference: "shipping_option",
@@ -278,9 +404,8 @@ medusaIntegrationTestRunner({
})
const createOrderWithLocale = async (locale?: string) => {
const container = getContainer()
const orderModule = container.resolve(Modules.ORDER)
const inventoryModule = container.resolve(Modules.INVENTORY)
const orderModule = appContainer.resolve(Modules.ORDER)
const inventoryModule = appContainer.resolve(Modules.INVENTORY)
const createdOrder = await orderModule.createOrders({
region_id: region.id,
@@ -302,6 +427,7 @@ medusaIntegrationTestRunner({
address_1: "Test",
city: "Test",
country_code: "US",
province: "CA",
postal_code: "12345",
phone: "12345",
},
@@ -312,6 +438,7 @@ medusaIntegrationTestRunner({
address_1: "Test",
city: "Test",
country_code: "US",
province: "CA",
postal_code: "12345",
},
shipping_methods: [
@@ -319,6 +446,7 @@ medusaIntegrationTestRunner({
name: "Test shipping method",
amount: 10,
data: {},
shipping_option_id: shippingOption.id,
},
],
currency_code: "usd",
@@ -334,7 +462,7 @@ medusaIntegrationTestRunner({
await inventoryModule.createReservationItems([
{
inventory_item_id: inventoryItem.id,
location_id: location.id,
location_id: stockLocation.id,
quantity: 2,
line_item_id: createdOrder.items![0].id,
},
@@ -357,6 +485,288 @@ medusaIntegrationTestRunner({
return createdOrder
}
describe("Claims tax line translations", () => {
describe("when adding outbound items to a claim", () => {
it("should translate tax lines based on order locale when adding new items", async () => {
order = await createOrderWithLocale("fr-FR")
const claim = (
await api.post(
"/admin/claims",
{
order_id: order.id,
type: ClaimType.REPLACE,
description: "Test claim",
},
adminHeaders
)
).data.claim
await api.post(
`/admin/claims/${claim.id}/outbound/items`,
{
items: [
{
variant_id: productExtra.variants[0].id,
quantity: 1,
},
],
},
adminHeaders
)
await api.post(`/admin/claims/${claim.id}/request`, {}, adminHeaders)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const newItem = updatedOrder.items.find(
(item) => item.title === "Extra product"
)
expect(newItem).toBeDefined()
expect(newItem.tax_lines).toBeDefined()
expect(newItem.tax_lines.length).toBeGreaterThan(0)
const taxLine = newItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine).toBeDefined()
expect(taxLine.description).toEqual("Taux par défaut CA")
})
it("should use original tax line description when order has no locale", async () => {
order = await createOrderWithLocale()
const claim = (
await api.post(
"/admin/claims",
{
order_id: order.id,
type: ClaimType.REPLACE,
description: "Test claim",
},
adminHeaders
)
).data.claim
await api.post(
`/admin/claims/${claim.id}/outbound/items`,
{
items: [
{
variant_id: productExtra.variants[0].id,
quantity: 1,
},
],
},
adminHeaders
)
await api.post(`/admin/claims/${claim.id}/request`, {}, adminHeaders)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const newItem = updatedOrder.items.find(
(item) => item.title === "Extra product"
)
expect(newItem).toBeDefined()
expect(newItem.tax_lines).toBeDefined()
expect(newItem.tax_lines.length).toBeGreaterThan(0)
const taxLine = newItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine).toBeDefined()
expect(taxLine.description).toEqual("CA Default Rate")
})
})
describe("when adding outbound shipping methods to a claim", () => {
it("should translate shipping method tax lines based on order locale", async () => {
order = await createOrderWithLocale("fr-FR")
await api.post(
`/admin/orders/${order.id}`,
{ locale: "fr-FR" },
adminHeaders
)
const claim = (
await api.post(
"/admin/claims",
{
order_id: order.id,
type: ClaimType.REPLACE,
description: "Test claim",
},
adminHeaders
)
).data.claim
await api.post(
`/admin/claims/${claim.id}/outbound/items`,
{
items: [
{
variant_id: productExtra.variants[0].id,
quantity: 1,
},
],
},
adminHeaders
)
await api.post(
`/admin/claims/${claim.id}/outbound/shipping-method`,
{ shipping_option_id: outboundShippingOption.id },
adminHeaders
)
await api.post(`/admin/claims/${claim.id}/request`, {}, adminHeaders)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const outboundShippingMethod = updatedOrder.shipping_methods.find(
(sm) => sm.shipping_option_id === outboundShippingOption.id
)
expect(outboundShippingMethod.tax_lines.length).toBeGreaterThan(0)
const taxLine = outboundShippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("Taux par défaut CA")
})
it("should use original tax line description when order has no locale", async () => {
order = await createOrderWithLocale()
const claim = (
await api.post(
"/admin/claims",
{
order_id: order.id,
type: ClaimType.REPLACE,
description: "Test claim",
},
adminHeaders
)
).data.claim
await api.post(
`/admin/claims/${claim.id}/outbound/items`,
{
items: [
{
variant_id: productExtra.variants[0].id,
quantity: 1,
},
],
},
adminHeaders
)
await api.post(
`/admin/claims/${claim.id}/outbound/shipping-method`,
{ shipping_option_id: outboundShippingOption.id },
adminHeaders
)
await api.post(`/admin/claims/${claim.id}/request`, {}, adminHeaders)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const outboundShippingMethod = updatedOrder.shipping_methods.find(
(sm) => sm.shipping_option_id === outboundShippingOption.id
)
expect(outboundShippingMethod.tax_lines.length).toBeGreaterThan(0)
const taxLine = outboundShippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("CA Default Rate")
})
})
describe("when updating outbound items in a claim", () => {
it("should preserve tax line translations when updating item quantity", async () => {
order = await createOrderWithLocale("fr-FR")
await api.post(
`/admin/orders/${order.id}`,
{ locale: "fr-FR" },
adminHeaders
)
const claim = (
await api.post(
"/admin/claims",
{
order_id: order.id,
type: ClaimType.REPLACE,
description: "Test claim",
},
adminHeaders
)
).data.claim
const addItemResponse = await api.post(
`/admin/claims/${claim.id}/outbound/items`,
{
items: [
{
variant_id: productExtra.variants[0].id,
quantity: 1,
},
],
},
adminHeaders
)
const actionId = addItemResponse.data.order_preview.items.find(
(item) =>
!!item.actions?.find((action) => action.action === "ITEM_ADD")
).actions[0].id
await api.post(
`/admin/claims/${claim.id}/outbound/items/${actionId}`,
{
quantity: 2,
},
adminHeaders
)
await api.post(`/admin/claims/${claim.id}/request`, {}, adminHeaders)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const newItem = updatedOrder.items.find(
(item) => item.title === "Extra product"
)
expect(newItem).toBeDefined()
expect(newItem.tax_lines).toBeDefined()
expect(newItem.tax_lines.length).toBeGreaterThan(0)
const taxLine = newItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine).toBeDefined()
expect(taxLine.description).toEqual("Taux par défaut CA")
})
})
})
describe("Claim shipping method translation", () => {
describe("Inbound (return) shipping method", () => {
it("should translate inbound shipping method name using French locale", async () => {

View File

@@ -21,13 +21,16 @@ medusaIntegrationTestRunner({
let shippingProfile: { id: string }
let stockLocation: { id: string }
let shippingOption: { id: string }
let taxRate: { id: string }
beforeAll(async () => {
appContainer = getContainer()
})
beforeEach(async () => {
await setupTaxStructure(appContainer.resolve(Modules.TAX))
const taxStructure = await setupTaxStructure(
appContainer.resolve(Modules.TAX)
)
await createAdminUser(dbConnection, adminHeaders, appContainer)
salesChannel = (
@@ -162,6 +165,14 @@ medusaIntegrationTestRunner({
)
).data.shipping_option
const taxRatesResponse = await api.get(
`/admin/tax-rates?tax_region_id=${taxStructure.us.children.cal.province.id}`,
adminHeaders
)
taxRate = taxRatesResponse.data.tax_rates.find(
(rate: { code: string }) => rate.code === "CADEFAULT"
)
await api.post(
"/admin/translations/batch",
{
@@ -224,6 +235,22 @@ medusaIntegrationTestRunner({
name: "Test-Versandoption",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "fr-FR",
translations: {
name: "Taux par défaut CA",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "de-DE",
translations: {
name: "CA Standardsteuersatz",
},
},
],
},
adminHeaders
@@ -244,6 +271,7 @@ medusaIntegrationTestRunner({
address_1: "123 Main St",
city: "Anytown",
country_code: "us",
province: "ca",
postal_code: "12345",
first_name: "John",
},
@@ -283,6 +311,12 @@ medusaIntegrationTestRunner({
variant_title: "Petit",
})
)
expect(updatedDraftOrder.items[0].tax_lines.length).toBeGreaterThan(0)
const taxLine = updatedDraftOrder.items[0].tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("Taux par défaut CA")
})
it("should have original values when draft order has no locale", async () => {
@@ -297,6 +331,7 @@ medusaIntegrationTestRunner({
address_1: "123 Main St",
city: "Anytown",
country_code: "us",
province: "ca",
postal_code: "12345",
first_name: "John",
},
@@ -336,6 +371,12 @@ medusaIntegrationTestRunner({
variant_title: "Small",
})
)
expect(updatedDraftOrder.items[0].tax_lines.length).toBeGreaterThan(0)
const taxLine = updatedDraftOrder.items[0].tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("CA Default Rate")
})
it("should translate multiple items added to draft order", async () => {
@@ -351,6 +392,7 @@ medusaIntegrationTestRunner({
address_1: "123 Main St",
city: "Anytown",
country_code: "us",
province: "ca",
postal_code: "12345",
first_name: "John",
},
@@ -407,6 +449,146 @@ medusaIntegrationTestRunner({
variant_title: "Mittel",
})
)
expect(smallItem.tax_lines.length).toBeGreaterThan(0)
const smallTaxLine = smallItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(smallTaxLine.description).toEqual("CA Standardsteuersatz")
expect(mediumItem.tax_lines.length).toBeGreaterThan(0)
const mediumTaxLine = mediumItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(mediumTaxLine.description).toEqual("CA Standardsteuersatz")
})
})
describe("POST /admin/draft-orders/:id/edit/shipping-methods (add shipping method to draft order)", () => {
it("should translate shipping method tax lines when adding to draft order with locale", async () => {
const draftOrder = (
await api.post(
"/admin/draft-orders",
{
email: "test@test.com",
region_id: region.id,
sales_channel_id: salesChannel.id,
locale: "fr-FR",
shipping_address: {
address_1: "123 Main St",
city: "Anytown",
country_code: "us",
province: "ca",
postal_code: "12345",
first_name: "John",
},
},
adminHeaders
)
).data.draft_order
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit`,
{},
adminHeaders
)
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit/items`,
{
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
},
adminHeaders
)
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit/shipping-methods`,
{
shipping_option_id: shippingOption.id,
},
adminHeaders
)
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit/confirm`,
{},
adminHeaders
)
const updatedDraftOrder = (
await api.get(`/admin/draft-orders/${draftOrder.id}`, adminHeaders)
).data.draft_order
expect(updatedDraftOrder.shipping_methods.length).toBeGreaterThan(0)
const shippingMethod = updatedDraftOrder.shipping_methods[0]
const taxLine = shippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("Taux par défaut CA")
})
it("should use original tax line description when draft order has no locale", async () => {
const draftOrder = (
await api.post(
"/admin/draft-orders",
{
email: "test@test.com",
region_id: region.id,
sales_channel_id: salesChannel.id,
shipping_address: {
address_1: "123 Main St",
city: "Anytown",
country_code: "us",
province: "ca",
postal_code: "12345",
first_name: "John",
},
},
adminHeaders
)
).data.draft_order
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit`,
{},
adminHeaders
)
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit/items`,
{
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
},
adminHeaders
)
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit/shipping-methods`,
{
shipping_option_id: shippingOption.id,
},
adminHeaders
)
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit/confirm`,
{},
adminHeaders
)
const updatedDraftOrder = (
await api.get(`/admin/draft-orders/${draftOrder.id}`, adminHeaders)
).data.draft_order
expect(updatedDraftOrder.shipping_methods.length).toBeGreaterThan(0)
const shippingMethod = updatedDraftOrder.shipping_methods[0]
const taxLine = shippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine).toBeDefined()
expect(taxLine.description).toEqual("CA Default Rate")
})
})
@@ -424,6 +606,7 @@ medusaIntegrationTestRunner({
address_1: "123 Main St",
city: "Anytown",
country_code: "us",
province: "ca",
postal_code: "12345",
first_name: "John",
},
@@ -449,6 +632,14 @@ medusaIntegrationTestRunner({
adminHeaders
)
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit/shipping-methods`,
{
shipping_option_id: shippingOption.id,
},
adminHeaders
)
await api.post(
`/admin/draft-orders/${draftOrder.id}/edit/confirm`,
{},
@@ -464,6 +655,12 @@ medusaIntegrationTestRunner({
)
expect(frenchSmallItem.variant_title).toEqual("Petit")
expect(frenchSmallItem.tax_lines.length).toBeGreaterThan(0)
const frenchTaxLine = frenchSmallItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(frenchTaxLine.description).toEqual("Taux par défaut CA")
await api.post(
`/admin/draft-orders/${draftOrder.id}`,
{ locale: "de-DE" },
@@ -494,6 +691,31 @@ medusaIntegrationTestRunner({
variant_title: "Mittel",
})
)
expect(germanSmallItem.tax_lines.length).toBeGreaterThan(0)
const germanSmallTaxLine = germanSmallItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(germanSmallTaxLine.description).toEqual(
"CA Standardsteuersatz"
)
expect(germanMediumItem.tax_lines.length).toBeGreaterThan(0)
const germanMediumTaxLine = germanMediumItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(germanMediumTaxLine.description).toEqual(
"CA Standardsteuersatz"
)
expect(updatedDraftOrder.shipping_methods.length).toBeGreaterThan(0)
const shippingMethod = updatedDraftOrder.shipping_methods[0]
const shippingTaxLine = shippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(shippingTaxLine).toBeDefined()
expect(shippingTaxLine.description).toEqual("CA Standardsteuersatz")
})
})

View File

@@ -36,13 +36,16 @@ medusaIntegrationTestRunner({
let outboundShippingOption: { id: string }
let returnShippingOption: { id: string }
let inventoryItem: { id: string }
let taxRate: { id: string }
beforeAll(async () => {
appContainer = getContainer()
})
beforeEach(async () => {
await setupTaxStructure(appContainer.resolve(Modules.TAX))
const taxStructure = await setupTaxStructure(
appContainer.resolve(Modules.TAX)
)
await createAdminUser(dbConnection, adminHeaders, appContainer)
const publishableKey = await generatePublishableKey(appContainer)
storeHeaders = generateStoreHeaders({ publishableKey })
@@ -251,6 +254,13 @@ medusaIntegrationTestRunner({
adminHeaders
)
).data.shipping_option
const taxRatesResponse = await api.get(
`/admin/tax-rates?tax_region_id=${taxStructure.us.children.cal.province.id}`,
adminHeaders
)
taxRate = taxRatesResponse.data.tax_rates.find(
(rate: { code: string }) => rate.code === "CADEFAULT"
)
await api.post(
"/admin/translations/batch",
@@ -330,6 +340,22 @@ medusaIntegrationTestRunner({
name: "Rückversand",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "fr-FR",
translations: {
name: "Taux par défaut CA",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "de-DE",
translations: {
name: "CA Standardsteuersatz",
},
},
],
},
adminHeaders
@@ -447,73 +473,21 @@ medusaIntegrationTestRunner({
variant_title: "Moyen",
})
)
})
it("should translate exchange items using German locale", async () => {
const order = await createOrderFromCart("de-DE")
await api.post(
`/admin/orders/${order.id}/fulfillments`,
{
location_id: stockLocation.id,
items: [{ id: order.items[0].id, quantity: 1 }],
},
adminHeaders
expect(newItem.tax_lines.length).toBeGreaterThan(0)
const taxLine = newItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("Taux par défaut CA")
const exchange = (
await api.post(
"/admin/exchanges",
{ order_id: order.id, description: "Test exchange" },
adminHeaders
)
).data.exchange
// Add inbound item (item being returned)
await api.post(
`/admin/exchanges/${exchange.id}/inbound/items`,
{
items: [{ id: order.items[0].id, quantity: 1 }],
},
adminHeaders
const outboundShippingMethod = updatedOrder.shipping_methods.find(
(sm) => sm.shipping_option_id === outboundShippingOption.id
)
// Add outbound item (new item being sent)
await api.post(
`/admin/exchanges/${exchange.id}/outbound/items`,
{
items: [{ variant_id: product.variants[1].id, quantity: 1 }],
},
adminHeaders
)
await api.post(
`/admin/exchanges/${exchange.id}/outbound/shipping-method`,
{ shipping_option_id: outboundShippingOption.id },
adminHeaders
)
await api.post(
`/admin/exchanges/${exchange.id}/request`,
{},
adminHeaders
)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const newItem = updatedOrder.items.find(
(item: any) => item.variant_id === product.variants[1].id
)
expect(newItem).toEqual(
expect.objectContaining({
product_title: "Medusa T-Shirt DE",
product_description: "Ein bequemes Baumwoll-T-Shirt",
variant_title: "Mittel",
})
expect(outboundShippingMethod.tax_lines.length).toBeGreaterThan(0)
const shippingTaxLine = outboundShippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(shippingTaxLine.description).toEqual("Taux par défaut CA")
})
it("should have original values when order has no locale", async () => {
@@ -580,6 +554,21 @@ medusaIntegrationTestRunner({
variant_title: "Medium",
})
)
expect(newItem.tax_lines.length).toBeGreaterThan(0)
const taxLine = newItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("CA Default Rate")
const outboundShippingMethod = updatedOrder.shipping_methods.find(
(sm) => sm.shipping_option_id === outboundShippingOption.id
)
expect(outboundShippingMethod.tax_lines.length).toBeGreaterThan(0)
const shippingTaxLine = outboundShippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(shippingTaxLine.description).toEqual("CA Default Rate")
})
})

View File

@@ -35,13 +35,16 @@ medusaIntegrationTestRunner({
let shippingOption: { id: string }
let additionalShippingOption: { id: string }
let inventoryItem: { id: string }
let taxRate: { id: string }
beforeAll(async () => {
appContainer = getContainer()
})
beforeEach(async () => {
await setupTaxStructure(appContainer.resolve(Modules.TAX))
const taxStructure = await setupTaxStructure(
appContainer.resolve(Modules.TAX)
)
await createAdminUser(dbConnection, adminHeaders, appContainer)
const publishableKey = await generatePublishableKey(appContainer)
storeHeaders = generateStoreHeaders({ publishableKey })
@@ -217,6 +220,13 @@ medusaIntegrationTestRunner({
adminHeaders
)
).data.shipping_option
const taxRatesResponse = await api.get(
`/admin/tax-rates?tax_region_id=${taxStructure.us.children.cal.province.id}`,
adminHeaders
)
taxRate = taxRatesResponse.data.tax_rates.find(
(rate: { code: string }) => rate.code === "CADEFAULT"
)
await api.post(
"/admin/translations/batch",
@@ -296,6 +306,22 @@ medusaIntegrationTestRunner({
name: "Zusätzliche Versandoption",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "fr-FR",
translations: {
name: "Taux par défaut CA",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "de-DE",
translations: {
name: "CA Standardsteuersatz",
},
},
],
},
adminHeaders
@@ -386,6 +412,12 @@ medusaIntegrationTestRunner({
variant_title: "Moyen",
})
)
expect(newItem.tax_lines.length).toBeGreaterThan(0)
const taxLine = newItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("Taux par défaut CA")
})
it("should have original values when order has no locale", async () => {
@@ -426,46 +458,12 @@ medusaIntegrationTestRunner({
variant_title: "Medium",
})
)
})
it("should translate items using German locale", async () => {
const order = await createOrderFromCart("de-DE")
await api.post(
"/admin/order-edits",
{ order_id: order.id },
adminHeaders
)
await api.post(
`/admin/order-edits/${order.id}/items`,
{
items: [{ variant_id: product.variants[1].id, quantity: 1 }],
},
adminHeaders
)
await api.post(
`/admin/order-edits/${order.id}/confirm`,
{},
adminHeaders
)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const newItem = updatedOrder.items.find(
(item) => item.variant_id === product.variants[1].id
)
expect(newItem).toEqual(
expect.objectContaining({
product_title: "Medusa T-Shirt DE",
product_description: "Ein bequemes Baumwoll-T-Shirt",
variant_title: "Mittel",
})
expect(newItem.tax_lines.length).toBeGreaterThan(0)
const taxLine = newItem.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("CA Default Rate")
})
})
@@ -557,6 +555,78 @@ medusaIntegrationTestRunner({
])
)
})
it("should translate shipping method tax lines when adding to order edit with locale", async () => {
const order = await createOrderFromCart("fr-FR")
await api.post(
"/admin/order-edits",
{ order_id: order.id },
adminHeaders
)
await api.post(
`/admin/order-edits/${order.id}/shipping-method`,
{ shipping_option_id: shippingOption.id },
adminHeaders
)
await api.post(
`/admin/order-edits/${order.id}/confirm`,
{},
adminHeaders
)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const newShippingMethod = updatedOrder.shipping_methods.find(
(sm) => sm.shipping_option_id === shippingOption.id
)
expect(newShippingMethod.tax_lines.length).toBeGreaterThan(0)
const taxLine = newShippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("Taux par défaut CA")
})
it("should use original tax line description when order has no locale", async () => {
const order = await createOrderFromCart()
await api.post(
"/admin/order-edits",
{ order_id: order.id },
adminHeaders
)
await api.post(
`/admin/order-edits/${order.id}/shipping-method`,
{ shipping_option_id: shippingOption.id },
adminHeaders
)
await api.post(
`/admin/order-edits/${order.id}/confirm`,
{},
adminHeaders
)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const newShippingMethod = updatedOrder.shipping_methods.find(
(sm) => sm.shipping_option_id === shippingOption.id
)
expect(newShippingMethod.tax_lines.length).toBeGreaterThan(0)
const taxLine = newShippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("CA Default Rate")
})
})
})
},

View File

@@ -36,13 +36,16 @@ medusaIntegrationTestRunner({
let returnShippingOption: { id: string }
let outboundShippingOption: { id: string }
let inventoryItem: { id: string }
let taxRate: { id: string; name: string }
beforeAll(async () => {
appContainer = getContainer()
})
beforeEach(async () => {
await setupTaxStructure(appContainer.resolve(Modules.TAX))
const taxStructure = await setupTaxStructure(
appContainer.resolve(Modules.TAX)
)
await createAdminUser(dbConnection, adminHeaders, appContainer)
const publishableKey = await generatePublishableKey(appContainer)
storeHeaders = generateStoreHeaders({ publishableKey })
@@ -255,7 +258,16 @@ medusaIntegrationTestRunner({
)
).data.shipping_option
// Create translations for product, variants, and shipping options
const taxRatesResponse = await api.get(
`/admin/tax-rates?tax_region_id=${taxStructure.us.children.cal.province.id}`,
adminHeaders
)
taxRate = taxRatesResponse.data.tax_rates.find(
(rate: { is_default: boolean; code: string }) =>
rate.is_default && rate.code === "CADEFAULT"
)
// Create translations for product and variants
await api.post(
"/admin/translations/batch",
{
@@ -318,6 +330,22 @@ medusaIntegrationTestRunner({
name: "Test-Versandoption",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "fr-FR",
translations: {
name: "Taux par défaut CA",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "de-DE",
translations: {
name: "CA Standardsteuersatz",
},
},
],
},
adminHeaders
@@ -521,6 +549,119 @@ medusaIntegrationTestRunner({
)
})
})
describe("Tax line translations", () => {
it("should translate tax line descriptions when order locale is updated", async () => {
// Create order with French locale
const order = await createOrderFromCart("fr-FR")
// Verify tax lines exist and have French translation
expect(order.items[0].tax_lines).toBeDefined()
expect(order.items[0].tax_lines.length).toBe(1)
expect(order.items[0].tax_lines[0]).toEqual(
expect.objectContaining({
description: "Taux par défaut CA",
rate: 5,
code: "CADEFAULT",
})
)
// Update order locale to German
await api.post(
`/admin/orders/${order.id}`,
{ locale: "de-DE" },
adminHeaders
)
// Fetch updated order
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
// Verify tax lines are translated to German
expect(updatedOrder.items[0].tax_lines.length).toBe(1)
expect(updatedOrder.items[0].tax_lines[0]).toEqual(
expect.objectContaining({
description: "CA Standardsteuersatz",
rate: 5,
code: "CADEFAULT",
})
)
})
it("should preserve tax line translations when order is created with locale", async () => {
// Create order with French locale
const order = await createOrderFromCart("fr-FR")
// Verify tax lines are translated from the start
expect(order.items[0].tax_lines).toBeDefined()
expect(order.items[0].tax_lines.length).toBeGreaterThan(0)
expect(order.items[0].tax_lines[0]).toEqual(
expect.objectContaining({
description: "Taux par défaut CA",
rate: 5,
code: "CADEFAULT",
})
)
})
it("should use original tax line description when order has no locale", async () => {
// Create order without locale
const order = await createOrderFromCart()
// Verify tax lines use original description
expect(order.items[0].tax_lines).toBeDefined()
expect(order.items[0].tax_lines.length).toBeGreaterThan(0)
expect(order.items[0].tax_lines[0]).toEqual(
expect.objectContaining({
description: "CA Default Rate",
rate: 5,
code: "CADEFAULT",
})
)
})
it("should translate shipping method tax lines when order locale is updated", async () => {
// Create order with French locale
const order = await createOrderFromCart("fr-FR")
// Verify shipping method tax lines exist and are translated
expect(order.shipping_methods).toBeDefined()
expect(order.shipping_methods.length).toBeGreaterThan(0)
if (order.shipping_methods[0].tax_lines?.length > 0) {
expect(order.shipping_methods[0].tax_lines[0]).toEqual(
expect.objectContaining({
description: "Taux par défaut CA",
rate: 5,
code: "CADEFAULT",
})
)
// Update order locale to German
await api.post(
`/admin/orders/${order.id}`,
{ locale: "de-DE" },
adminHeaders
)
// Fetch updated order
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
// Verify shipping method tax lines are translated
if (updatedOrder.shipping_methods[0].tax_lines?.length > 0) {
expect(updatedOrder.shipping_methods[0].tax_lines[0]).toEqual(
expect.objectContaining({
description: "CA Standardsteuersatz",
rate: 5,
code: "CADEFAULT",
})
)
}
}
})
})
})
},
})

View File

@@ -0,0 +1,428 @@
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
import { MedusaContainer } from "@medusajs/types"
import { Modules, ProductStatus, RuleOperator } from "@medusajs/utils"
import {
adminHeaders,
createAdminUser,
generatePublishableKey,
generateStoreHeaders,
} from "../../../helpers/create-admin-user"
import { setupTaxStructure } from "../../../modules/__tests__/fixtures"
jest.setTimeout(300000)
process.env.MEDUSA_FF_TRANSLATION = "true"
const shippingAddressData = {
address_1: "test address 1",
address_2: "test address 2",
city: "SF",
country_code: "us",
province: "CA",
postal_code: "94016",
}
medusaIntegrationTestRunner({
testSuite: ({ dbConnection, getContainer, api }) => {
describe("Return Translation API", () => {
let appContainer: MedusaContainer
let storeHeaders: { headers: { [key: string]: string } }
let region: { id: string }
let product: { id: string; variants: { id: string; title: string }[] }
let salesChannel: { id: string }
let shippingProfile: { id: string }
let stockLocation: { id: string }
let shippingOption: { id: string }
let returnShippingOption: { id: string }
let inventoryItem: { id: string }
let taxRate: { id: string }
beforeAll(async () => {
appContainer = getContainer()
})
beforeEach(async () => {
const taxStructure = await setupTaxStructure(
appContainer.resolve(Modules.TAX)
)
await createAdminUser(dbConnection, adminHeaders, appContainer)
const publishableKey = await generatePublishableKey(appContainer)
storeHeaders = generateStoreHeaders({ publishableKey })
salesChannel = (
await api.post(
"/admin/sales-channels",
{ name: "Webshop", description: "channel" },
adminHeaders
)
).data.sales_channel
const storeModule = appContainer.resolve(Modules.STORE)
const [defaultStore] = await storeModule.listStores(
{},
{ select: ["id"], take: 1 }
)
await storeModule.updateStores(defaultStore.id, {
supported_locales: [
{ locale_code: "en-US" },
{ locale_code: "fr-FR" },
{ locale_code: "de-DE" },
],
})
region = (
await api.post(
"/admin/regions",
{ name: "US", currency_code: "usd", countries: ["us"] },
adminHeaders
)
).data.region
shippingProfile = (
await api.post(
`/admin/shipping-profiles`,
{ name: "default", type: "default" },
adminHeaders
)
).data.shipping_profile
stockLocation = (
await api.post(
`/admin/stock-locations`,
{ name: "test location" },
adminHeaders
)
).data.stock_location
inventoryItem = (
await api.post(
`/admin/inventory-items`,
{ sku: "test-variant" },
adminHeaders
)
).data.inventory_item
await api.post(
`/admin/inventory-items/${inventoryItem.id}/location-levels`,
{ location_id: stockLocation.id, stocked_quantity: 100 },
adminHeaders
)
await api.post(
`/admin/stock-locations/${stockLocation.id}/sales-channels`,
{ add: [salesChannel.id] },
adminHeaders
)
product = (
await api.post(
"/admin/products",
{
title: "Medusa T-Shirt",
description: "A comfortable cotton t-shirt",
handle: "t-shirt",
status: ProductStatus.PUBLISHED,
shipping_profile_id: shippingProfile.id,
options: [{ title: "Size", values: ["S", "M"] }],
variants: [
{
title: "Small",
sku: "SHIRT-S",
options: { Size: "S" },
inventory_items: [
{
inventory_item_id: inventoryItem.id,
required_quantity: 1,
},
],
prices: [{ amount: 1500, currency_code: "usd" }],
},
{
title: "Medium",
sku: "SHIRT-M",
options: { Size: "M" },
manage_inventory: false,
prices: [{ amount: 1500, currency_code: "usd" }],
},
],
},
adminHeaders
)
).data.product
const variantSmall = product.variants.find((v) => v.title === "Small")
const variantMedium = product.variants.find((v) => v.title === "Medium")
product.variants = [variantSmall!, variantMedium!]
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
const fulfillmentSet = (
await api.post(
`/admin/fulfillment-sets/${fulfillmentSets[0].id}/service-zones`,
{
name: "Test",
geo_zones: [{ 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",
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 }],
rules: [],
},
adminHeaders
)
).data.shipping_option
returnShippingOption = (
await api.post(
`/admin/shipping-options`,
{
name: "Return 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 }],
rules: [
{
operator: RuleOperator.EQ,
attribute: "is_return",
value: "true",
},
],
},
adminHeaders
)
).data.shipping_option
const taxRatesResponse = await api.get(
`/admin/tax-rates?tax_region_id=${taxStructure.us.children.cal.province.id}`,
adminHeaders
)
taxRate = taxRatesResponse.data.tax_rates.find(
(rate: { code: string }) => rate.code === "CADEFAULT"
)
await api.post(
"/admin/translations/batch",
{
create: [
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "fr-FR",
translations: {
name: "Taux par défaut CA",
},
},
{
reference_id: taxRate.id,
reference: "tax_rate",
locale_code: "de-DE",
translations: {
name: "CA Standardsteuersatz",
},
},
],
},
adminHeaders
)
})
const createOrderFromCart = async (locale?: string) => {
const cart = (
await api.post(
`/store/carts`,
{
currency_code: "usd",
email: "test@example.com",
region_id: region.id,
sales_channel_id: salesChannel.id,
locale,
shipping_address: shippingAddressData,
billing_address: shippingAddressData,
items: [{ variant_id: product.variants[0].id, quantity: 1 }],
},
storeHeaders
)
).data.cart
await api.post(
`/store/carts/${cart.id}/shipping-methods`,
{ option_id: shippingOption.id },
storeHeaders
)
const paymentCollection = (
await api.post(
`/store/payment-collections`,
{ cart_id: cart.id },
storeHeaders
)
).data.payment_collection
await api.post(
`/store/payment-collections/${paymentCollection.id}/payment-sessions`,
{ provider_id: "pp_system_default" },
storeHeaders
)
const order = (
await api.post(`/store/carts/${cart.id}/complete`, {}, storeHeaders)
).data.order
const fullOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
await api.post(
`/admin/orders/${fullOrder.id}/fulfillments`,
{
location_id: stockLocation.id,
items: [{ id: fullOrder.items[0].id, quantity: 1 }],
},
adminHeaders
)
return (await api.get(`/admin/orders/${fullOrder.id}`, adminHeaders))
.data.order
}
describe("Return shipping method tax line translations", () => {
it("should translate shipping method tax lines based on order locale", async () => {
const order = await createOrderFromCart("fr-FR")
const return_ = (
await api.post(
"/admin/returns",
{
order_id: order.id,
description: "Test return",
},
adminHeaders
)
).data.return
await api.post(
`/admin/returns/${return_.id}/request-items`,
{
items: [{ id: order.items[0].id, quantity: 1 }],
},
adminHeaders
)
await api.post(
`/admin/returns/${return_.id}/shipping-method`,
{
shipping_option_id: returnShippingOption.id,
},
adminHeaders
)
await api.post(
`/admin/returns/${return_.id}/request`,
{},
adminHeaders
)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const returnShippingMethod = updatedOrder.shipping_methods.find(
(sm) => sm.shipping_option_id === returnShippingOption.id
)
expect(returnShippingMethod.tax_lines.length).toBeGreaterThan(0)
const taxLine = returnShippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("Taux par défaut CA")
})
it("should use original tax line description when order has no locale", async () => {
const order = await createOrderFromCart()
const return_ = (
await api.post(
"/admin/returns",
{
order_id: order.id,
description: "Test return",
},
adminHeaders
)
).data.return
await api.post(
`/admin/returns/${return_.id}/request-items`,
{
items: [{ id: order.items[0].id, quantity: 1 }],
},
adminHeaders
)
await api.post(
`/admin/returns/${return_.id}/shipping-method`,
{
shipping_option_id: returnShippingOption.id,
},
adminHeaders
)
await api.post(
`/admin/returns/${return_.id}/request`,
{},
adminHeaders
)
const updatedOrder = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const returnShippingMethod = updatedOrder.shipping_methods.find(
(sm) => sm.shipping_option_id === returnShippingOption.id
)
expect(returnShippingMethod.tax_lines.length).toBeGreaterThan(0)
const taxLine = returnShippingMethod.tax_lines.find(
(tl) => tl.code === "CADEFAULT"
)
expect(taxLine.description).toEqual("CA Default Rate")
})
})
})
},
})