## Summary
**What** — What changes are introduced in this PR?
Remove `default_locale` from Store <> Locale relation
**Why** — Why are these changes relevant or necessary?
*Please provide answer here*
**How** — How have these changes been implemented?
*Please provide answer here*
**Testing** — How have these changes been tested, or how can the reviewer test the feature?
*Please provide answer here*
---
## Examples
Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice.
This helps with documentation and ensures maintainers can quickly understand and verify the change.
```ts
// Example usage
```
---
## Checklist
Please ensure the following before requesting a review:
- [ ] I have added a **changeset** for this PR
- Every non-breaking change should be marked as a **patch**
- To add a changeset, run `yarn changeset` and follow the prompts
- [ ] The changes are covered by relevant **tests**
- [ ] I have verified the code works as intended locally
- [ ] I have linked the related issue(s) if applicable
---
## Additional Context
Add any additional context, related issues, or references that might help the reviewer understand this PR.
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
528 lines
16 KiB
TypeScript
528 lines
16 KiB
TypeScript
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("Exchange 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 outboundShippingOption: { id: string }
|
|
let inventoryItem: { id: string }
|
|
|
|
beforeAll(async () => {
|
|
appContainer = getContainer()
|
|
})
|
|
|
|
beforeEach(async () => {
|
|
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
|
|
|
|
outboundShippingOption = (
|
|
await api.post(
|
|
`/admin/shipping-options`,
|
|
{
|
|
name: "Outbound 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: 0 }],
|
|
rules: [
|
|
{
|
|
operator: RuleOperator.EQ,
|
|
attribute: "is_return",
|
|
value: "false",
|
|
},
|
|
],
|
|
},
|
|
adminHeaders
|
|
)
|
|
).data.shipping_option
|
|
|
|
await api.post(
|
|
"/admin/translations/batch",
|
|
{
|
|
create: [
|
|
{
|
|
reference_id: product.id,
|
|
reference: "product",
|
|
locale_code: "fr-FR",
|
|
translations: {
|
|
title: "T-Shirt Medusa",
|
|
description: "Un t-shirt en coton confortable",
|
|
},
|
|
},
|
|
{
|
|
reference_id: product.id,
|
|
reference: "product",
|
|
locale_code: "de-DE",
|
|
translations: {
|
|
title: "Medusa T-Shirt DE",
|
|
description: "Ein bequemes Baumwoll-T-Shirt",
|
|
},
|
|
},
|
|
{
|
|
reference_id: product.variants[0].id,
|
|
reference: "product_variant",
|
|
locale_code: "fr-FR",
|
|
translations: { title: "Petit" },
|
|
},
|
|
{
|
|
reference_id: product.variants[0].id,
|
|
reference: "product_variant",
|
|
locale_code: "de-DE",
|
|
translations: { title: "Klein" },
|
|
},
|
|
{
|
|
reference_id: product.variants[1].id,
|
|
reference: "product_variant",
|
|
locale_code: "fr-FR",
|
|
translations: { title: "Moyen" },
|
|
},
|
|
{
|
|
reference_id: product.variants[1].id,
|
|
reference: "product_variant",
|
|
locale_code: "de-DE",
|
|
translations: { title: "Mittel" },
|
|
},
|
|
],
|
|
},
|
|
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
|
|
|
|
return (await api.get(`/admin/orders/${order.id}`, adminHeaders)).data
|
|
.order
|
|
}
|
|
|
|
describe("Exchange items translation", () => {
|
|
it("should translate new items in exchange using order locale", async () => {
|
|
const order = await createOrderFromCart("fr-FR")
|
|
|
|
await api.post(
|
|
`/admin/orders/${order.id}/fulfillments`,
|
|
{
|
|
location_id: stockLocation.id,
|
|
items: [{ id: order.items[0].id, quantity: 1 }],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
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
|
|
)
|
|
|
|
// 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: "T-Shirt Medusa",
|
|
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
|
|
)
|
|
|
|
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
|
|
)
|
|
|
|
// 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",
|
|
})
|
|
)
|
|
})
|
|
|
|
it("should have original values when order has no locale", async () => {
|
|
const order = await createOrderFromCart()
|
|
|
|
await api.post(
|
|
`/admin/orders/${order.id}/fulfillments`,
|
|
{
|
|
location_id: stockLocation.id,
|
|
items: [{ id: order.items[0].id, quantity: 1 }],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
const exchange = (
|
|
await api.post(
|
|
"/admin/exchanges",
|
|
{ order_id: order.id, description: "Test exchange" },
|
|
adminHeaders
|
|
)
|
|
).data.exchange
|
|
|
|
await api.post(
|
|
`/admin/exchanges/${exchange.id}/inbound/items`,
|
|
{
|
|
items: [{ id: order.items[0].id, quantity: 1 }],
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
// 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",
|
|
product_description: "A comfortable cotton t-shirt",
|
|
variant_title: "Medium",
|
|
})
|
|
)
|
|
})
|
|
})
|
|
})
|
|
},
|
|
})
|