chore: V2 core loader + modules integration-tests (#6544)
This commit is contained in:
@@ -1,197 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ApiKeyType } from "@medusajs/utils"
|
||||
import { IApiKeyModuleService, IRegionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("API Keys - Admin", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let service: IApiKeyModuleService
|
||||
let regionService: IRegionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
service = appContainer.resolve(ModuleRegistrationName.API_KEY)
|
||||
regionService = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
|
||||
// Used for testing cross-module authentication checks
|
||||
await regionService.createDefaultCountries()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should correctly implement the entire lifecycle of an api key", async () => {
|
||||
const api = useApi() as any
|
||||
const created = await api.post(
|
||||
`/admin/api-keys`,
|
||||
{
|
||||
title: "Test Secret Key",
|
||||
type: ApiKeyType.SECRET,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(created.status).toEqual(200)
|
||||
expect(created.data.apiKey).toEqual(
|
||||
expect.objectContaining({
|
||||
id: created.data.apiKey.id,
|
||||
title: "Test Secret Key",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
)
|
||||
// On create we get the token in raw form so we can store it.
|
||||
expect(created.data.apiKey.token).toContain("sk_")
|
||||
|
||||
const updated = await api.post(
|
||||
`/admin/api-keys/${created.data.apiKey.id}`,
|
||||
{
|
||||
title: "Updated Secret Key",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.apiKey).toEqual(
|
||||
expect.objectContaining({
|
||||
id: created.data.apiKey.id,
|
||||
title: "Updated Secret Key",
|
||||
})
|
||||
)
|
||||
|
||||
const revoked = await api.post(
|
||||
`/admin/api-keys/${created.data.apiKey.id}/revoke`,
|
||||
{},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(revoked.status).toEqual(200)
|
||||
expect(revoked.data.apiKey).toEqual(
|
||||
expect.objectContaining({
|
||||
id: created.data.apiKey.id,
|
||||
revoked_by: "admin_user",
|
||||
})
|
||||
)
|
||||
expect(revoked.data.apiKey.revoked_at).toBeTruthy()
|
||||
|
||||
const deleted = await api.delete(
|
||||
`/admin/api-keys/${created.data.apiKey.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
const listedApiKeys = await api.get(`/admin/api-keys`, adminHeaders)
|
||||
|
||||
expect(deleted.status).toEqual(200)
|
||||
expect(listedApiKeys.data.apiKeys).toHaveLength(0)
|
||||
})
|
||||
|
||||
it("can use a secret api key for authentication", async () => {
|
||||
const api = useApi() as any
|
||||
const created = await api.post(
|
||||
`/admin/api-keys`,
|
||||
{
|
||||
title: "Test Secret Key",
|
||||
type: ApiKeyType.SECRET,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const createdRegion = await api.post(
|
||||
`/admin/regions`,
|
||||
{
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
countries: ["us", "ca"],
|
||||
},
|
||||
{
|
||||
auth: {
|
||||
username: created.data.apiKey.token,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
expect(createdRegion.status).toEqual(200)
|
||||
expect(createdRegion.data.region.name).toEqual("Test Region")
|
||||
})
|
||||
|
||||
it("falls back to other mode of authentication when an api key is not valid", async () => {
|
||||
const api = useApi() as any
|
||||
const created = await api.post(
|
||||
`/admin/api-keys`,
|
||||
{
|
||||
title: "Test Secret Key",
|
||||
type: ApiKeyType.SECRET,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
await api.post(
|
||||
`/admin/api-keys/${created.data.apiKey.id}/revoke`,
|
||||
{},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const err = await api
|
||||
.post(
|
||||
`/admin/regions`,
|
||||
{
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
countries: ["us", "ca"],
|
||||
},
|
||||
{
|
||||
auth: {
|
||||
username: created.data.apiKey.token,
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => e.message)
|
||||
|
||||
const createdRegion = await api.post(
|
||||
`/admin/regions`,
|
||||
{
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
countries: ["us", "ca"],
|
||||
},
|
||||
{
|
||||
auth: {
|
||||
username: created.data.apiKey.token,
|
||||
},
|
||||
...adminHeaders,
|
||||
}
|
||||
)
|
||||
|
||||
expect(err).toEqual("Request failed with status code 401")
|
||||
expect(createdRegion.status).toEqual(200)
|
||||
expect(createdRegion.data.region.name).toEqual("Test Region")
|
||||
})
|
||||
})
|
||||
@@ -1,307 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { ICartModuleService, IPromotionModuleService } from "@medusajs/types"
|
||||
import { PromotionType } from "@medusajs/utils"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("Store Carts API: Add promotions to cart", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let cartModuleService: ICartModuleService
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id/promotions", () => {
|
||||
it("should add line item adjustments to a cart based on promotions", async () => {
|
||||
const appliedPromotion = await promotionModuleService.create({
|
||||
code: "PROMOTION_APPLIED",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "each",
|
||||
value: "300",
|
||||
apply_to_quantity: 1,
|
||||
max_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "product_id",
|
||||
operator: "eq",
|
||||
values: "prod_tshirt",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "PROMOTION_TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "across",
|
||||
value: "1000",
|
||||
apply_to_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "product_id",
|
||||
operator: "eq",
|
||||
values: "prod_mat",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
// Adjustment to add
|
||||
{
|
||||
id: "item-1",
|
||||
unit_price: 2000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_mat",
|
||||
} as any,
|
||||
// This adjustment will be removed and recreated
|
||||
{
|
||||
id: "item-2",
|
||||
unit_price: 1000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_tshirt",
|
||||
} as any,
|
||||
],
|
||||
})
|
||||
|
||||
// Adjustment to keep
|
||||
const [lineItemAdjustment] =
|
||||
await cartModuleService.addLineItemAdjustments([
|
||||
{
|
||||
code: appliedPromotion.code!,
|
||||
amount: 300,
|
||||
item_id: "item-2",
|
||||
promotion_id: appliedPromotion.id,
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const created = await api.post(`/store/carts/${cart.id}/promotions`, {
|
||||
promo_codes: [createdPromotion.code],
|
||||
})
|
||||
|
||||
expect(created.status).toEqual(200)
|
||||
expect(created.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "item-1",
|
||||
adjustments: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
code: createdPromotion.code,
|
||||
amount: 1000,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
adjustments: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.not.stringContaining(lineItemAdjustment.id),
|
||||
code: appliedPromotion.code,
|
||||
amount: 300,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should add shipping method adjustments to a cart based on promotions", async () => {
|
||||
const [appliedPromotion] = await promotionModuleService.create([
|
||||
{
|
||||
code: "PROMOTION_APPLIED",
|
||||
type: PromotionType.STANDARD,
|
||||
rules: [
|
||||
{
|
||||
attribute: "customer_id",
|
||||
operator: "in",
|
||||
values: ["cus_test"],
|
||||
},
|
||||
{
|
||||
attribute: "currency_code",
|
||||
operator: "in",
|
||||
values: ["eur"],
|
||||
},
|
||||
],
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "shipping_methods",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "name",
|
||||
operator: "in",
|
||||
values: ["express"],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const [newPromotion] = await promotionModuleService.create([
|
||||
{
|
||||
code: "PROMOTION_NEW",
|
||||
type: PromotionType.STANDARD,
|
||||
rules: [
|
||||
{
|
||||
attribute: "customer_id",
|
||||
operator: "in",
|
||||
values: ["cus_test"],
|
||||
},
|
||||
{
|
||||
attribute: "currency_code",
|
||||
operator: "in",
|
||||
values: ["eur"],
|
||||
},
|
||||
],
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "shipping_methods",
|
||||
allocation: "each",
|
||||
value: "200",
|
||||
max_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "name",
|
||||
operator: "in",
|
||||
values: ["express", "standard"],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "eur",
|
||||
customer_id: "cus_test",
|
||||
items: [
|
||||
{
|
||||
unit_price: 2000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_mat",
|
||||
} as any,
|
||||
],
|
||||
})
|
||||
|
||||
const [express, standard] = await cartModuleService.addShippingMethods(
|
||||
cart.id,
|
||||
[
|
||||
{
|
||||
amount: 500,
|
||||
name: "express",
|
||||
},
|
||||
{
|
||||
amount: 500,
|
||||
name: "standard",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const [adjustment] = await cartModuleService.addShippingMethodAdjustments(
|
||||
cart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: express.id,
|
||||
amount: 100,
|
||||
code: appliedPromotion.code!,
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const created = await api.post(`/store/carts/${cart.id}/promotions`, {
|
||||
promo_codes: [newPromotion.code],
|
||||
})
|
||||
|
||||
expect(created.status).toEqual(200)
|
||||
expect(created.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
]),
|
||||
shipping_methods: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: express.id,
|
||||
adjustments: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
amount: 200,
|
||||
code: newPromotion.code,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.not.stringContaining(adjustment.id),
|
||||
amount: 100,
|
||||
code: appliedPromotion.code,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: standard.id,
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
amount: 200,
|
||||
code: newPromotion.code,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,672 +0,0 @@
|
||||
import {
|
||||
addToCartWorkflow,
|
||||
createCartWorkflow,
|
||||
deleteLineItemsStepId,
|
||||
deleteLineItemsWorkflow,
|
||||
findOrCreateCustomerStepId,
|
||||
updateLineItemInCartWorkflow,
|
||||
updateLineItemsStepId,
|
||||
} from "@medusajs/core-flows"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
ICartModuleService,
|
||||
ICustomerModuleService,
|
||||
IPricingModuleService,
|
||||
IProductModuleService,
|
||||
IRegionModuleService,
|
||||
ISalesChannelModuleService,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("Carts workflows", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let cartModuleService: ICartModuleService
|
||||
let regionModuleService: IRegionModuleService
|
||||
let scModuleService: ISalesChannelModuleService
|
||||
let customerModule: ICustomerModuleService
|
||||
let productModule: IProductModuleService
|
||||
let pricingModule: IPricingModuleService
|
||||
let remoteLink
|
||||
|
||||
let defaultRegion
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
||||
regionModuleService = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||
scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL)
|
||||
customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER)
|
||||
productModule = appContainer.resolve(ModuleRegistrationName.PRODUCT)
|
||||
pricingModule = appContainer.resolve(ModuleRegistrationName.PRICING)
|
||||
remoteLink = appContainer.resolve("remoteLink")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await regionModuleService.createDefaultCountries()
|
||||
|
||||
// Here, so we don't have to create a region for each test
|
||||
defaultRegion = await regionModuleService.create({
|
||||
name: "Default Region",
|
||||
currency_code: "dkk",
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
describe("CreateCartWorkflow", () => {
|
||||
it("should create a cart", async () => {
|
||||
const region = await regionModuleService.create({
|
||||
name: "US",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const { result } = await createCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
email: "tony@stark.com",
|
||||
currency_code: "usd",
|
||||
region_id: region.id,
|
||||
sales_channel_id: salesChannel.id,
|
||||
items: [
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.retrieve(result.id, {
|
||||
relations: ["items"],
|
||||
})
|
||||
|
||||
expect(cart).toEqual(
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
email: "tony@stark.com",
|
||||
region_id: region.id,
|
||||
sales_channel_id: salesChannel.id,
|
||||
customer_id: expect.any(String),
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
quantity: 1,
|
||||
unit_price: 3000,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw when no regions exist", async () => {
|
||||
await regionModuleService.delete(defaultRegion.id)
|
||||
|
||||
const { errors } = await createCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
email: "tony@stark.com",
|
||||
currency_code: "usd",
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "find-one-or-any-region",
|
||||
handlerType: "invoke",
|
||||
error: new Error("No regions found"),
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it("should throw if sales channel is disabled", async () => {
|
||||
const api = useApi() as any
|
||||
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
is_disabled: true,
|
||||
})
|
||||
|
||||
const { errors } = await createCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
sales_channel_id: salesChannel.id,
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "find-sales-channel",
|
||||
handlerType: "invoke",
|
||||
error: new Error(
|
||||
`Unable to assign cart to disabled Sales Channel: Webshop`
|
||||
),
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
describe("compensation", () => {
|
||||
it("should delete created customer if cart-creation fails", async () => {
|
||||
expect.assertions(2)
|
||||
const workflow = createCartWorkflow(appContainer)
|
||||
|
||||
workflow.appendAction("throw", findOrCreateCustomerStepId, {
|
||||
invoke: async function failStep() {
|
||||
throw new Error(`Failed to create cart`)
|
||||
},
|
||||
})
|
||||
|
||||
const { errors } = await workflow.run({
|
||||
input: {
|
||||
currency_code: "usd",
|
||||
email: "tony@stark-industries.com",
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "throw",
|
||||
handlerType: "invoke",
|
||||
error: new Error(`Failed to create cart`),
|
||||
},
|
||||
])
|
||||
|
||||
const customers = await customerModule.list({
|
||||
email: "tony@stark-industries.com",
|
||||
})
|
||||
|
||||
expect(customers).toHaveLength(0)
|
||||
})
|
||||
|
||||
it("should not delete existing customer if cart-creation fails", async () => {
|
||||
expect.assertions(2)
|
||||
const workflow = createCartWorkflow(appContainer)
|
||||
|
||||
workflow.appendAction("throw", findOrCreateCustomerStepId, {
|
||||
invoke: async function failStep() {
|
||||
throw new Error(`Failed to create cart`)
|
||||
},
|
||||
})
|
||||
|
||||
const customer = await customerModule.create({
|
||||
email: "tony@stark-industries.com",
|
||||
})
|
||||
|
||||
const { errors } = await workflow.run({
|
||||
input: {
|
||||
currency_code: "usd",
|
||||
customer_id: customer.id,
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "throw",
|
||||
handlerType: "invoke",
|
||||
error: new Error(`Failed to create cart`),
|
||||
},
|
||||
])
|
||||
|
||||
const customers = await customerModule.list({
|
||||
email: "tony@stark-industries.com",
|
||||
})
|
||||
|
||||
expect(customers).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("AddToCartWorkflow", () => {
|
||||
it("should add item to cart", async () => {
|
||||
let cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
cart = await cartModuleService.retrieve(cart.id, {
|
||||
select: ["id", "region_id", "currency_code"],
|
||||
})
|
||||
|
||||
await addToCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
items: [
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
cart,
|
||||
},
|
||||
})
|
||||
|
||||
cart = await cartModuleService.retrieve(cart.id, {
|
||||
relations: ["items"],
|
||||
})
|
||||
|
||||
expect(cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
currency_code: "usd",
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
unit_price: 3000,
|
||||
quantity: 1,
|
||||
title: "Test variant",
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw if no price sets for variant exist", async () => {
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const { errors } = await addToCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
items: [
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
cart,
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "get-variant-price-sets",
|
||||
handlerType: "invoke",
|
||||
error: new Error(
|
||||
`Variants with IDs ${product.variants[0].id} do not have a price`
|
||||
),
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it("should throw if variant does not exist", async () => {
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const { errors } = await addToCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
items: [
|
||||
{
|
||||
variant_id: "prva_foo",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
cart,
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "validate-variants-exist",
|
||||
handlerType: "invoke",
|
||||
error: new Error(`Variants with IDs prva_foo do not exist`),
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("updateLineItemInCartWorkflow", () => {
|
||||
it("should update item in cart", async () => {
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
let cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
unit_price: 5000,
|
||||
title: "Test item",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
cart = await cartModuleService.retrieve(cart.id, {
|
||||
select: ["id", "region_id", "currency_code"],
|
||||
relations: ["items", "items.variant_id", "items.metadata"],
|
||||
})
|
||||
|
||||
const item = cart.items?.[0]!
|
||||
|
||||
await updateLineItemInCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
cart,
|
||||
item,
|
||||
update: {
|
||||
metadata: {
|
||||
foo: "bar",
|
||||
},
|
||||
quantity: 2,
|
||||
},
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
const updatedItem = await cartModuleService.retrieveLineItem(item.id)
|
||||
|
||||
expect(updatedItem).toEqual(
|
||||
expect.objectContaining({
|
||||
id: item.id,
|
||||
unit_price: 3000,
|
||||
quantity: 2,
|
||||
title: "Test item",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
describe("compensation", () => {
|
||||
it("should revert line item update to original state", async () => {
|
||||
expect.assertions(2)
|
||||
const workflow = updateLineItemInCartWorkflow(appContainer)
|
||||
|
||||
workflow.appendAction("throw", updateLineItemsStepId, {
|
||||
invoke: async function failStep() {
|
||||
throw new Error(`Failed to update something after line items`)
|
||||
},
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
let cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
unit_price: 3000,
|
||||
title: "Test item",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
cart = await cartModuleService.retrieve(cart.id, {
|
||||
select: ["id", "region_id", "currency_code"],
|
||||
relations: ["items", "items.variant_id", "items.metadata"],
|
||||
})
|
||||
|
||||
const item = cart.items?.[0]!
|
||||
|
||||
const { errors } = await workflow.run({
|
||||
input: {
|
||||
cart,
|
||||
item,
|
||||
update: {
|
||||
metadata: {
|
||||
foo: "bar",
|
||||
},
|
||||
title: "Test item updated",
|
||||
quantity: 2,
|
||||
},
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "throw",
|
||||
handlerType: "invoke",
|
||||
error: new Error(`Failed to update something after line items`),
|
||||
},
|
||||
])
|
||||
|
||||
const updatedItem = await cartModuleService.retrieveLineItem(item.id)
|
||||
|
||||
expect(updatedItem).toEqual(
|
||||
expect.objectContaining({
|
||||
id: item.id,
|
||||
unit_price: 3000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("deleteLineItems", () => {
|
||||
it("should delete items in cart", async () => {
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
{
|
||||
quantity: 1,
|
||||
unit_price: 5000,
|
||||
title: "Test item",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const items = await cartModuleService.listLineItems({ cart_id: cart.id })
|
||||
|
||||
await deleteLineItemsWorkflow(appContainer).run({
|
||||
input: {
|
||||
ids: items.map((i) => i.id),
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
const [deletedItem] = await cartModuleService.listLineItems({
|
||||
id: items.map((i) => i.id),
|
||||
})
|
||||
|
||||
expect(deletedItem).toBeUndefined()
|
||||
})
|
||||
|
||||
describe("compensation", () => {
|
||||
it("should restore line item if delete fails", async () => {
|
||||
const workflow = deleteLineItemsWorkflow(appContainer)
|
||||
|
||||
workflow.appendAction("throw", deleteLineItemsStepId, {
|
||||
invoke: async function failStep() {
|
||||
throw new Error(`Failed to do something after deleting line items`)
|
||||
},
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
{
|
||||
quantity: 1,
|
||||
unit_price: 3000,
|
||||
title: "Test item",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const items = await cartModuleService.listLineItems({
|
||||
cart_id: cart.id,
|
||||
})
|
||||
|
||||
const { errors } = await workflow.run({
|
||||
input: {
|
||||
ids: items.map((i) => i.id),
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "throw",
|
||||
handlerType: "invoke",
|
||||
error: new Error(
|
||||
`Failed to do something after deleting line items`
|
||||
),
|
||||
},
|
||||
])
|
||||
|
||||
const updatedItem = await cartModuleService.retrieveLineItem(
|
||||
items[0].id
|
||||
)
|
||||
|
||||
expect(updatedItem).not.toBeUndefined()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,673 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
ICartModuleService,
|
||||
ICustomerModuleService,
|
||||
IPricingModuleService,
|
||||
IProductModuleService,
|
||||
IPromotionModuleService,
|
||||
IRegionModuleService,
|
||||
ISalesChannelModuleService,
|
||||
} from "@medusajs/types"
|
||||
import { PromotionRuleOperator, PromotionType } from "@medusajs/utils"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("Store Carts API", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let cartModuleService: ICartModuleService
|
||||
let regionModuleService: IRegionModuleService
|
||||
let scModuleService: ISalesChannelModuleService
|
||||
let customerModule: ICustomerModuleService
|
||||
let productModule: IProductModuleService
|
||||
let pricingModule: IPricingModuleService
|
||||
let remoteLink
|
||||
let promotionModule: IPromotionModuleService
|
||||
|
||||
let defaultRegion
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
||||
regionModuleService = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||
scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL)
|
||||
customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER)
|
||||
productModule = appContainer.resolve(ModuleRegistrationName.PRODUCT)
|
||||
pricingModule = appContainer.resolve(ModuleRegistrationName.PRICING)
|
||||
remoteLink = appContainer.resolve("remoteLink")
|
||||
promotionModule = appContainer.resolve(ModuleRegistrationName.PROMOTION)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await regionModuleService.createDefaultCountries()
|
||||
|
||||
// Here, so we don't have to create a region for each test
|
||||
defaultRegion = await regionModuleService.create({
|
||||
name: "Default Region",
|
||||
currency_code: "dkk",
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
describe("POST /store/carts", () => {
|
||||
it("should create a cart", async () => {
|
||||
const region = await regionModuleService.create({
|
||||
name: "US",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const [priceSet, priceSetTwo] = await pricingModule.create([
|
||||
{
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
prices: [
|
||||
{
|
||||
amount: 4000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
productService: {
|
||||
variant_id: product.variants[1].id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSetTwo.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const created = await api.post(`/store/carts`, {
|
||||
email: "tony@stark.com",
|
||||
currency_code: "usd",
|
||||
region_id: region.id,
|
||||
sales_channel_id: salesChannel.id,
|
||||
items: [
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
},
|
||||
{
|
||||
variant_id: product.variants[1].id,
|
||||
quantity: 2,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(created.status).toEqual(200)
|
||||
expect(created.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: created.data.cart.id,
|
||||
currency_code: "usd",
|
||||
email: "tony@stark.com",
|
||||
region: expect.objectContaining({
|
||||
id: region.id,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
sales_channel_id: salesChannel.id,
|
||||
customer: expect.objectContaining({
|
||||
email: "tony@stark.com",
|
||||
}),
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
quantity: 1,
|
||||
unit_price: 3000,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
quantity: 2,
|
||||
unit_price: 4000,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create cart with customer from email", async () => {
|
||||
const api = useApi() as any
|
||||
|
||||
const created = await api.post(`/store/carts`, {
|
||||
currency_code: "usd",
|
||||
email: "tony@stark-industries.com",
|
||||
})
|
||||
|
||||
expect(created.status).toEqual(200)
|
||||
expect(created.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: created.data.cart.id,
|
||||
currency_code: "usd",
|
||||
email: "tony@stark-industries.com",
|
||||
customer: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
email: "tony@stark-industries.com",
|
||||
}),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create cart with any region", async () => {
|
||||
await regionModuleService.create({
|
||||
name: "US",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(`/store/carts`, {
|
||||
email: "tony@stark.com",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: response.data.cart.id,
|
||||
currency_code: "usd",
|
||||
email: "tony@stark.com",
|
||||
region: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create cart with region currency code", async () => {
|
||||
const region = await regionModuleService.create({
|
||||
name: "US",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(`/store/carts`, {
|
||||
email: "tony@stark.com",
|
||||
region_id: region.id,
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: response.data.cart.id,
|
||||
currency_code: "usd",
|
||||
email: "tony@stark.com",
|
||||
region: expect.objectContaining({
|
||||
id: region.id,
|
||||
}),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create cart with logged-in customer", async () => {
|
||||
const { customer, jwt } = await createAuthenticatedCustomer(appContainer)
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/store/carts`,
|
||||
{},
|
||||
{
|
||||
headers: { authorization: `Bearer ${jwt}` },
|
||||
}
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: response.data.cart.id,
|
||||
currency_code: "dkk",
|
||||
email: customer.email,
|
||||
customer: expect.objectContaining({
|
||||
id: customer.id,
|
||||
email: customer.email,
|
||||
}),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should respond 400 bad request on unknown props", async () => {
|
||||
const api = useApi() as any
|
||||
|
||||
await expect(
|
||||
api.post(`/store/carts`, {
|
||||
foo: "bar",
|
||||
})
|
||||
).rejects.toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id", () => {
|
||||
it("should update a cart with promo codes with a replace action", async () => {
|
||||
const targetRules = [
|
||||
{
|
||||
attribute: "product_id",
|
||||
operator: PromotionRuleOperator.IN,
|
||||
values: ["prod_tshirt"],
|
||||
},
|
||||
]
|
||||
|
||||
const appliedPromotion = await promotionModule.create({
|
||||
code: "PROMOTION_APPLIED",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "each",
|
||||
value: "300",
|
||||
apply_to_quantity: 1,
|
||||
max_quantity: 1,
|
||||
target_rules: targetRules,
|
||||
},
|
||||
})
|
||||
|
||||
const createdPromotion = await promotionModule.create({
|
||||
code: "PROMOTION_TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "across",
|
||||
value: "1000",
|
||||
apply_to_quantity: 1,
|
||||
target_rules: targetRules,
|
||||
},
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
email: "tony@stark.com",
|
||||
items: [
|
||||
{
|
||||
id: "item-1",
|
||||
unit_price: 2000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_tshirt",
|
||||
} as any,
|
||||
],
|
||||
})
|
||||
|
||||
const [adjustment] = await cartModuleService.addLineItemAdjustments([
|
||||
{
|
||||
code: appliedPromotion.code!,
|
||||
amount: 300,
|
||||
item_id: "item-1",
|
||||
promotion_id: appliedPromotion.id,
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
// Should remove earlier adjustments from other promocodes
|
||||
let updated = await api.post(`/store/carts/${cart.id}`, {
|
||||
promo_codes: [createdPromotion.code],
|
||||
})
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
items: [
|
||||
expect.objectContaining({
|
||||
id: "item-1",
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
id: expect.not.stringContaining(adjustment.id),
|
||||
code: createdPromotion.code,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
// Should remove all adjustments from other promo codes
|
||||
updated = await api.post(`/store/carts/${cart.id}`, {
|
||||
promo_codes: [],
|
||||
})
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
items: [
|
||||
expect.objectContaining({
|
||||
id: "item-1",
|
||||
adjustments: [],
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update a cart's region, sales channel and customer data", async () => {
|
||||
const region = await regionModuleService.create({
|
||||
name: "US",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "eur",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
let updated = await api.post(`/store/carts/${cart.id}`, {
|
||||
region_id: region.id,
|
||||
email: "tony@stark.com",
|
||||
sales_channel_id: salesChannel.id,
|
||||
})
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
currency_code: "usd",
|
||||
region: expect.objectContaining({
|
||||
id: region.id,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
email: "tony@stark.com",
|
||||
customer: expect.objectContaining({
|
||||
email: "tony@stark.com",
|
||||
}),
|
||||
sales_channel_id: salesChannel.id,
|
||||
})
|
||||
)
|
||||
|
||||
updated = await api.post(`/store/carts/${cart.id}`, {
|
||||
email: null,
|
||||
sales_channel_id: null,
|
||||
})
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
currency_code: "usd",
|
||||
email: null,
|
||||
customer_id: null,
|
||||
region: expect.objectContaining({
|
||||
id: region.id,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
sales_channel_id: null,
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("GET /store/carts/:id", () => {
|
||||
it("should create and update a cart", async () => {
|
||||
const region = await regionModuleService.create({
|
||||
name: "US",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const created = await api.post(`/store/carts`, {
|
||||
email: "tony@stark.com",
|
||||
currency_code: "usd",
|
||||
region_id: region.id,
|
||||
sales_channel_id: salesChannel.id,
|
||||
})
|
||||
|
||||
expect(created.status).toEqual(200)
|
||||
expect(created.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: created.data.cart.id,
|
||||
currency_code: "usd",
|
||||
email: "tony@stark.com",
|
||||
region: expect.objectContaining({
|
||||
id: region.id,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
sales_channel_id: salesChannel.id,
|
||||
})
|
||||
)
|
||||
|
||||
const updated = await api.post(`/store/carts/${created.data.cart.id}`, {
|
||||
email: "tony@stark-industries.com",
|
||||
})
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: updated.data.cart.id,
|
||||
currency_code: "usd",
|
||||
email: "tony@stark-industries.com",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("GET /store/carts", () => {
|
||||
it("should get cart", async () => {
|
||||
const region = await regionModuleService.create({
|
||||
name: "US",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
{
|
||||
unit_price: 1000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
},
|
||||
],
|
||||
region_id: region.id,
|
||||
sales_channel_id: salesChannel.id,
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/store/carts/${cart.id}`)
|
||||
|
||||
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: 1000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
}),
|
||||
]),
|
||||
region: expect.objectContaining({
|
||||
id: region.id,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
sales_channel_id: salesChannel.id,
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id/line-items", () => {
|
||||
it("should add item to cart", async () => {
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
{
|
||||
id: "item-1",
|
||||
unit_price: 2000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_mat",
|
||||
} as any,
|
||||
],
|
||||
})
|
||||
|
||||
const appliedPromotion = await promotionModule.create({
|
||||
code: "PROMOTION_APPLIED",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "across",
|
||||
value: "300",
|
||||
apply_to_quantity: 2,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "product_id",
|
||||
operator: "in",
|
||||
values: ["prod_mat", product.id],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const [lineItemAdjustment] =
|
||||
await cartModuleService.addLineItemAdjustments([
|
||||
{
|
||||
code: appliedPromotion.code!,
|
||||
amount: 300,
|
||||
item_id: "item-1",
|
||||
promotion_id: appliedPromotion.id,
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
})
|
||||
|
||||
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,
|
||||
quantity: 1,
|
||||
title: "Test variant",
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
code: "PROMOTION_APPLIED",
|
||||
amount: 180,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
expect.objectContaining({
|
||||
unit_price: 2000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
id: expect.not.stringContaining(lineItemAdjustment.id),
|
||||
code: "PROMOTION_APPLIED",
|
||||
amount: 120,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,300 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { ICartModuleService, IPromotionModuleService } from "@medusajs/types"
|
||||
import { PromotionType } from "@medusajs/utils"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("Store Carts API: Remove promotions from cart", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let cartModuleService: ICartModuleService
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
describe("DELETE /store/carts/:id/promotions", () => {
|
||||
it("should remove line item adjustments from a cart based on promotions", async () => {
|
||||
const appliedPromotion = await promotionModuleService.create({
|
||||
code: "PROMOTION_APPLIED",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "each",
|
||||
value: "300",
|
||||
apply_to_quantity: 1,
|
||||
max_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "product_id",
|
||||
operator: "eq",
|
||||
values: "prod_tshirt",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const appliedPromotionToRemove = await promotionModuleService.create({
|
||||
code: "PROMOTION_APPLIED_TO_REMOVE",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "each",
|
||||
value: "300",
|
||||
apply_to_quantity: 1,
|
||||
max_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "product_id",
|
||||
operator: "eq",
|
||||
values: "prod_tshirt",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
{
|
||||
id: "item-1",
|
||||
unit_price: 2000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_mat",
|
||||
} as any,
|
||||
{
|
||||
id: "item-2",
|
||||
unit_price: 1000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_tshirt",
|
||||
} as any,
|
||||
],
|
||||
})
|
||||
|
||||
const [adjustment1, adjustment2] =
|
||||
await cartModuleService.addLineItemAdjustments([
|
||||
{
|
||||
code: appliedPromotion.code!,
|
||||
amount: 300,
|
||||
item_id: "item-2",
|
||||
promotion_id: appliedPromotionToRemove.id,
|
||||
},
|
||||
{
|
||||
code: appliedPromotionToRemove.code!,
|
||||
amount: 150,
|
||||
item_id: "item-1",
|
||||
promotion_id: appliedPromotionToRemove.id,
|
||||
},
|
||||
{
|
||||
code: appliedPromotionToRemove.code!,
|
||||
amount: 150,
|
||||
item_id: "item-2",
|
||||
promotion_id: appliedPromotionToRemove.id,
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const response = await api.delete(`/store/carts/${cart.id}/promotions`, {
|
||||
data: {
|
||||
promo_codes: [appliedPromotionToRemove.code],
|
||||
},
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "item-1",
|
||||
adjustments: [],
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "item-2",
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
amount: 300,
|
||||
code: appliedPromotion.code,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should add shipping method adjustments to a cart based on promotions", async () => {
|
||||
const appliedPromotion = await promotionModuleService.create({
|
||||
code: "PROMOTION_APPLIED",
|
||||
type: PromotionType.STANDARD,
|
||||
rules: [
|
||||
{
|
||||
attribute: "customer_id",
|
||||
operator: "in",
|
||||
values: ["cus_test"],
|
||||
},
|
||||
{
|
||||
attribute: "currency_code",
|
||||
operator: "in",
|
||||
values: ["eur"],
|
||||
},
|
||||
],
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "shipping_methods",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "name",
|
||||
operator: "in",
|
||||
values: ["express"],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const appliedPromotionToRemove = await promotionModuleService.create({
|
||||
code: "PROMOTION_APPLIED_TO_REMOVE",
|
||||
type: PromotionType.STANDARD,
|
||||
rules: [
|
||||
{
|
||||
attribute: "customer_id",
|
||||
operator: "in",
|
||||
values: ["cus_test"],
|
||||
},
|
||||
{
|
||||
attribute: "currency_code",
|
||||
operator: "in",
|
||||
values: ["eur"],
|
||||
},
|
||||
],
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "shipping_methods",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "name",
|
||||
operator: "in",
|
||||
values: ["express"],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
currency_code: "eur",
|
||||
customer_id: "cus_test",
|
||||
items: [
|
||||
{
|
||||
unit_price: 2000,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
product_id: "prod_mat",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const [express, standard] = await cartModuleService.addShippingMethods(
|
||||
cart.id,
|
||||
[
|
||||
{
|
||||
amount: 500,
|
||||
name: "express",
|
||||
},
|
||||
{
|
||||
amount: 500,
|
||||
name: "standard",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
await cartModuleService.addShippingMethodAdjustments(cart.id, [
|
||||
{
|
||||
shipping_method_id: express.id,
|
||||
amount: 100,
|
||||
code: appliedPromotion.code!,
|
||||
},
|
||||
{
|
||||
shipping_method_id: express.id,
|
||||
amount: 100,
|
||||
code: appliedPromotionToRemove.code!,
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const response = await api.delete(`/store/carts/${cart.id}/promotions`, {
|
||||
data: { promo_codes: [appliedPromotionToRemove.code] },
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
]),
|
||||
shipping_methods: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: express.id,
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
amount: 100,
|
||||
code: appliedPromotion.code,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: standard.id,
|
||||
adjustments: [],
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,67 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { ICurrencyModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { DataSource } from "typeorm"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("Currency - Admin", () => {
|
||||
let dbConnection: DataSource
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let service: ICurrencyModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
service = appContainer.resolve(ModuleRegistrationName.CURRENCY)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should correctly retrieve and list currencies", async () => {
|
||||
const api = useApi() as any
|
||||
const listResp = await api.get("/admin/currencies", adminHeaders)
|
||||
|
||||
expect(listResp.data.currencies).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
code: "aud",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
code: "cad",
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
const retrieveResp = await api.get(`/admin/currencies/aud`, adminHeaders)
|
||||
expect(retrieveResp.data.currency).toEqual(
|
||||
listResp.data.currencies.find((c) => c.code === "aud")
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,62 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { ICurrencyModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { DataSource } from "typeorm"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const storeHeaders = {
|
||||
headers: {},
|
||||
}
|
||||
|
||||
describe("Currency - Store", () => {
|
||||
let dbConnection: DataSource
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let service: ICurrencyModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
service = appContainer.resolve(ModuleRegistrationName.CURRENCY)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should correctly retrieve and list currencies", async () => {
|
||||
const api = useApi() as any
|
||||
const listResp = await api.get("/store/currencies", storeHeaders)
|
||||
|
||||
expect(listResp.data.currencies).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
code: "aud",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
code: "cad",
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
const retrieveResp = await api.get(`/store/currencies/aud`, storeHeaders)
|
||||
expect(retrieveResp.data.currency).toEqual(
|
||||
listResp.data.currencies.find((c) => c.code === "aud")
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,89 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/customer-groups/:id/customers/batch", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should batch add customers to a group", async () => {
|
||||
const api = useApi() as any
|
||||
|
||||
const group = await customerModuleService.createCustomerGroup({
|
||||
name: "VIP",
|
||||
})
|
||||
const customers = await customerModuleService.create([
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
},
|
||||
{
|
||||
first_name: "Test2",
|
||||
last_name: "Test2",
|
||||
},
|
||||
{
|
||||
first_name: "Test3",
|
||||
last_name: "Test3",
|
||||
},
|
||||
])
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/customer-groups/${group.id}/customers/batch`,
|
||||
{
|
||||
customer_ids: customers.map((c) => ({ id: c.id })),
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const updatedGroup = await customerModuleService.retrieveCustomerGroup(
|
||||
group.id,
|
||||
{
|
||||
relations: ["customers"],
|
||||
}
|
||||
)
|
||||
expect(updatedGroup.customers?.length).toEqual(3)
|
||||
})
|
||||
})
|
||||
@@ -1,93 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("DELETE /admin/customer-groups/:id/customers/remove", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should batch delete customers from a group", async () => {
|
||||
const api = useApi() as any
|
||||
|
||||
const group = await customerModuleService.createCustomerGroup({
|
||||
name: "VIP",
|
||||
})
|
||||
const customers = await customerModuleService.create([
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
},
|
||||
{
|
||||
first_name: "Test2",
|
||||
last_name: "Test2",
|
||||
},
|
||||
{
|
||||
first_name: "Test3",
|
||||
last_name: "Test3",
|
||||
},
|
||||
])
|
||||
|
||||
await customerModuleService.addCustomerToGroup(
|
||||
customers.map((c) => ({ customer_id: c.id, customer_group_id: group.id }))
|
||||
)
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/customer-groups/${group.id}/customers/remove`,
|
||||
{
|
||||
customer_ids: customers.map((c) => ({ id: c.id })),
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const updatedGroup = await customerModuleService.retrieveCustomerGroup(
|
||||
group.id,
|
||||
{
|
||||
relations: ["customers"],
|
||||
}
|
||||
)
|
||||
expect(updatedGroup.customers?.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -1,70 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/customer-groups", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
// await adminSeeder(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a customer group", async () => {
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customer-groups`,
|
||||
{
|
||||
name: "VIP",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer_group).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "VIP",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,69 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("DELETE /admin/customer-groups/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete a group", async () => {
|
||||
const group = await customerModuleService.createCustomerGroup({
|
||||
name: "VIP",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.delete(
|
||||
`/admin/customer-groups/${group.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const deletedCustomer = await customerModuleService.retrieveCustomerGroup(
|
||||
group.id,
|
||||
{ withDeleted: true }
|
||||
)
|
||||
expect(deletedCustomer.deleted_at).toBeTruthy()
|
||||
})
|
||||
})
|
||||
@@ -1,92 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/customer-groups/:id/customers", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get all customer groups and its count", async () => {
|
||||
const group = await customerModuleService.createCustomerGroup({
|
||||
name: "Test",
|
||||
})
|
||||
|
||||
const customers = await customerModuleService.create([
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
},
|
||||
{
|
||||
first_name: "Test2",
|
||||
last_name: "Test2",
|
||||
},
|
||||
])
|
||||
|
||||
// add to group
|
||||
|
||||
await customerModuleService.addCustomerToGroup(
|
||||
customers.map((c) => ({ customer_id: c.id, customer_group_id: group.id }))
|
||||
)
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/customer-groups/${group.id}/customers`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(2)
|
||||
expect(response.data.customers).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: customers[0].id,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: customers[1].id,
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,67 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/customer-groups", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get all customer groups and its count", async () => {
|
||||
await customerModuleService.createCustomerGroup({
|
||||
name: "Test",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/admin/customer-groups`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.customer_groups).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "Test",
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1,69 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/customer-groups/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should retrieve customer group", async () => {
|
||||
const group = await customerModuleService.createCustomerGroup({
|
||||
name: "Test",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/customer-groups/${group.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer_group).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "Test",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,72 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/customer-groups/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update a customer group", async () => {
|
||||
const customer = await customerModuleService.createCustomerGroup({
|
||||
name: "VIP",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customer-groups/${customer.id}`,
|
||||
{
|
||||
name: "regular",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer_group).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "regular",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,157 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/customers/:id/addresses", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a customer address", async () => {
|
||||
// Create a customer
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customers/${customer.id}/addresses`,
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.address).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
})
|
||||
)
|
||||
|
||||
const customerWithAddresses = await customerModuleService.retrieve(
|
||||
customer.id,
|
||||
{ relations: ["addresses"] }
|
||||
)
|
||||
|
||||
expect(customerWithAddresses.addresses?.length).toEqual(1)
|
||||
})
|
||||
|
||||
it("sets new shipping address as default and unsets the old one", async () => {
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
addresses: [
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
is_default_shipping: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customers/${customer.id}/addresses`,
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 2",
|
||||
is_default_shipping: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const [address] = await customerModuleService.listAddresses({
|
||||
customer_id: customer.id,
|
||||
is_default_shipping: true,
|
||||
})
|
||||
|
||||
expect(address.address_1).toEqual("Test street 2")
|
||||
})
|
||||
|
||||
it("sets new billing address as default and unsets the old one", async () => {
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
addresses: [
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
is_default_billing: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customers/${customer.id}/addresses`,
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 2",
|
||||
is_default_billing: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const [address] = await customerModuleService.listAddresses({
|
||||
customer_id: customer.id,
|
||||
is_default_billing: true,
|
||||
})
|
||||
|
||||
expect(address.address_1).toEqual("Test street 2")
|
||||
})
|
||||
})
|
||||
@@ -1,71 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/customers", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a customer", async () => {
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customers`,
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,77 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("DELETE /admin/customers/:id/addresses/:address_id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update a customer address", async () => {
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
})
|
||||
|
||||
const address = await customerModuleService.addAddresses({
|
||||
customer_id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.delete(
|
||||
`/admin/customers/${customer.id}/addresses/${address.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const updatedCustomer = await customerModuleService.retrieve(customer.id, {
|
||||
relations: ["addresses"],
|
||||
})
|
||||
|
||||
expect(updatedCustomer.addresses?.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -1,69 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("DELETE /admin/customers/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete a customer", async () => {
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.delete(
|
||||
`/admin/customers/${customer.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const deletedCustomer = await customerModuleService.retrieve(customer.id, {
|
||||
withDeleted: true,
|
||||
})
|
||||
expect(deletedCustomer.deleted_at).toBeTruthy()
|
||||
})
|
||||
})
|
||||
@@ -1,115 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/customers/:id/addresses", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get all customer addresses and its count", async () => {
|
||||
const [customer] = await customerModuleService.create([
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
email: "test@me.com",
|
||||
addresses: [
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
address_1: "Test street 1",
|
||||
},
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
address_1: "Test street 2",
|
||||
},
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
address_1: "Test street 3",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
first_name: "Test Test",
|
||||
last_name: "Test Test",
|
||||
addresses: [
|
||||
{
|
||||
first_name: "Test TEST",
|
||||
last_name: "Test TEST",
|
||||
address_1: "NOT street 1",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/customers/${customer.id}/addresses`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(3)
|
||||
expect(response.data.addresses).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
customer_id: customer.id,
|
||||
address_1: "Test street 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
customer_id: customer.id,
|
||||
address_1: "Test street 2",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
customer_id: customer.id,
|
||||
address_1: "Test street 3",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,123 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/customers", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get all customers and its count", async () => {
|
||||
await customerModuleService.create([
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
email: "test@me.com",
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/admin/customers`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.customers).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
email: "test@me.com",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should filter customers by last name", async () => {
|
||||
await customerModuleService.create([
|
||||
{
|
||||
first_name: "Jane",
|
||||
last_name: "Doe",
|
||||
email: "jane@me.com",
|
||||
},
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john@me.com",
|
||||
},
|
||||
{
|
||||
first_name: "LeBron",
|
||||
last_name: "James",
|
||||
email: "lebron@me.com",
|
||||
},
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Silver",
|
||||
email: "johns@me.com",
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/customers?last_name=Doe`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(2)
|
||||
expect(response.data.customers).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "Jane",
|
||||
last_name: "Doe",
|
||||
email: "jane@me.com",
|
||||
})
|
||||
)
|
||||
expect(response.data.customers).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john@me.com",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,166 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/customers/:id/addresses/:address_id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update a customer address", async () => {
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
})
|
||||
|
||||
const address = await customerModuleService.addAddresses({
|
||||
customer_id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customers/${customer.id}/addresses/${address.id}`,
|
||||
{
|
||||
first_name: "Jane",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.address).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "Jane",
|
||||
last_name: "Doe",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("updates a new address to be default and unsets old one", async () => {
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
})
|
||||
const [, address] = await customerModuleService.addAddresses([
|
||||
{
|
||||
customer_id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
is_default_shipping: true,
|
||||
},
|
||||
{
|
||||
customer_id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 2",
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customers/${customer.id}/addresses/${address.id}`,
|
||||
{
|
||||
first_name: "jane",
|
||||
is_default_shipping: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const [defaultAddress] = await customerModuleService.listAddresses({
|
||||
customer_id: customer.id,
|
||||
is_default_shipping: true,
|
||||
})
|
||||
|
||||
expect(defaultAddress.first_name).toEqual("jane")
|
||||
expect(defaultAddress.address_1).toEqual("Test street 2")
|
||||
})
|
||||
|
||||
// do the same as above but for billing address
|
||||
it("updates a new address to be default and unsets old one", async () => {
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
})
|
||||
const [, address] = await customerModuleService.addAddresses([
|
||||
{
|
||||
customer_id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
is_default_billing: true,
|
||||
},
|
||||
{
|
||||
customer_id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 2",
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customers/${customer.id}/addresses/${address.id}`,
|
||||
{
|
||||
first_name: "jane",
|
||||
is_default_billing: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const [defaultAddress] = await customerModuleService.listAddresses({
|
||||
customer_id: customer.id,
|
||||
is_default_billing: true,
|
||||
})
|
||||
|
||||
expect(defaultAddress.first_name).toEqual("jane")
|
||||
expect(defaultAddress.address_1).toEqual("Test street 2")
|
||||
})
|
||||
})
|
||||
@@ -1,74 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/customers/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update a customer", async () => {
|
||||
const customer = await customerModuleService.create({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/customers/${customer.id}`,
|
||||
{
|
||||
first_name: "Jane",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "Jane",
|
||||
last_name: "Doe",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,74 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("POST /store/customers/me/addresses", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a customer address", async () => {
|
||||
const { customer, jwt } = await createAuthenticatedCustomer(appContainer)
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/store/customers/me/addresses`,
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
},
|
||||
{ headers: { authorization: `Bearer ${jwt}` } }
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.address).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
customer_id: customer.id,
|
||||
})
|
||||
)
|
||||
|
||||
const customerWithAddresses = await customerModuleService.retrieve(
|
||||
customer.id,
|
||||
{ relations: ["addresses"] }
|
||||
)
|
||||
|
||||
expect(customerWithAddresses.addresses?.length).toEqual(1)
|
||||
})
|
||||
})
|
||||
@@ -1,82 +0,0 @@
|
||||
import { IAuthModuleService, ICustomerModuleService } from "@medusajs/types"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import jwt from "jsonwebtoken"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("POST /store/customers", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a customer", async () => {
|
||||
const authService: IAuthModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.AUTH
|
||||
)
|
||||
const { jwt_secret } = appContainer.resolve("configModule").projectConfig
|
||||
const authUser = await authService.create({
|
||||
entity_id: "store_user",
|
||||
provider: "emailpass",
|
||||
scope: "store",
|
||||
})
|
||||
|
||||
const token = jwt.sign(authUser, jwt_secret)
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/store/customers`,
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john@me.com",
|
||||
},
|
||||
{ headers: { authorization: `Bearer ${token}` } }
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john@me.com",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,90 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
describe("DELETE /store/customers/me/addresses/:address_id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete a customer address", async () => {
|
||||
const { customer, jwt } = await createAuthenticatedCustomer(appContainer)
|
||||
|
||||
const address = await customerModuleService.addAddresses({
|
||||
customer_id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.delete(
|
||||
`/store/customers/me/addresses/${address.id}`,
|
||||
{ headers: { authorization: `Bearer ${jwt}` } }
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const updatedCustomer = await customerModuleService.retrieve(customer.id, {
|
||||
relations: ["addresses"],
|
||||
})
|
||||
|
||||
expect(updatedCustomer.addresses?.length).toEqual(0)
|
||||
})
|
||||
|
||||
it("should fail to delete another customer's address", async () => {
|
||||
const { jwt } = await createAuthenticatedCustomer(appContainer)
|
||||
|
||||
const otherCustomer = await customerModuleService.create({
|
||||
first_name: "Jane",
|
||||
last_name: "Doe",
|
||||
})
|
||||
const address = await customerModuleService.addAddresses({
|
||||
customer_id: otherCustomer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api
|
||||
.delete(`/store/customers/me/addresses/${address.id}`, {
|
||||
headers: { authorization: `Bearer ${jwt}` },
|
||||
})
|
||||
.catch((e) => e.response)
|
||||
|
||||
expect(response.status).toEqual(404)
|
||||
})
|
||||
})
|
||||
@@ -1,60 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("GET /store/customers", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should retrieve auth user's customer", async () => {
|
||||
const { customer, jwt } = await createAuthenticatedCustomer(appContainer)
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/store/customers/me`, {
|
||||
headers: { authorization: `Bearer ${jwt}` },
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).toEqual(
|
||||
expect.objectContaining({
|
||||
id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john@me.com",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,109 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
jest.setTimeout(100000)
|
||||
|
||||
describe("GET /store/customers/me/addresses", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
try {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get all customer addresses and its count", async () => {
|
||||
const { customer, jwt } = await createAuthenticatedCustomer(appContainer)
|
||||
|
||||
await customerModuleService.addAddresses([
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
address_1: "Test street 1",
|
||||
customer_id: customer.id,
|
||||
},
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
address_1: "Test street 2",
|
||||
customer_id: customer.id,
|
||||
},
|
||||
{
|
||||
first_name: "Test",
|
||||
last_name: "Test",
|
||||
address_1: "Test street 3",
|
||||
customer_id: customer.id,
|
||||
},
|
||||
])
|
||||
|
||||
await customerModuleService.create({
|
||||
first_name: "Test Test",
|
||||
last_name: "Test Test",
|
||||
addresses: [
|
||||
{
|
||||
first_name: "Test TEST",
|
||||
last_name: "Test TEST",
|
||||
address_1: "NOT street 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/store/customers/me/addresses`, {
|
||||
headers: { authorization: `Bearer ${jwt}` },
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(3)
|
||||
expect(response.data.addresses).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
customer_id: customer.id,
|
||||
address_1: "Test street 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
customer_id: customer.id,
|
||||
address_1: "Test street 2",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
customer_id: customer.id,
|
||||
address_1: "Test street 3",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,97 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { ICustomerModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("POST /store/customers/:id/addresses/:address_id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let customerModuleService: ICustomerModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update a customer address", async () => {
|
||||
const { customer, jwt } = await createAuthenticatedCustomer(appContainer)
|
||||
|
||||
const address = await customerModuleService.addAddresses({
|
||||
customer_id: customer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/store/customers/me/addresses/${address.id}`,
|
||||
{
|
||||
first_name: "Jane",
|
||||
},
|
||||
{ headers: { authorization: `Bearer ${jwt}` } }
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.address).toEqual(
|
||||
expect.objectContaining({
|
||||
id: address.id,
|
||||
first_name: "Jane",
|
||||
last_name: "Doe",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should fail to update another customer's address", async () => {
|
||||
const { jwt } = await createAuthenticatedCustomer(appContainer)
|
||||
|
||||
const otherCustomer = await customerModuleService.create({
|
||||
first_name: "Jane",
|
||||
last_name: "Doe",
|
||||
})
|
||||
|
||||
const address = await customerModuleService.addAddresses({
|
||||
customer_id: otherCustomer.id,
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
address_1: "Test street 1",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api
|
||||
.post(
|
||||
`/store/customers/me/addresses/${address.id}`,
|
||||
{ first_name: "Jane" },
|
||||
{ headers: { authorization: `Bearer ${jwt}` } }
|
||||
)
|
||||
.catch((e) => e.response)
|
||||
|
||||
expect(response.status).toEqual(404)
|
||||
})
|
||||
})
|
||||
@@ -1,112 +0,0 @@
|
||||
import { IAuthModuleService, IUserModuleService } from "@medusajs/types"
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/invites/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should fail to accept an invite with an invalid invite token", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const authResponse = await api.post(`/auth/admin/emailpass`, {
|
||||
email: "potential_member@test.com",
|
||||
password: "supersecret",
|
||||
})
|
||||
|
||||
expect(authResponse.status).toEqual(200)
|
||||
const token = authResponse.data.token
|
||||
|
||||
const acceptResponse = await api
|
||||
.post(
|
||||
`/admin/invites/accept?token=${"non-existing-token"}`,
|
||||
{
|
||||
first_name: "John",
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(acceptResponse.response.status).toEqual(401)
|
||||
expect(acceptResponse.response.data.message).toEqual("Unauthorized")
|
||||
})
|
||||
|
||||
it("should accept an invite", async () => {
|
||||
const invite = await userModuleService.createInvites({
|
||||
email: "potential_member@test.com",
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const authResponse = await api.post(`/auth/admin/emailpass`, {
|
||||
email: "potential_member@test.com",
|
||||
password: "supersecret",
|
||||
})
|
||||
|
||||
expect(authResponse.status).toEqual(200)
|
||||
const token = authResponse.data.token
|
||||
|
||||
const acceptResponse = await api.post(
|
||||
`/admin/invites/accept?token=${invite.token}`,
|
||||
{
|
||||
first_name: "John",
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
expect(acceptResponse.status).toEqual(200)
|
||||
expect(acceptResponse.data.user).toEqual(
|
||||
expect.objectContaining({
|
||||
email: "potential_member@test.com",
|
||||
first_name: "John",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,56 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
import adminSeeder from "../../../helpers/admin-seeder"
|
||||
import { AxiosInstance } from "axios"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/invites", () => {
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("create an invite", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const body = {
|
||||
email: "test_member@test.com",
|
||||
}
|
||||
|
||||
const response = await api.post(`/admin/invites`, body, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
invite: expect.objectContaining(body),
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,77 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { IUserModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
import adminSeeder from "../../../helpers/admin-seeder"
|
||||
import { AxiosInstance } from "axios"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("DELETE /admin/invites/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete a single invite", async () => {
|
||||
const invite = await userModuleService.createInvites({
|
||||
email: "potential_member@test.com",
|
||||
token: "test",
|
||||
expires_at: new Date(),
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.delete(
|
||||
`/admin/invites/${invite.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
id: invite.id,
|
||||
object: "invite",
|
||||
deleted: true,
|
||||
})
|
||||
|
||||
const { response: deletedResponse } = await api
|
||||
.get(`/admin/invites/${invite.id}`, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(deletedResponse.status).toEqual(404)
|
||||
expect(deletedResponse.data.type).toEqual("not_found")
|
||||
})
|
||||
})
|
||||
@@ -1,70 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { IUserModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
import adminSeeder from "../../../helpers/admin-seeder"
|
||||
import { AxiosInstance } from "axios"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/invites", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should list invites", async () => {
|
||||
await userModuleService.createInvites({
|
||||
email: "potential_member@test.com",
|
||||
token: "test",
|
||||
expires_at: new Date(),
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.get(`/admin/invites`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
invites: [
|
||||
expect.objectContaining({ email: "potential_member@test.com" }),
|
||||
],
|
||||
count: 1,
|
||||
offset: 0,
|
||||
limit: 50,
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,67 +0,0 @@
|
||||
import { IAuthModuleService, IUserModuleService } from "@medusajs/types"
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/invites/:id/resend", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should resend a single invite", async () => {
|
||||
const invite = await userModuleService.createInvites({
|
||||
email: "potential_member@test.com",
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/invites/${invite.id}/resend`,
|
||||
{},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.invite.token).not.toEqual(invite.token)
|
||||
expect(response.data.invite).toEqual(
|
||||
expect.objectContaining({ email: "potential_member@test.com" })
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,62 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { IAuthModuleService, IUserModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
import { AxiosInstance } from "axios"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/invites/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should retrieve a single invite", async () => {
|
||||
const invite = await userModuleService.createInvites({
|
||||
email: "potential_member@test.com",
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.get(`/admin/invites/${invite.id}`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.invite).toEqual(
|
||||
expect.objectContaining({ email: "potential_member@test.com" })
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,164 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
ICartModuleService,
|
||||
ICustomerModuleService,
|
||||
IRegionModuleService,
|
||||
ISalesChannelModuleService,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("Cart links", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let cartModuleService: ICartModuleService
|
||||
let regionModule: IRegionModuleService
|
||||
let customerModule: ICustomerModuleService
|
||||
let scModuleService: ISalesChannelModuleService
|
||||
let remoteQuery
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
||||
regionModule = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||
customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER)
|
||||
scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL)
|
||||
regionModule = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||
remoteQuery = appContainer.resolve("remoteQuery")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
// @ts-ignore
|
||||
await regionModule.createDefaultCountries()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should query carts, sales channels, customers, regions with remote query", async () => {
|
||||
const region = await regionModule.create({
|
||||
name: "Region",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const customer = await customerModule.create({
|
||||
email: "tony@stark.com",
|
||||
})
|
||||
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
email: "tony@stark.com",
|
||||
currency_code: "usd",
|
||||
region_id: region.id,
|
||||
sales_channel_id: salesChannel.id,
|
||||
customer_id: customer.id,
|
||||
})
|
||||
|
||||
const carts = await remoteQuery({
|
||||
cart: {
|
||||
fields: ["id"],
|
||||
region: {
|
||||
fields: ["id"],
|
||||
},
|
||||
customer: {
|
||||
fields: ["id"],
|
||||
},
|
||||
sales_channel: {
|
||||
fields: ["id"],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const salesChannels = await remoteQuery({
|
||||
sales_channel: {
|
||||
fields: ["id"],
|
||||
carts: {
|
||||
fields: ["id"],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const customers = await remoteQuery({
|
||||
customer: {
|
||||
fields: ["id"],
|
||||
carts: {
|
||||
fields: ["id"],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const regions = await remoteQuery({
|
||||
region: {
|
||||
fields: ["id"],
|
||||
carts: {
|
||||
fields: ["id"],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(carts).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
customer: expect.objectContaining({ id: customer.id }),
|
||||
sales_channel: expect.objectContaining({ id: salesChannel.id }),
|
||||
region: expect.objectContaining({ id: region.id }),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(salesChannels).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: salesChannel.id,
|
||||
carts: expect.arrayContaining([
|
||||
expect.objectContaining({ id: cart.id }),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(customers).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: customer.id,
|
||||
carts: expect.arrayContaining([
|
||||
expect.objectContaining({ id: cart.id }),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(regions).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: region.id,
|
||||
carts: expect.arrayContaining([
|
||||
expect.objectContaining({ id: cart.id }),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,96 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { ICartModuleService, IRegionModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("Link: Cart Region", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let cartModuleService: ICartModuleService
|
||||
let regionModule: IRegionModuleService
|
||||
let remoteQuery
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
||||
regionModule = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||
remoteQuery = appContainer.resolve("remoteQuery")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
// @ts-ignore
|
||||
await regionModule.createDefaultCountries()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should query carts and regions with remote query", async () => {
|
||||
const region = await regionModule.create({
|
||||
name: "Region",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const cart = await cartModuleService.create({
|
||||
email: "tony@stark.com",
|
||||
currency_code: "usd",
|
||||
region_id: region.id,
|
||||
})
|
||||
|
||||
const carts = await remoteQuery({
|
||||
cart: {
|
||||
fields: ["id"],
|
||||
region: {
|
||||
fields: ["id"],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const regions = await remoteQuery({
|
||||
region: {
|
||||
fields: ["id"],
|
||||
carts: {
|
||||
fields: ["id"],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(carts).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: cart.id,
|
||||
region: expect.objectContaining({ id: region.id }),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(regions).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: region.id,
|
||||
carts: expect.arrayContaining([
|
||||
expect.objectContaining({ id: cart.id }),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,188 +0,0 @@
|
||||
import { initialize, runMigrations } from "@medusajs/link-modules"
|
||||
import { MedusaModule, ModuleJoinerConfig } from "@medusajs/modules-sdk"
|
||||
|
||||
jest.setTimeout(5000000)
|
||||
|
||||
const DB_HOST = process.env.DB_HOST
|
||||
const DB_USERNAME = process.env.DB_USERNAME
|
||||
const DB_PASSWORD = process.env.DB_PASSWORD
|
||||
const DB_NAME = process.env.DB_TEMP_NAME
|
||||
const DB_URL = `postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}/${DB_NAME}`
|
||||
|
||||
describe("Link Modules", () => {
|
||||
let links
|
||||
const linkDefinition: ModuleJoinerConfig[] = [
|
||||
{
|
||||
serviceName: "linkServiceName",
|
||||
isLink: true,
|
||||
databaseConfig: {
|
||||
tableName: "linkTableName",
|
||||
idPrefix: "prefix",
|
||||
extraFields: {
|
||||
extra_field: {
|
||||
type: "integer",
|
||||
defaultValue: "-1",
|
||||
},
|
||||
another_field: {
|
||||
type: "string",
|
||||
nullable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
relationships: [
|
||||
{
|
||||
serviceName: "moduleA",
|
||||
primaryKey: "id",
|
||||
foreignKey: "product_id",
|
||||
alias: "product",
|
||||
},
|
||||
{
|
||||
serviceName: "moduleB",
|
||||
primaryKey: "id",
|
||||
foreignKey: "inventory_item_id",
|
||||
alias: "inventory",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
const dbConfig = {
|
||||
database: {
|
||||
clientUrl: DB_URL,
|
||||
},
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.spyOn(MedusaModule, "getLoadedModules").mockImplementation((() => {
|
||||
return [{ moduleA: [{}] }, { moduleB: [{}] }]
|
||||
}) as any)
|
||||
|
||||
await runMigrations({ options: dbConfig }, linkDefinition)
|
||||
links = await initialize(dbConfig, linkDefinition)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("Should insert values in a declared link", async function () {
|
||||
// simple
|
||||
await links.linkServiceName.create("modA_id", "modB_id")
|
||||
|
||||
// extra fields
|
||||
await links.linkServiceName.create("123", "abc", {
|
||||
extra_field: 333,
|
||||
another_field: "value**",
|
||||
})
|
||||
|
||||
// bulk
|
||||
await links.linkServiceName.create([
|
||||
["111", "aaa", { another_field: "test" }],
|
||||
["222", "bbb"],
|
||||
["333", "ccc", { extra_field: 2 }],
|
||||
["444", "bbb"],
|
||||
])
|
||||
|
||||
const values = await links.linkServiceName.list()
|
||||
|
||||
expect(values).toEqual([
|
||||
{
|
||||
product_id: "modA_id",
|
||||
inventory_item_id: "modB_id",
|
||||
id: expect.stringMatching("prefix_.+"),
|
||||
extra_field: -1,
|
||||
another_field: null,
|
||||
created_at: expect.any(Date),
|
||||
updated_at: expect.any(Date),
|
||||
deleted_at: null,
|
||||
},
|
||||
expect.objectContaining({
|
||||
product_id: "123",
|
||||
inventory_item_id: "abc",
|
||||
id: expect.stringMatching("prefix_.+"),
|
||||
extra_field: 333,
|
||||
another_field: "value**",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
product_id: "111",
|
||||
inventory_item_id: "aaa",
|
||||
extra_field: -1,
|
||||
another_field: "test",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
product_id: "222",
|
||||
inventory_item_id: "bbb",
|
||||
extra_field: -1,
|
||||
another_field: null,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
product_id: "333",
|
||||
inventory_item_id: "ccc",
|
||||
id: expect.stringMatching("prefix_.+"),
|
||||
extra_field: 2,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
product_id: "444",
|
||||
inventory_item_id: "bbb",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("Should dismiss the link of a given pair of keys", async function () {
|
||||
// simple
|
||||
const dismissSingle = await links.linkServiceName.dismiss(
|
||||
"modA_id",
|
||||
"modB_id"
|
||||
)
|
||||
|
||||
// bulk
|
||||
const dismissMulti = await links.linkServiceName.dismiss([
|
||||
["111", "aaa"],
|
||||
["333", "ccc"],
|
||||
])
|
||||
|
||||
expect(dismissSingle).toEqual([
|
||||
expect.objectContaining({
|
||||
product_id: "modA_id",
|
||||
inventory_item_id: "modB_id",
|
||||
deleted_at: expect.any(Date),
|
||||
}),
|
||||
])
|
||||
|
||||
expect(dismissMulti).toEqual([
|
||||
expect.objectContaining({
|
||||
product_id: "111",
|
||||
inventory_item_id: "aaa",
|
||||
deleted_at: expect.any(Date),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
product_id: "333",
|
||||
inventory_item_id: "ccc",
|
||||
deleted_at: expect.any(Date),
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("Should delete all the links related to a given key", async function () {
|
||||
await links.linkServiceName.softDelete({
|
||||
inventory_item_id: "bbb",
|
||||
})
|
||||
|
||||
const values = await links.linkServiceName.list(
|
||||
{ inventory_item_id: "bbb" },
|
||||
{ withDeleted: true }
|
||||
)
|
||||
|
||||
expect(values).toEqual([
|
||||
expect.objectContaining({
|
||||
product_id: "222",
|
||||
inventory_item_id: "bbb",
|
||||
deleted_at: expect.any(Date),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
product_id: "444",
|
||||
inventory_item_id: "bbb",
|
||||
deleted_at: expect.any(Date),
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1,29 +0,0 @@
|
||||
import dbFactory from "./../../../environment-helpers/use-template-db"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("Standalone Modules", () => {
|
||||
beforeAll(async () => {
|
||||
const DB_HOST = process.env.DB_HOST
|
||||
const DB_USERNAME = process.env.DB_USERNAME
|
||||
const DB_PASSWORD = process.env.DB_PASSWORD
|
||||
const DB_NAME = process.env.DB_TEMP_NAME
|
||||
|
||||
process.env.POSTGRES_URL = `postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}/${DB_NAME}`
|
||||
await dbFactory.createFromTemplate(DB_NAME)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
process.env.POSTGRES_URL = undefined
|
||||
})
|
||||
|
||||
it("Should migrate database and initialize Product module using connection string from environment variable ", async function () {
|
||||
const { initialize, runMigrations } = require("@medusajs/product")
|
||||
await runMigrations()
|
||||
|
||||
const product = await initialize()
|
||||
const productList = await product.list()
|
||||
|
||||
expect(productList).toEqual(expect.arrayContaining([]))
|
||||
})
|
||||
})
|
||||
@@ -1,233 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("POST /admin/price-lists/:id/prices/batch", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update money amounts if variant id is present in prices", async () => {
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date().toISOString(),
|
||||
starts_at: new Date().toISOString(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
},
|
||||
])
|
||||
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
prices: [
|
||||
{
|
||||
variant_id: variant.id,
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
{
|
||||
amount: 6000,
|
||||
region_id: "test-region",
|
||||
variant_id: variant.id,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(
|
||||
`admin/price-lists/${priceList.id}/prices/batch`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
customer_groups: [],
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 6000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: "test-region",
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,191 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleCustomerGroupFactory,
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("POST /admin/price-lists", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
await simpleCustomerGroupFactory(dbConnection, {
|
||||
id: "customer-group-1",
|
||||
name: "Test Group",
|
||||
})
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create price list and money amounts", async () => {
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
customer_groups: [{ id: "customer-group-1" }],
|
||||
status: "active",
|
||||
starts_at: new Date(),
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||
|
||||
let response = await api.get(
|
||||
`/admin/price-lists/${result.data.price_list.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: null,
|
||||
customer_groups: [
|
||||
{
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "Test Group",
|
||||
metadata: null,
|
||||
},
|
||||
],
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 400,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,180 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
import { AxiosInstance } from "axios"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("DELETE /admin/price-lists/:id/products/:productId/batch", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant1
|
||||
let priceSet
|
||||
let priceListId
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant1 = product.variants[0]
|
||||
|
||||
priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant1.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
customer_groups: [],
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant1.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const priceListResult = await api.post(
|
||||
`admin/price-lists`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
priceListId = priceListResult.data.price_list.id
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete prices in batch based on product ids", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
let priceSetMoneyAmounts =
|
||||
await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_set_id: [priceSet.id],
|
||||
})
|
||||
expect(priceSetMoneyAmounts.length).toEqual(2)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}/products/prices/batch`,
|
||||
{
|
||||
headers: adminHeaders.headers,
|
||||
data: {
|
||||
product_ids: [product.id],
|
||||
},
|
||||
}
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
priceSetMoneyAmounts = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_set_id: [priceSet.id],
|
||||
})
|
||||
|
||||
expect(priceSetMoneyAmounts.length).toEqual(1)
|
||||
expect(priceSetMoneyAmounts).toEqual([
|
||||
expect.objectContaining({
|
||||
price_list: null,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should delete prices based on single product id", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
let priceSetMoneyAmounts =
|
||||
await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_set_id: [priceSet.id],
|
||||
})
|
||||
expect(priceSetMoneyAmounts.length).toEqual(2)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}/products/${product.id}/prices`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
priceSetMoneyAmounts = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_set_id: [priceSet.id],
|
||||
})
|
||||
|
||||
expect(priceSetMoneyAmounts.length).toEqual(1)
|
||||
expect(priceSetMoneyAmounts).toEqual([
|
||||
expect.objectContaining({
|
||||
price_list: null,
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1,131 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("DELETE /admin/price-lists/:id/variants/:variantId/prices", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete all prices based on product variant ids", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
customer_groups: [],
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||
const priceListId = result.data.price_list.id
|
||||
|
||||
let psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(1)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}/variants/${variant.id}/prices`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -1,145 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("DELETE /admin/price-lists/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete price list prices by money amount ids", async () => {
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
{
|
||||
amount: 4000,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const res = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||
|
||||
const priceListId = res.data.price_list.id
|
||||
let psmas = await pricingModuleService.listPriceSetMoneyAmounts(
|
||||
{
|
||||
price_list_id: [priceListId],
|
||||
},
|
||||
{ relations: ["money_amount"] }
|
||||
)
|
||||
|
||||
expect(psmas.length).toEqual(2)
|
||||
|
||||
const deletePrice = psmas[0].money_amount
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}/prices/batch`,
|
||||
{
|
||||
data: {
|
||||
price_ids: [deletePrice?.id],
|
||||
},
|
||||
...adminHeaders,
|
||||
}
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(1)
|
||||
})
|
||||
})
|
||||
@@ -1,144 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("DELETE /admin/price-lists/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete price list and money amounts", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
customer_groups: [],
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||
const priceListId = result.data.price_list.id
|
||||
|
||||
const getResponse = await api.get(
|
||||
`/admin/price-lists/${priceListId}`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(getResponse.status).toEqual(200)
|
||||
|
||||
let psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(1)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
const afterDelete = await api
|
||||
.get(`/admin/price-lists/${priceListId}`, adminHeaders)
|
||||
.catch((err) => {
|
||||
return err
|
||||
})
|
||||
expect(afterDelete.response.status).toEqual(404)
|
||||
|
||||
psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -1,203 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleProductFactory } from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("GET /admin/price-lists/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get price list and its money amounts with variants", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list 1",
|
||||
description: "test 1",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
customer_groups: [],
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when price list is not found", async () => {
|
||||
const api = useApi() as any
|
||||
|
||||
const error = await api
|
||||
.get(`/admin/price-lists/does-not-exist`, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toBe(404)
|
||||
expect(error.response.data).toEqual({
|
||||
type: "not_found",
|
||||
message: "Price list with id: does-not-exist was not found",
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,272 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleProductFactory } from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("GET /admin/price-lists/:id/products", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let product2
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
title: "uniquely fun product",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
|
||||
product2 = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant-2",
|
||||
title: "uniquely fun product 2",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-2", value: "test 2" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-2",
|
||||
title: "Test option 2",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should list all products in a price list", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
let response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}/products`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: expect.any(String),
|
||||
handle: expect.any(String),
|
||||
subtitle: null,
|
||||
description: null,
|
||||
is_giftcard: false,
|
||||
status: "draft",
|
||||
thumbnail: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
origin_country: null,
|
||||
hs_code: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
collection_id: null,
|
||||
collection: null,
|
||||
type_id: null,
|
||||
type: null,
|
||||
discountable: true,
|
||||
external_id: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
metadata: null,
|
||||
}),
|
||||
])
|
||||
|
||||
response = await api.get(
|
||||
`/admin/products?price_list_id[]=${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: expect.any(String),
|
||||
handle: expect.any(String),
|
||||
subtitle: null,
|
||||
description: null,
|
||||
is_giftcard: false,
|
||||
status: "draft",
|
||||
thumbnail: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
origin_country: null,
|
||||
hs_code: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
collection_id: null,
|
||||
collection: null,
|
||||
type_id: null,
|
||||
type: null,
|
||||
discountable: true,
|
||||
external_id: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
metadata: null,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should list all products constrained by search query in a price list", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
let response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}/products?q=shouldnotreturnanything`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(0)
|
||||
expect(response.data.products).toEqual([])
|
||||
|
||||
response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}/products?q=uniquely`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
])
|
||||
|
||||
response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}/products?q=`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1,169 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleProductFactory } from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("GET /admin/price-lists", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get price list and its money amounts with variants", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const response = await api.get(`/admin/price-lists`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.price_lists).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
customer_groups: [],
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1,280 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleCustomerGroupFactory,
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("POST /admin/price-lists/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let variant2
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
await simpleCustomerGroupFactory(dbConnection, {
|
||||
id: "customer-group-2",
|
||||
name: "Test Group 2",
|
||||
})
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
{
|
||||
options: [{ option_id: "test-product-option-2", value: "test 2" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
{
|
||||
id: "test-product-option-2",
|
||||
title: "Test option 2",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
variant2 = product.variants[1]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update price lists successfully with prices", async () => {
|
||||
const var2PriceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant2.id,
|
||||
prices: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
price_set_id: var2PriceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "new price list name",
|
||||
description: "new price list description",
|
||||
customer_groups: [{ id: "customer-group-2" }],
|
||||
prices: [
|
||||
{
|
||||
variant_id: variant.id,
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
{
|
||||
id: priceList?.price_set_money_amounts?.[0].money_amount?.id,
|
||||
amount: 6000,
|
||||
currency_code: "usd",
|
||||
variant_id: variant2.id,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "new price list name",
|
||||
description: "new price list description",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
customer_groups: [
|
||||
{
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "Test Group 2",
|
||||
metadata: null,
|
||||
},
|
||||
],
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: priceList.id,
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: variant.id,
|
||||
}),
|
||||
variant_id: variant.id,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 6000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: priceList.id,
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: variant2.id,
|
||||
}),
|
||||
variant_id: variant2.id,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should not delete customer groups if customer_groups is not passed as a param", async () => {
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant2.id,
|
||||
prices: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
status: PriceListStatus.DRAFT,
|
||||
rules: {
|
||||
customer_group_id: ["customer-group-2"],
|
||||
},
|
||||
prices: [],
|
||||
},
|
||||
])
|
||||
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
status: PriceListStatus.ACTIVE,
|
||||
}
|
||||
|
||||
await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
customer_groups: [
|
||||
{
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "Test Group 2",
|
||||
metadata: null,
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,287 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleCustomerFactory,
|
||||
simpleCustomerGroupFactory,
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("GET /store/products/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let priceSetId
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
status: "published",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
{
|
||||
amount: 4000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
priceSetId = priceSet.id
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get product and its prices from price-list created through the price list workflow", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const priceListResponse = await api.post(
|
||||
`/admin/price-lists`,
|
||||
{
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.SALE,
|
||||
prices: [
|
||||
{
|
||||
amount: 2500,
|
||||
currency_code: "usd",
|
||||
variant_id: variant.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
let response = await api.get(
|
||||
`/store/products/${product.id}?currency_code=usd`
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product.variants[0].prices).toHaveLength(2)
|
||||
expect(response.data.product.variants[0].prices).toEqual([
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 3000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: null,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 2500,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: priceListResponse.data.price_list.id,
|
||||
}),
|
||||
])
|
||||
expect(response.data.product.variants[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
original_price: 3000,
|
||||
calculated_price: 2500,
|
||||
calculated_price_type: "sale",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should not list prices from price-list with customer groups if not logged in", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const { id: customerGroupId } = await simpleCustomerGroupFactory(
|
||||
dbConnection
|
||||
)
|
||||
|
||||
const priceListResponse = await api.post(
|
||||
`/admin/price-lists`,
|
||||
{
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.SALE,
|
||||
prices: [
|
||||
{
|
||||
amount: 2500,
|
||||
currency_code: "usd",
|
||||
variant_id: variant.id,
|
||||
},
|
||||
],
|
||||
customer_groups: [{ id: customerGroupId }],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
let response = await api.get(
|
||||
`/store/products/${product.id}?currency_code=usd`
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product.variants[0].prices).toEqual([
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 3000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: null,
|
||||
}),
|
||||
])
|
||||
expect(response.data.product.variants[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
original_price: 3000,
|
||||
calculated_price: 3000,
|
||||
calculated_price_type: null,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should list prices from price-list with customer groups", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
await simpleCustomerFactory(dbConnection, {
|
||||
id: "test-customer-5-pl",
|
||||
email: "test5@email-pl.com",
|
||||
first_name: "John",
|
||||
last_name: "Deere",
|
||||
password_hash:
|
||||
"c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test"
|
||||
has_account: true,
|
||||
groups: [{ id: "customer-group-1" }],
|
||||
})
|
||||
|
||||
const authResponse = await api.post("/store/auth", {
|
||||
email: "test5@email-pl.com",
|
||||
password: "test",
|
||||
})
|
||||
|
||||
const [authCookie] = authResponse.headers["set-cookie"][0].split(";")
|
||||
|
||||
const priceListResponse = await api.post(
|
||||
`/admin/price-lists`,
|
||||
{
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.SALE,
|
||||
prices: [
|
||||
{
|
||||
amount: 2500,
|
||||
currency_code: "usd",
|
||||
variant_id: variant.id,
|
||||
},
|
||||
],
|
||||
customer_groups: [{ id: "customer-group-1" }],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
let response = await api.get(
|
||||
`/store/products/${product.id}?currency_code=usd`,
|
||||
{
|
||||
headers: {
|
||||
Cookie: authCookie,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product.variants[0].prices).toHaveLength(2)
|
||||
expect(response.data.product.variants[0].prices).toEqual([
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 3000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: null,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 2500,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: priceListResponse.data.price_list.id,
|
||||
}),
|
||||
])
|
||||
expect(response.data.product.variants[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
original_price: 3000,
|
||||
calculated_price: 2500,
|
||||
calculated_price_type: "sale",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,136 +0,0 @@
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
import { simpleCartFactory, simpleRegionFactory } from "../../../factories"
|
||||
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import adminSeeder from "../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../helpers/create-default-rule-types"
|
||||
|
||||
jest.setTimeout(5000000)
|
||||
|
||||
const DB_HOST = process.env.DB_HOST
|
||||
const DB_USERNAME = process.env.DB_USERNAME
|
||||
const DB_PASSWORD = process.env.DB_PASSWORD
|
||||
const DB_NAME = process.env.DB_TEMP_NAME
|
||||
const DB_URL = `postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}/${DB_NAME}`
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("Link Modules", () => {
|
||||
let medusaContainer
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
medusaContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createDefaultRuleTypes(medusaContainer)
|
||||
await adminSeeder(dbConnection)
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "region-1",
|
||||
currency_code: "usd",
|
||||
})
|
||||
})
|
||||
|
||||
describe("get product price", () => {
|
||||
let ruleType
|
||||
let priceSet
|
||||
let productId
|
||||
const cartId = "test-cart"
|
||||
beforeEach(async () => {
|
||||
const pricingModuleService = medusaContainer.resolve(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
await simpleCartFactory(dbConnection, { id: cartId, region: "region-1" })
|
||||
|
||||
const payload = {
|
||||
title: "Test",
|
||||
description: "test-product-description",
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
prices: [],
|
||||
options: [],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api.post("/admin/products", payload, adminHeaders)
|
||||
|
||||
productId = response.data.product.id
|
||||
const variant = response.data.product.variants[0]
|
||||
|
||||
ruleType = await pricingModuleService.createRuleTypes([
|
||||
{ name: "region_id", rule_attribute: "region_id" },
|
||||
])
|
||||
|
||||
priceSet = await pricingModuleService.create({
|
||||
rules: [{ rule_attribute: "region_id" }],
|
||||
prices: [
|
||||
{
|
||||
amount: 1000,
|
||||
currency_code: "usd",
|
||||
rules: { region_id: "region-1" },
|
||||
},
|
||||
{
|
||||
amount: 900,
|
||||
currency_code: "usd",
|
||||
rules: { region_id: "region-2" },
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const remoteLink = medusaContainer.resolve("remoteLink") as any
|
||||
|
||||
await remoteLink.create({
|
||||
productService: {
|
||||
variant_id: variant.id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("Should get prices declared in pricing module", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.get(
|
||||
`/store/products/${productId}?cart_id=${cartId}`
|
||||
)
|
||||
|
||||
expect(response.data.product.variants[0].prices).toEqual([
|
||||
expect.objectContaining({
|
||||
amount: 1000,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,204 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { ProductModuleService } from "@medusajs/product"
|
||||
import { PricingModuleService } from "@medusajs/pricing"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("POST /admin/products/:id/variants", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a product variant with its price sets and prices through the workflow", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant create",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
material: "boo",
|
||||
mid_code: "234asdfadsf",
|
||||
hs_code: "asdfasdf234",
|
||||
origin_country: "DE",
|
||||
sku: "asdf",
|
||||
ean: "234",
|
||||
upc: "234",
|
||||
barcode: "asdf",
|
||||
inventory_quantity: 234,
|
||||
manage_inventory: true,
|
||||
allow_backorder: true,
|
||||
weight: 234,
|
||||
width: 234,
|
||||
height: 234,
|
||||
length: 234,
|
||||
metadata: { asdf: "asdf" },
|
||||
options: [{ option_id: "test-product-option-1", value: "test option" }],
|
||||
}
|
||||
|
||||
let response = await api.post(
|
||||
`/admin/products/${product.id}/variants`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: "test variant create",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should compensate creating product variants when error throws in future step", async () => {
|
||||
jest
|
||||
.spyOn(PricingModuleService.prototype, "create")
|
||||
.mockImplementation(() => {
|
||||
throw new Error("Random Error")
|
||||
})
|
||||
|
||||
const productSpy = jest.spyOn(
|
||||
ProductModuleService.prototype,
|
||||
"deleteVariants"
|
||||
)
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant create",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
material: "boo",
|
||||
mid_code: "234asdfadsf",
|
||||
hs_code: "asdfasdf234",
|
||||
origin_country: "DE",
|
||||
sku: "asdf",
|
||||
ean: "234",
|
||||
upc: "234",
|
||||
barcode: "asdf",
|
||||
inventory_quantity: 234,
|
||||
manage_inventory: true,
|
||||
allow_backorder: true,
|
||||
weight: 234,
|
||||
width: 234,
|
||||
height: 234,
|
||||
length: 234,
|
||||
metadata: { asdf: "asdf" },
|
||||
options: [{ option_id: "test-product-option-1", value: "test option" }],
|
||||
}
|
||||
|
||||
await api
|
||||
.post(`/admin/products/${product.id}/variants`, data, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(productSpy).toBeCalledWith([expect.any(String)])
|
||||
|
||||
const getProductResponse = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(getProductResponse.data.product.variants).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
@@ -1,125 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { Region } from "@medusajs/medusa"
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { simpleSalesChannelFactory } from "../../../../factories"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("POST /admin/products", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await manager.insert(Region, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, { is_default: true })
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create prices with region_id and currency_code context", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const data = {
|
||||
title: "test product",
|
||||
options: [{ title: "test-option" }],
|
||||
variants: [
|
||||
{
|
||||
title: "test variant",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
options: [{ value: "test-option" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let response = await api.post(
|
||||
"/admin/products?relations=variants.prices",
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
product: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: "test product",
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: "test variant",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
})
|
||||
|
||||
const pricingModuleService: IPricingModuleService = appContainer.resolve(
|
||||
"pricingModuleService"
|
||||
)
|
||||
|
||||
const [_, count] = await pricingModuleService.listAndCount()
|
||||
expect(count).toEqual(1)
|
||||
})
|
||||
})
|
||||
@@ -1,471 +0,0 @@
|
||||
import fs from "fs/promises"
|
||||
import path, { resolve, sep } from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleSalesChannelFactory } from "../../../../factories"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import productSeeder from "../../../../helpers/product-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
|
||||
const setupServer = require("../../../../environment-helpers/setup-server")
|
||||
const userSeeder = require("../../../../helpers/user-seeder")
|
||||
|
||||
const adminReqConfig = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env: Record<any, any> = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
jest.setTimeout(180000)
|
||||
|
||||
describe.skip("Batch job of product-export type", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
let exportFilePath = ""
|
||||
let topDir = ""
|
||||
let shutdownServer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
medusaProcess = await setupServer({
|
||||
cwd,
|
||||
uploadDir: __dirname,
|
||||
env,
|
||||
verbose: true,
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
if (topDir !== "") {
|
||||
await fs.rm(resolve(__dirname, topDir), { recursive: true })
|
||||
}
|
||||
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
await medusaProcess.kill()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
const container = getContainer()
|
||||
await createDefaultRuleTypes(container)
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
await userSeeder(dbConnection)
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
id: "test-channel",
|
||||
is_default: true,
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
|
||||
// @ts-ignore
|
||||
try {
|
||||
const isFileExists = (await fs.stat(exportFilePath))?.isFile()
|
||||
|
||||
if (isFileExists) {
|
||||
const [, relativeRoot] = exportFilePath
|
||||
.replace(__dirname, "")
|
||||
.split(sep)
|
||||
|
||||
if ((await fs.stat(resolve(__dirname, relativeRoot)))?.isDirectory()) {
|
||||
topDir = relativeRoot
|
||||
}
|
||||
|
||||
await fs.unlink(exportFilePath)
|
||||
}
|
||||
} catch (err) {
|
||||
// noop
|
||||
}
|
||||
})
|
||||
|
||||
it("should export a csv file containing the expected products", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const productPayload = {
|
||||
title: "Test export product",
|
||||
description: "test-product-description",
|
||||
type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
sku: "test-variant-sku-product-export",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "usd",
|
||||
amount: 100,
|
||||
},
|
||||
{
|
||||
currency_code: "eur",
|
||||
amount: 45,
|
||||
},
|
||||
{
|
||||
currency_code: "dkk",
|
||||
amount: 30,
|
||||
},
|
||||
],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const createProductRes = await api.post(
|
||||
"/admin/products",
|
||||
productPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
const productId = createProductRes.data.product.id
|
||||
const variantId = createProductRes.data.product.variants[0].id
|
||||
|
||||
const batchPayload = {
|
||||
type: "product-export",
|
||||
context: {
|
||||
filterable_fields: {
|
||||
title: "Test export product",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const fileSize = (await fs.stat(exportFilePath)).size
|
||||
expect(batchJob.result?.file_size).toBe(fileSize)
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(1)
|
||||
|
||||
const lineColumn = lines[0].split(";")
|
||||
|
||||
expect(lineColumn[0]).toBe(productId)
|
||||
expect(lineColumn[2]).toBe(productPayload.title)
|
||||
expect(lineColumn[4]).toBe(productPayload.description)
|
||||
expect(lineColumn[23]).toBe(variantId)
|
||||
expect(lineColumn[24]).toBe(productPayload.variants[0].title)
|
||||
expect(lineColumn[25]).toBe(productPayload.variants[0].sku)
|
||||
})
|
||||
|
||||
it("should export a csv file containing the expected products including new line char in the cells", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const productPayload = {
|
||||
title: "Test export product",
|
||||
description: "test-product-description\ntest line 2",
|
||||
type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
sku: "test-variant-sku-product-export",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "usd",
|
||||
amount: 100,
|
||||
},
|
||||
{
|
||||
currency_code: "eur",
|
||||
amount: 45,
|
||||
},
|
||||
{
|
||||
currency_code: "dkk",
|
||||
amount: 30,
|
||||
},
|
||||
],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
const createProductRes = await api.post(
|
||||
"/admin/products",
|
||||
productPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const productId = createProductRes.data.product.id
|
||||
const variantId = createProductRes.data.product.variants[0].id
|
||||
|
||||
const batchPayload = {
|
||||
type: "product-export",
|
||||
context: {
|
||||
filterable_fields: {
|
||||
title: "Test export product",
|
||||
},
|
||||
},
|
||||
}
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const fileSize = (await fs.stat(exportFilePath)).size
|
||||
expect(batchJob.result?.file_size).toBe(fileSize)
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(1)
|
||||
|
||||
const lineColumn = lines[0].split(";")
|
||||
|
||||
expect(lineColumn[0]).toBe(productId)
|
||||
expect(lineColumn[2]).toBe(productPayload.title)
|
||||
expect(lineColumn[4]).toBe(`"${productPayload.description}"`)
|
||||
expect(lineColumn[23]).toBe(variantId)
|
||||
expect(lineColumn[24]).toBe(productPayload.variants[0].title)
|
||||
expect(lineColumn[25]).toBe(productPayload.variants[0].sku)
|
||||
})
|
||||
|
||||
it("should export a csv file containing a limited number of products", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const batchPayload = {
|
||||
type: "product-export",
|
||||
context: {
|
||||
batch_size: 1,
|
||||
filterable_fields: { collection_id: "test-collection" },
|
||||
order: "created_at",
|
||||
},
|
||||
}
|
||||
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(4)
|
||||
|
||||
const csvLine = lines[0].split(";")
|
||||
expect(csvLine[0]).toBe("test-product")
|
||||
})
|
||||
|
||||
it("should be able to import an exported csv file", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const batchPayload = {
|
||||
type: "product-export",
|
||||
context: {
|
||||
batch_size: 1,
|
||||
filterable_fields: { collection_id: "test-collection" },
|
||||
order: "created_at",
|
||||
},
|
||||
}
|
||||
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
let batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [header, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(4)
|
||||
|
||||
const csvLine = lines[0].split(";")
|
||||
expect(csvLine[0]).toBe("test-product")
|
||||
expect(csvLine[2]).toBe("Test product")
|
||||
|
||||
csvLine[2] = "Updated test product"
|
||||
lines.splice(0, 1, csvLine.join(";"))
|
||||
|
||||
await fs.writeFile(exportFilePath, [header, ...lines].join("\r\n"))
|
||||
|
||||
const importBatchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
{
|
||||
type: "product-import",
|
||||
context: {
|
||||
fileKey: exportFilePath,
|
||||
},
|
||||
},
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
batchJobId = importBatchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
shouldContinuePulling = true
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
const productsResponse = await api.get("/admin/products", adminReqConfig)
|
||||
expect(productsResponse.data.count).toBe(5)
|
||||
expect(productsResponse.data.products).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: csvLine[0],
|
||||
handle: csvLine[1],
|
||||
title: csvLine[2],
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,406 +0,0 @@
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleProductFactory } from "../../../../factories"
|
||||
import { simpleProductCollectionFactory } from "../../../../factories/simple-product-collection-factory"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import batchJobSeeder from "../../../../helpers/batch-job-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
|
||||
const setupServer = require("../../../../environment-helpers/setup-server")
|
||||
const userSeeder = require("../../../../helpers/user-seeder")
|
||||
|
||||
const adminReqConfig = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
function getImportFile() {
|
||||
return path.resolve("__tests__", "product", "admin", "product-import.csv")
|
||||
}
|
||||
|
||||
function copyTemplateFile() {
|
||||
const csvTemplate = path.resolve(
|
||||
"__tests__",
|
||||
"product",
|
||||
"admin",
|
||||
"product-import-template.csv"
|
||||
)
|
||||
const destination = getImportFile()
|
||||
|
||||
fs.copyFileSync(csvTemplate, destination)
|
||||
}
|
||||
|
||||
jest.setTimeout(1000000)
|
||||
|
||||
function cleanTempData() {
|
||||
// cleanup tmp ops files
|
||||
const opsFiles = path.resolve("__tests__", "product", "admin", "imports")
|
||||
|
||||
fs.rmSync(opsFiles, { recursive: true, force: true })
|
||||
}
|
||||
|
||||
const env: Record<any, any> = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("Product import batch job", () => {
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
let medusaProcess
|
||||
|
||||
const collectionHandle1 = "test-collection1"
|
||||
const collectionHandle2 = "test-collection2"
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
env.UPLOAD_DIR = __dirname
|
||||
|
||||
cleanTempData() // cleanup if previous process didn't manage to do it
|
||||
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
medusaProcess = await setupServer({
|
||||
cwd,
|
||||
uploadDir: __dirname,
|
||||
env,
|
||||
verbose: true,
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
cleanTempData()
|
||||
|
||||
await medusaProcess.kill()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
const container = getContainer()
|
||||
await createDefaultRuleTypes(container)
|
||||
await batchJobSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
await userSeeder(dbConnection)
|
||||
await simpleProductCollectionFactory(dbConnection, [
|
||||
{
|
||||
handle: collectionHandle1,
|
||||
},
|
||||
{
|
||||
handle: collectionHandle2,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should import a csv file", async () => {
|
||||
jest.setTimeout(1000000)
|
||||
const api = useApi()
|
||||
copyTemplateFile()
|
||||
|
||||
const existingProductToBeUpdated = await simpleProductFactory(
|
||||
dbConnection,
|
||||
{
|
||||
id: "existing-product-id",
|
||||
title: "Test product",
|
||||
options: [{ id: "opt-1-id", title: "Size" }],
|
||||
variants: [
|
||||
{
|
||||
id: "existing-variant-id",
|
||||
title: "Initial tile",
|
||||
sku: "test-sku-4",
|
||||
options: [
|
||||
{
|
||||
option_id: "opt-1-id",
|
||||
value: "Large",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
const response = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
{
|
||||
type: "product-import",
|
||||
context: {
|
||||
fileKey: "product-import.csv",
|
||||
},
|
||||
},
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
const batchJobId = response.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
const productsResponse = await api.get("/admin/products", adminReqConfig)
|
||||
expect(productsResponse.data.count).toBe(3)
|
||||
|
||||
expect(productsResponse.data.products).toEqual(
|
||||
expect.arrayContaining([
|
||||
// NEW PRODUCT
|
||||
expect.objectContaining({
|
||||
title: "Test product",
|
||||
description:
|
||||
"Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\\n100% organic cotton, soft and crisp to the touch. Made in Portugal.",
|
||||
handle: "test-product-product-1",
|
||||
is_giftcard: false,
|
||||
status: "draft",
|
||||
thumbnail: "test-image.png",
|
||||
variants: [
|
||||
// NEW VARIANT
|
||||
expect.objectContaining({
|
||||
title: "Test variant",
|
||||
sku: "test-sku-1",
|
||||
barcode: "test-barcode-1",
|
||||
ean: null,
|
||||
upc: null,
|
||||
// inventory_quantity: 10,
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
currency_code: "eur",
|
||||
amount: 100,
|
||||
region_id: "region-product-import-0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 110,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
currency_code: "dkk",
|
||||
amount: 130,
|
||||
region_id: "region-product-import-1",
|
||||
}),
|
||||
]),
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: "option 1 value red",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
value: "option 2 value 1",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
type: null,
|
||||
images: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
url: "test-image.png",
|
||||
}),
|
||||
]),
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
title: "test-option-1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "test-option-2",
|
||||
}),
|
||||
]),
|
||||
tags: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: "123_1",
|
||||
}),
|
||||
]),
|
||||
collection: expect.objectContaining({
|
||||
handle: collectionHandle1,
|
||||
}),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "Test product",
|
||||
description:
|
||||
"Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\\n100% organic cotton, soft and crisp to the touch. Made in Portugal.",
|
||||
handle: "test-product-product-1-1",
|
||||
is_giftcard: false,
|
||||
status: "draft",
|
||||
thumbnail: "test-image.png",
|
||||
variants: [
|
||||
// NEW VARIANT
|
||||
expect.objectContaining({
|
||||
title: "Test variant",
|
||||
sku: "test-sku-1-1",
|
||||
barcode: "test-barcode-1-1",
|
||||
ean: null,
|
||||
upc: null,
|
||||
// inventory_quantity: 10,
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
currency_code: "eur",
|
||||
amount: 100,
|
||||
region_id: "region-product-import-0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 110,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
currency_code: "dkk",
|
||||
amount: 130,
|
||||
region_id: "region-product-import-1",
|
||||
}),
|
||||
]),
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: "option 1 value red",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
value: "option 2 value 1",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
type: null,
|
||||
images: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
url: "test-image.png",
|
||||
}),
|
||||
]),
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
title: "test-option-1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "test-option-2",
|
||||
}),
|
||||
]),
|
||||
tags: [],
|
||||
collection: expect.objectContaining({
|
||||
handle: collectionHandle1,
|
||||
}),
|
||||
}),
|
||||
// // UPDATED PRODUCT
|
||||
expect.objectContaining({
|
||||
id: existingProductToBeUpdated?.id,
|
||||
title: "Test product",
|
||||
description: "test-product-description",
|
||||
handle: "test-product-product-2",
|
||||
is_giftcard: false,
|
||||
status: "draft",
|
||||
thumbnail: "test-image.png",
|
||||
profile_id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
// UPDATED VARIANT
|
||||
expect.objectContaining({
|
||||
id: "existing-variant-id",
|
||||
title: "Test variant changed",
|
||||
sku: "test-sku-4",
|
||||
barcode: "test-barcode-4",
|
||||
options: [
|
||||
expect.objectContaining({
|
||||
value: "Large",
|
||||
option_id: "opt-1-id",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
// CREATED VARIANT
|
||||
expect.objectContaining({
|
||||
title: "Test variant",
|
||||
product_id: existingProductToBeUpdated.id,
|
||||
sku: "test-sku-2",
|
||||
barcode: "test-barcode-2",
|
||||
ean: null,
|
||||
upc: null,
|
||||
// inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
currency_code: "dkk",
|
||||
amount: 110,
|
||||
region_id: "region-product-import-2",
|
||||
}),
|
||||
],
|
||||
options: [
|
||||
expect.objectContaining({
|
||||
value: "Small",
|
||||
option_id: "opt-1-id",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
// CREATED VARIANT
|
||||
expect.objectContaining({
|
||||
title: "Test variant",
|
||||
product_id: existingProductToBeUpdated.id,
|
||||
sku: "test-sku-3",
|
||||
barcode: "test-barcode-3",
|
||||
ean: null,
|
||||
upc: null,
|
||||
// inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 120,
|
||||
region_id: null,
|
||||
}),
|
||||
],
|
||||
options: [
|
||||
expect.objectContaining({
|
||||
value: "Medium",
|
||||
option_id: "opt-1-id",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
]),
|
||||
images: [
|
||||
expect.objectContaining({
|
||||
url: "test-image.png",
|
||||
}),
|
||||
],
|
||||
options: [
|
||||
expect.objectContaining({
|
||||
product_id: existingProductToBeUpdated.id,
|
||||
id: "opt-1-id",
|
||||
title: "Size",
|
||||
}),
|
||||
],
|
||||
type: expect.objectContaining({ value: "test-type" }),
|
||||
tags: [
|
||||
expect.objectContaining({
|
||||
value: "123",
|
||||
}),
|
||||
],
|
||||
collection: expect.objectContaining({
|
||||
handle: collectionHandle2,
|
||||
}),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,655 +0,0 @@
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import productSeeder from "../../../../helpers/product-seeder"
|
||||
|
||||
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
|
||||
import { MedusaV2Flag } from "@medusajs/utils"
|
||||
import { AxiosInstance } from "axios"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleSalesChannelFactory,
|
||||
} from "../../../../factories"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("/admin/products", () => {
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
let medusaContainer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env })
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
medusaContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
it("Should have loaded the product module", function () {
|
||||
const productRegistrationName =
|
||||
ModulesDefinition[Modules.PRODUCT].registrationName
|
||||
expect(
|
||||
medusaContainer.hasRegistration(productRegistrationName)
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should have enabled workflows feature flag", function () {
|
||||
const flagRouter = medusaContainer.resolve("featureFlagRouter")
|
||||
|
||||
const workflowsFlag = flagRouter.isFeatureEnabled(MedusaV2Flag.key)
|
||||
|
||||
expect(workflowsFlag).toBe(true)
|
||||
})
|
||||
|
||||
describe("POST /admin/products", () => {
|
||||
beforeEach(async () => {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(medusaContainer)
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "Default channel",
|
||||
id: "default-channel",
|
||||
is_default: true,
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a product", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test",
|
||||
description: "test-product-description",
|
||||
type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
prices: [
|
||||
{
|
||||
currency_code: "usd",
|
||||
amount: 100,
|
||||
},
|
||||
{
|
||||
currency_code: "eur",
|
||||
amount: 45,
|
||||
},
|
||||
{
|
||||
currency_code: "dkk",
|
||||
amount: 30,
|
||||
},
|
||||
],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^prod_*/),
|
||||
title: "Test",
|
||||
discountable: true,
|
||||
is_giftcard: false,
|
||||
handle: "test",
|
||||
status: "draft",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
profile_id: expect.stringMatching(/^sp_*/),
|
||||
images: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
url: "test-image.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
url: "test-image-2.png",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
]),
|
||||
thumbnail: "test-image.png",
|
||||
tags: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: "123",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: "456",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
]),
|
||||
type: expect.objectContaining({
|
||||
value: "test-type",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
collection: expect.objectContaining({
|
||||
id: "test-collection",
|
||||
title: "Test collection",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^opt_*/),
|
||||
product_id: expect.stringMatching(/^prod_*/),
|
||||
title: "size",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^opt_*/),
|
||||
product_id: expect.stringMatching(/^prod_*/),
|
||||
title: "color",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}),
|
||||
]),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^variant_*/),
|
||||
product_id: expect.stringMatching(/^prod_*/),
|
||||
updated_at: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
title: "Test variant",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^ma_*/),
|
||||
currency_code: "usd",
|
||||
amount: 100,
|
||||
// TODO: enable this in the Pricing Module PR
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^ma_*/),
|
||||
currency_code: "eur",
|
||||
amount: 45,
|
||||
// TODO: enable this in the Pricing Module PR
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^ma_*/),
|
||||
currency_code: "dkk",
|
||||
amount: 30,
|
||||
// TODO: enable this in the Pricing Module PR
|
||||
// created_at: expect.any(String),
|
||||
// updated_at: expect.any(String),
|
||||
// variant_id: expect.stringMatching(/^variant_*/),
|
||||
}),
|
||||
]),
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: "large",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
variant_id: expect.stringMatching(/^variant_*/),
|
||||
option_id: expect.stringMatching(/^opt_*/),
|
||||
id: expect.stringMatching(/^optval_*/),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
value: "green",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
variant_id: expect.stringMatching(/^variant_*/),
|
||||
option_id: expect.stringMatching(/^opt_*/),
|
||||
id: expect.stringMatching(/^optval_*/),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a product that is not discountable", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test",
|
||||
discountable: false,
|
||||
description: "test-product-description",
|
||||
type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
discountable: false,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should sets the variant ranks when creating a product", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test product - 1",
|
||||
description: "test-product-description 1",
|
||||
type: { value: "test-type 1" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant 1",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const creationResponse = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(creationResponse?.status).toEqual(200)
|
||||
|
||||
const productId = creationResponse?.data.product.id
|
||||
|
||||
const response = await api
|
||||
.get(`/admin/products/${productId}`, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test product - 1",
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
title: "Test variant 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "Test variant 2",
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a giftcard", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "Test Giftcard",
|
||||
is_giftcard: true,
|
||||
description: "test-giftcard-description",
|
||||
options: [{ title: "Denominations" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "100" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/products", payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "Test Giftcard",
|
||||
discountable: false,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create variants with inventory items", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/products`,
|
||||
{
|
||||
title: "Test product - 1",
|
||||
description: "test-product-description 1",
|
||||
type: { value: "test-type 1" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant 1",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
{
|
||||
title: "Test variant 2",
|
||||
inventory_quantity: 10,
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
{ headers: { "x-medusa-access-token": "test_token" } }
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const variantIds = response.data.product.variants.map(
|
||||
(v: { id: string }) => v.id
|
||||
)
|
||||
|
||||
const variantInventoryService = medusaContainer.resolve(
|
||||
"productVariantInventoryService"
|
||||
)
|
||||
const inventory = await variantInventoryService.listByVariant(variantIds)
|
||||
|
||||
expect(inventory).toHaveLength(2)
|
||||
expect(inventory).toContainEqual(
|
||||
expect.objectContaining({
|
||||
variant_id: variantIds[0],
|
||||
required_quantity: 1,
|
||||
})
|
||||
)
|
||||
expect(inventory).toContainEqual(
|
||||
expect.objectContaining({
|
||||
variant_id: variantIds[1],
|
||||
required_quantity: 1,
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/products/:id", () => {
|
||||
const toUpdateWithSalesChannels = "to-update-with-sales-channels"
|
||||
const toUpdateWithVariants = "to-update-with-variants"
|
||||
const toUpdate = "to-update"
|
||||
|
||||
beforeEach(async () => {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(medusaContainer)
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "Default channel",
|
||||
id: "default-channel",
|
||||
is_default: true,
|
||||
})
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "Channel 3",
|
||||
id: "channel-3",
|
||||
is_default: true,
|
||||
})
|
||||
|
||||
await simpleProductFactory(dbConnection, {
|
||||
title: "To update product",
|
||||
id: toUpdate,
|
||||
})
|
||||
|
||||
await simpleProductFactory(dbConnection, {
|
||||
title: "To update product with channels",
|
||||
id: toUpdateWithSalesChannels,
|
||||
sales_channels: [
|
||||
{ name: "channel 1", id: "channel-1" },
|
||||
{ name: "channel 2", id: "channel-2" },
|
||||
],
|
||||
})
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "To be added",
|
||||
id: "to-be-added",
|
||||
})
|
||||
|
||||
await simpleProductFactory(dbConnection, {
|
||||
title: "To update product with variants",
|
||||
id: toUpdateWithVariants,
|
||||
variants: [
|
||||
{
|
||||
id: "variant-1",
|
||||
title: "Variant 1",
|
||||
},
|
||||
{
|
||||
id: "variant-2",
|
||||
title: "Variant 2",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should do a basic product update", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post(`/admin/products/${toUpdate}`, payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: toUpdate,
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update product and also update a variant and create a variant", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
variants: [
|
||||
{
|
||||
id: "variant-1",
|
||||
title: "Variant 1 updated",
|
||||
},
|
||||
{
|
||||
title: "Variant 3",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post(`/admin/products/${toUpdateWithVariants}`, payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: toUpdateWithVariants,
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "variant-1",
|
||||
title: "Variant 1 updated",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "Variant 3",
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update product's sales channels", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const payload = {
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
sales_channels: [{ id: "channel-2" }, { id: "channel-3" }],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
`/admin/products/${toUpdateWithSalesChannels}?expand=sales_channels`,
|
||||
payload,
|
||||
adminHeaders
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: toUpdateWithSalesChannels,
|
||||
sales_channels: [
|
||||
expect.objectContaining({ id: "channel-2" }),
|
||||
expect.objectContaining({ id: "channel-3" }),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update inventory when variants are updated", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const variantInventoryService = medusaContainer.resolve(
|
||||
"productVariantInventoryService"
|
||||
)
|
||||
|
||||
const payload = {
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
variants: [
|
||||
{
|
||||
id: "variant-1",
|
||||
title: "Variant 1 updated",
|
||||
},
|
||||
{
|
||||
title: "Variant 3",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post(`/admin/products/${toUpdateWithVariants}`, payload, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
let inventory = await variantInventoryService.listInventoryItemsByVariant(
|
||||
"variant-2"
|
||||
)
|
||||
|
||||
expect(response?.status).toEqual(200)
|
||||
expect(response?.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: toUpdateWithVariants,
|
||||
title: "New title",
|
||||
description: "test-product-description",
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "variant-1",
|
||||
title: "Variant 1 updated",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "Variant 3",
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
expect(inventory).toEqual([]) // no inventory items for removed variant
|
||||
|
||||
inventory = await variantInventoryService.listInventoryItemsByVariant(
|
||||
response?.data.product.variants.find((v) => v.title === "Variant 3").id
|
||||
)
|
||||
|
||||
expect(inventory).toEqual([
|
||||
expect.objectContaining({ id: expect.any(String) }),
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,6 +0,0 @@
|
||||
Product Id,Product Handle,Product Title,Product Subtitle,Product Description,Product Status,Product Thumbnail,Product Weight,Product Length,Product Width,Product Height,Product HS Code,Product Origin Country,Product MID Code,Product Material,Product Collection Title,Product Collection Handle,Product Type,Product Tags,Product Discountable,Product External Id,Variant Id,Variant Title,Variant SKU,Variant Barcode,Variant Inventory Quantity,Variant Allow Backorder,Variant Manage Inventory,Variant Weight,Variant Length,Variant Width,Variant Height,Variant HS Code,Variant Origin Country,Variant MID Code,Variant Material,Price ImportLand [EUR],Price USD,Price denmark [DKK],Price Denmark [DKK],Option 1 Name,Option 1 Value,Option 2 Name,Option 2 Value,Image 1 Url
|
||||
,test-product-product-1,Test product,,"Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\n100% organic cotton, soft and crisp to the touch. Made in Portugal.",draft,,,,,,,,,,Test collection 1,test-collection1,,123_1,TRUE,,,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,1.30,,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png
|
||||
,test-product-product-1-1,Test product,,"Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\n100% organic cotton, soft and crisp to the touch. Made in Portugal.",draft,,,,,,,,,,Test collection 1,test-collection1,,,TRUE,,,Test variant,test-sku-1-1,test-barcode-1-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,1.30,,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png
|
||||
existing-product-id,test-product-product-2,Test product,,test-product-description,draft,test-image.png,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,,Test variant,test-sku-2,test-barcode-2,10,FALSE,TRUE,,,,,,,,,,,,1.10,Size,Small,,,test-image.png
|
||||
existing-product-id,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,,Test variant,test-sku-3,test-barcode-3,10,FALSE,TRUE,,,,,,,,,,1.20,,,Size,Medium,,,test-image.png
|
||||
existing-product-id,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,existing-variant-id,Test variant changed,test-sku-4,test-barcode-4,10,FALSE,TRUE,,,,,,,,,,,,,Size,Large,,,test-image.png
|
||||
|
@@ -1,482 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("POST /admin/products/:id/variants/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test 2" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create product variant price sets and prices", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant update",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let response = await api.post(
|
||||
`/admin/products/${product.id}/variants/${variant.id}`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
response = await api.get(`/admin/products/${product.id}`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update money amounts if money amount id is present in prices", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const moneyAmountToUpdate = priceSet.money_amounts?.[0]
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant update",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
id: moneyAmountToUpdate?.id,
|
||||
amount: 2222,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let response = await api.post(
|
||||
`/admin/products/${product.id}/variants/${variant.id}`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
response = await api.get(`/admin/products/${product.id}`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: moneyAmountToUpdate?.id,
|
||||
amount: 2222,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should add prices if price set is already present", async () => {
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [],
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant update",
|
||||
prices: [
|
||||
{
|
||||
amount: 123,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 456,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let response = await api.post(
|
||||
`/admin/products/${product.id}/variants/${variant.id}`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
response = await api.get(`/admin/products/${product.id}`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 123,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 456,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update variant option value", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const data = {
|
||||
options: [
|
||||
{
|
||||
option_id: "test-product-option-1",
|
||||
value: "updated",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(
|
||||
`/admin/products/${product.id}/variants/${variant.id}`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
options: [
|
||||
expect.objectContaining({
|
||||
option_id: "test-product-option-1",
|
||||
value: "updated",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: product.variants[1].id,
|
||||
options: [
|
||||
expect.objectContaining({
|
||||
option_id: "test-product-option-1",
|
||||
value: "test 2",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update variant metadata", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const data = {
|
||||
metadata: {
|
||||
test: "string",
|
||||
},
|
||||
}
|
||||
|
||||
await api.post(
|
||||
`/admin/products/${product.id}/variants/${variant.id}`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
metadata: {
|
||||
test: "string",
|
||||
},
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should remove options not present in update", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-multiple-options",
|
||||
variants: [
|
||||
{
|
||||
options: [
|
||||
{ option_id: "test-product-multi-option-1", value: "test" },
|
||||
{ option_id: "test-product-multi-option-2", value: "test value" },
|
||||
],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-multi-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
{
|
||||
id: "test-product-multi-option-2",
|
||||
title: "Test option 2",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
|
||||
const data = {
|
||||
options: [
|
||||
{
|
||||
option_id: "test-product-multi-option-1",
|
||||
value: "updated",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(
|
||||
`/admin/products/${product.id}/variants/${variant.id}`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
options: [
|
||||
expect.objectContaining({
|
||||
option_id: "test-product-multi-option-1",
|
||||
value: "updated",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update several options in the same api call", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-multiple-options",
|
||||
variants: [
|
||||
{
|
||||
options: [
|
||||
{ option_id: "test-product-multi-option-1", value: "test" },
|
||||
{ option_id: "test-product-multi-option-2", value: "test value" },
|
||||
],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-multi-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
{
|
||||
id: "test-product-multi-option-2",
|
||||
title: "Test option 2",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
|
||||
const data = {
|
||||
options: [
|
||||
{
|
||||
option_id: "test-product-multi-option-1",
|
||||
value: "updated",
|
||||
},
|
||||
{
|
||||
option_id: "test-product-multi-option-2",
|
||||
value: "updated 2",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(
|
||||
`/admin/products/${product.id}/variants/${variant.id}`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
options: [
|
||||
expect.objectContaining({
|
||||
option_id: "test-product-multi-option-1",
|
||||
value: "updated",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
option_id: "test-product-multi-option-2",
|
||||
value: "updated 2",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,279 +0,0 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleProductFactory } from "../../../../factories"
|
||||
|
||||
import { Region } from "@medusajs/medusa"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe.skip("POST /admin/products/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await manager.insert(Region, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update product variant price sets and prices", async () => {
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
title: "test product update",
|
||||
variants: [
|
||||
{
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(`/admin/products/${product.id}`, data, adminHeaders)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product.variants).toHaveLength(1)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update money amounts if money amount id is present in prices", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const moneyAmountToUpdate = priceSet.money_amounts?.[0]
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
title: "test product update",
|
||||
variants: [
|
||||
{
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
id: moneyAmountToUpdate?.id,
|
||||
amount: 2222,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(`/admin/products/${product.id}`, data, adminHeaders)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: moneyAmountToUpdate?.id,
|
||||
amount: 2222,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should add prices if price set is already present", async () => {
|
||||
const remoteLink = appContainer.resolve("remoteLink")
|
||||
const pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
|
||||
const priceSet = await pricingModuleService.create({
|
||||
rules: [{ rule_attribute: "region_id" }],
|
||||
prices: [],
|
||||
})
|
||||
|
||||
await remoteLink.create({
|
||||
productService: {
|
||||
variant_id: variant.id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const data = {
|
||||
title: "test product update",
|
||||
variants: [
|
||||
{
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: [
|
||||
{
|
||||
amount: 123,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 456,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(`/admin/products/${product.id}`, data, adminHeaders)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 123,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 456,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,198 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/campaigns", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should throw an error if required params are not passed", async () => {
|
||||
const api = useApi() as any
|
||||
const { response } = await api
|
||||
.post(`/admin/campaigns`, {}, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(400)
|
||||
expect(response.data.message).toEqual(
|
||||
"name must be a string, name should not be empty"
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a campaign successfully", async () => {
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "TEST",
|
||||
type: "standard",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/campaigns`,
|
||||
{
|
||||
name: "test",
|
||||
campaign_identifier: "test",
|
||||
starts_at: new Date("01/01/2024").toISOString(),
|
||||
ends_at: new Date("01/01/2029").toISOString(),
|
||||
promotions: [{ id: createdPromotion.id }],
|
||||
budget: {
|
||||
limit: 1000,
|
||||
type: "usage",
|
||||
},
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.campaign).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "test",
|
||||
campaign_identifier: "test",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
budget: expect.objectContaining({
|
||||
limit: 1000,
|
||||
type: "usage",
|
||||
}),
|
||||
promotions: [
|
||||
expect.objectContaining({
|
||||
id: createdPromotion.id,
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create 3 campaigns in parallel and have the context passed as argument when calling createCampaigns with different transactionId", async () => {
|
||||
const parallelPromotion = await promotionModuleService.create({
|
||||
code: "PARALLEL",
|
||||
type: "standard",
|
||||
})
|
||||
|
||||
const spyCreateCampaigns = jest.spyOn(
|
||||
promotionModuleService.constructor.prototype,
|
||||
"createCampaigns"
|
||||
)
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const a = async () => {
|
||||
return await api.post(
|
||||
`/admin/campaigns`,
|
||||
{
|
||||
name: "camp_1",
|
||||
campaign_identifier: "camp_1",
|
||||
starts_at: new Date("01/01/2024").toISOString(),
|
||||
ends_at: new Date("01/02/2024").toISOString(),
|
||||
promotions: [{ id: parallelPromotion.id }],
|
||||
budget: {
|
||||
limit: 1000,
|
||||
type: "usage",
|
||||
},
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
}
|
||||
|
||||
const b = async () => {
|
||||
return await api.post(
|
||||
`/admin/campaigns`,
|
||||
{
|
||||
name: "camp_2",
|
||||
campaign_identifier: "camp_2",
|
||||
starts_at: new Date("01/02/2024").toISOString(),
|
||||
ends_at: new Date("01/03/2029").toISOString(),
|
||||
promotions: [{ id: parallelPromotion.id }],
|
||||
budget: {
|
||||
limit: 500,
|
||||
type: "usage",
|
||||
},
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
}
|
||||
|
||||
const c = async () => {
|
||||
return await api.post(
|
||||
`/admin/campaigns`,
|
||||
{
|
||||
name: "camp_3",
|
||||
campaign_identifier: "camp_3",
|
||||
starts_at: new Date("01/03/2024").toISOString(),
|
||||
ends_at: new Date("01/04/2029").toISOString(),
|
||||
promotions: [{ id: parallelPromotion.id }],
|
||||
budget: {
|
||||
limit: 250,
|
||||
type: "usage",
|
||||
},
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
...adminHeaders.headers,
|
||||
"x-request-id": "my-custom-request-id",
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
await Promise.all([a(), b(), c()])
|
||||
|
||||
expect(spyCreateCampaigns).toHaveBeenCalledTimes(3)
|
||||
expect(spyCreateCampaigns.mock.calls[0][1].__type).toBe("MedusaContext")
|
||||
|
||||
const distinctTransactionId = [
|
||||
...new Set(
|
||||
spyCreateCampaigns.mock.calls.map((call) => call[1].transactionId)
|
||||
),
|
||||
]
|
||||
expect(distinctTransactionId).toHaveLength(3)
|
||||
|
||||
const distinctRequestId = [
|
||||
...new Set(
|
||||
spyCreateCampaigns.mock.calls.map((call) => call[1].requestId)
|
||||
),
|
||||
]
|
||||
|
||||
expect(distinctRequestId).toHaveLength(3)
|
||||
expect(distinctRequestId).toContain("my-custom-request-id")
|
||||
})
|
||||
})
|
||||
@@ -1,344 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { PromotionType } from "@medusajs/utils"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/promotions", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should throw an error if required params are not passed", async () => {
|
||||
const api = useApi() as any
|
||||
const { response } = await api
|
||||
.post(
|
||||
`/admin/promotions`,
|
||||
{
|
||||
type: PromotionType.STANDARD,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(400)
|
||||
expect(response.data.message).toEqual(
|
||||
"code must be a string, code should not be empty, application_method should not be empty"
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a standard promotion successfully", async () => {
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/promotions`,
|
||||
{
|
||||
code: "TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
is_automatic: true,
|
||||
campaign: {
|
||||
name: "test",
|
||||
campaign_identifier: "test-1",
|
||||
budget: {
|
||||
type: "usage",
|
||||
limit: 100,
|
||||
},
|
||||
},
|
||||
application_method: {
|
||||
target_type: "items",
|
||||
type: "fixed",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 100,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.promotion).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
code: "TEST",
|
||||
type: "standard",
|
||||
is_automatic: true,
|
||||
campaign: expect.objectContaining({
|
||||
name: "test",
|
||||
campaign_identifier: "test-1",
|
||||
budget: expect.objectContaining({
|
||||
type: "usage",
|
||||
limit: 100,
|
||||
}),
|
||||
}),
|
||||
application_method: expect.objectContaining({
|
||||
value: 100,
|
||||
max_quantity: 100,
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "each",
|
||||
target_rules: [
|
||||
expect.objectContaining({
|
||||
operator: "eq",
|
||||
attribute: "test.test",
|
||||
values: expect.arrayContaining([
|
||||
expect.objectContaining({ value: "test1" }),
|
||||
expect.objectContaining({ value: "test2" }),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
rules: [
|
||||
expect.objectContaining({
|
||||
operator: "eq",
|
||||
attribute: "test.test",
|
||||
values: expect.arrayContaining([
|
||||
expect.objectContaining({ value: "test1" }),
|
||||
expect.objectContaining({ value: "test2" }),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error if buy_rules params are not passed", async () => {
|
||||
const api = useApi() as any
|
||||
const { response } = await api
|
||||
.post(
|
||||
`/admin/promotions`,
|
||||
{
|
||||
code: "TEST",
|
||||
type: PromotionType.BUYGET,
|
||||
is_automatic: true,
|
||||
application_method: {
|
||||
target_type: "items",
|
||||
type: "fixed",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 100,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(400)
|
||||
expect(response.data.message).toEqual(
|
||||
"Buy rules are required for buyget promotion type"
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error if buy_rules params are not passed", async () => {
|
||||
const api = useApi() as any
|
||||
const { response } = await api
|
||||
.post(
|
||||
`/admin/promotions`,
|
||||
{
|
||||
code: "TEST",
|
||||
type: PromotionType.BUYGET,
|
||||
is_automatic: true,
|
||||
application_method: {
|
||||
target_type: "items",
|
||||
type: "fixed",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 100,
|
||||
buy_rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(400)
|
||||
expect(response.data.message).toEqual(
|
||||
"Target rules are required for buyget promotion type"
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a buyget promotion successfully", async () => {
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/promotions`,
|
||||
{
|
||||
code: "TEST",
|
||||
type: PromotionType.BUYGET,
|
||||
is_automatic: true,
|
||||
campaign: {
|
||||
name: "test",
|
||||
campaign_identifier: "test-1",
|
||||
budget: {
|
||||
type: "usage",
|
||||
limit: 100,
|
||||
},
|
||||
},
|
||||
application_method: {
|
||||
target_type: "items",
|
||||
type: "fixed",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 100,
|
||||
apply_to_quantity: 1,
|
||||
buy_rules_min_quantity: 1,
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
buy_rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
attribute: "test.test",
|
||||
operator: "eq",
|
||||
values: ["test1", "test2"],
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.promotion).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
code: "TEST",
|
||||
type: "buyget",
|
||||
is_automatic: true,
|
||||
campaign: expect.objectContaining({
|
||||
name: "test",
|
||||
campaign_identifier: "test-1",
|
||||
budget: expect.objectContaining({
|
||||
type: "usage",
|
||||
limit: 100,
|
||||
}),
|
||||
}),
|
||||
application_method: expect.objectContaining({
|
||||
value: 100,
|
||||
max_quantity: 100,
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "each",
|
||||
apply_to_quantity: 1,
|
||||
buy_rules_min_quantity: 1,
|
||||
target_rules: [
|
||||
expect.objectContaining({
|
||||
operator: "eq",
|
||||
attribute: "test.test",
|
||||
values: expect.arrayContaining([
|
||||
expect.objectContaining({ value: "test1" }),
|
||||
expect.objectContaining({ value: "test2" }),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
buy_rules: [
|
||||
expect.objectContaining({
|
||||
operator: "eq",
|
||||
attribute: "test.test",
|
||||
values: expect.arrayContaining([
|
||||
expect.objectContaining({ value: "test1" }),
|
||||
expect.objectContaining({ value: "test2" }),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
rules: [
|
||||
expect.objectContaining({
|
||||
operator: "eq",
|
||||
attribute: "test.test",
|
||||
values: expect.arrayContaining([
|
||||
expect.objectContaining({ value: "test1" }),
|
||||
expect.objectContaining({ value: "test2" }),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,73 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("DELETE /admin/campaigns/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete campaign successfully", async () => {
|
||||
const [createdCampaign] = await promotionModuleService.createCampaigns([
|
||||
{
|
||||
name: "test",
|
||||
campaign_identifier: "test",
|
||||
starts_at: new Date("01/01/2024"),
|
||||
ends_at: new Date("01/01/2025"),
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/campaigns/${createdCampaign.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
const campaigns = await promotionModuleService.listCampaigns({
|
||||
id: [createdCampaign.id],
|
||||
})
|
||||
|
||||
expect(campaigns.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -1,74 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("DELETE /admin/promotions/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete promotion successfully", async () => {
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "TEST",
|
||||
type: "standard",
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "order",
|
||||
value: "100",
|
||||
},
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/promotions/${createdPromotion.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
const promotions = await promotionModuleService.list({
|
||||
id: [createdPromotion.id],
|
||||
})
|
||||
|
||||
expect(promotions.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -1,186 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { CampaignBudgetType } from "@medusajs/utils"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
export const campaignsData = [
|
||||
{
|
||||
id: "campaign-id-1",
|
||||
name: "campaign 1",
|
||||
description: "test description",
|
||||
currency: "USD",
|
||||
campaign_identifier: "test-1",
|
||||
starts_at: new Date("01/01/2023"),
|
||||
ends_at: new Date("01/01/2024"),
|
||||
budget: {
|
||||
type: CampaignBudgetType.SPEND,
|
||||
limit: 1000,
|
||||
used: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "campaign-id-2",
|
||||
name: "campaign 2",
|
||||
description: "test description",
|
||||
currency: "USD",
|
||||
campaign_identifier: "test-2",
|
||||
starts_at: new Date("01/01/2023"),
|
||||
ends_at: new Date("01/01/2024"),
|
||||
budget: {
|
||||
type: CampaignBudgetType.USAGE,
|
||||
limit: 1000,
|
||||
used: 0,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/campaigns", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
await promotionModuleService.createCampaigns(campaignsData)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get all campaigns and its count", async () => {
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/admin/campaigns`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(2)
|
||||
expect(response.data.campaigns).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "campaign 1",
|
||||
description: "test description",
|
||||
currency: "USD",
|
||||
campaign_identifier: "test-1",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
budget: {
|
||||
id: expect.any(String),
|
||||
campaign: expect.any(Object),
|
||||
type: "spend",
|
||||
limit: 1000,
|
||||
used: 0,
|
||||
raw_limit: {
|
||||
precision: 20,
|
||||
value: "1000",
|
||||
},
|
||||
raw_used: {
|
||||
precision: 20,
|
||||
value: "0",
|
||||
},
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
},
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "campaign 2",
|
||||
description: "test description",
|
||||
currency: "USD",
|
||||
campaign_identifier: "test-2",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
budget: {
|
||||
id: expect.any(String),
|
||||
campaign: expect.any(Object),
|
||||
type: "usage",
|
||||
limit: 1000,
|
||||
used: 0,
|
||||
raw_limit: {
|
||||
precision: 20,
|
||||
value: "1000",
|
||||
},
|
||||
raw_used: {
|
||||
precision: 20,
|
||||
value: "0",
|
||||
},
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
},
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should get all campaigns and its count filtered", async () => {
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/campaigns?fields=name,created_at,budget.id`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(2)
|
||||
expect(response.data.campaigns).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
id: expect.any(String),
|
||||
name: "campaign 1",
|
||||
created_at: expect.any(String),
|
||||
budget: {
|
||||
id: expect.any(String),
|
||||
campaign: expect.any(Object),
|
||||
},
|
||||
},
|
||||
{
|
||||
id: expect.any(String),
|
||||
name: "campaign 2",
|
||||
created_at: expect.any(String),
|
||||
budget: {
|
||||
id: expect.any(String),
|
||||
campaign: expect.any(Object),
|
||||
},
|
||||
},
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,125 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { PromotionType } from "@medusajs/utils"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/promotions", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get all promotions and its count", async () => {
|
||||
await promotionModuleService.create([
|
||||
{
|
||||
code: "TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "order",
|
||||
value: "100",
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/admin/promotions`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.promotions).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
code: "TEST",
|
||||
campaign: null,
|
||||
is_automatic: false,
|
||||
type: "standard",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
application_method: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: 100,
|
||||
type: "fixed",
|
||||
target_type: "order",
|
||||
allocation: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
}),
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should get all promotions and its count filtered", async () => {
|
||||
const [createdPromotion] = await promotionModuleService.create([
|
||||
{
|
||||
code: "TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "order",
|
||||
value: "100",
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/promotions?fields=code,created_at,application_method.id`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.promotions).toEqual([
|
||||
{
|
||||
id: expect.any(String),
|
||||
code: "TEST",
|
||||
created_at: expect.any(String),
|
||||
application_method: {
|
||||
id: expect.any(String),
|
||||
promotion: expect.any(Object),
|
||||
},
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1,141 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { CampaignBudgetType } from "@medusajs/utils"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
export const campaignData = {
|
||||
name: "campaign 1",
|
||||
description: "test description",
|
||||
currency: "USD",
|
||||
campaign_identifier: "test-1",
|
||||
starts_at: new Date("01/01/2023"),
|
||||
ends_at: new Date("01/01/2024"),
|
||||
budget: {
|
||||
type: CampaignBudgetType.SPEND,
|
||||
limit: 1000,
|
||||
used: 0,
|
||||
},
|
||||
}
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/campaigns", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
let campaigns
|
||||
|
||||
beforeEach(async () => {})
|
||||
|
||||
it("should throw an error if id does not exist", async () => {
|
||||
const api = useApi() as any
|
||||
const { response } = await api
|
||||
.get(`/admin/campaigns/does-not-exist`, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(404)
|
||||
expect(response.data.message).toEqual(
|
||||
"Campaign with id: does-not-exist was not found"
|
||||
)
|
||||
})
|
||||
|
||||
it("should get the requested campaign", async () => {
|
||||
const createdCampaign = await promotionModuleService.createCampaigns(
|
||||
campaignData
|
||||
)
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/campaigns/${createdCampaign.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.campaign).toEqual({
|
||||
id: expect.any(String),
|
||||
name: "campaign 1",
|
||||
description: "test description",
|
||||
currency: "USD",
|
||||
campaign_identifier: "test-1",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
budget: {
|
||||
id: expect.any(String),
|
||||
campaign: expect.any(Object),
|
||||
type: "spend",
|
||||
limit: 1000,
|
||||
raw_limit: {
|
||||
precision: 20,
|
||||
value: "1000",
|
||||
},
|
||||
raw_used: {
|
||||
precision: 20,
|
||||
value: "0",
|
||||
},
|
||||
used: 0,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
},
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
})
|
||||
})
|
||||
|
||||
it("should get the requested campaign with filtered fields and relations", async () => {
|
||||
const createdCampaign = await promotionModuleService.createCampaigns(
|
||||
campaignData
|
||||
)
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/campaigns/${createdCampaign.id}?fields=name&expand=`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.campaign).toEqual({
|
||||
id: expect.any(String),
|
||||
name: "campaign 1",
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,129 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { PromotionType } from "@medusajs/utils"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/promotions", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should throw an error if id does not exist", async () => {
|
||||
const api = useApi() as any
|
||||
const { response } = await api
|
||||
.get(`/admin/promotions/does-not-exist`, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(404)
|
||||
expect(response.data.message).toEqual(
|
||||
"Promotion with id: does-not-exist was not found"
|
||||
)
|
||||
})
|
||||
|
||||
it("should get the requested promotion", async () => {
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "order",
|
||||
value: "100",
|
||||
},
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/promotions/${createdPromotion.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.promotion).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
code: "TEST",
|
||||
campaign: null,
|
||||
is_automatic: false,
|
||||
type: "standard",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
application_method: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
promotion: expect.any(Object),
|
||||
value: 100,
|
||||
type: "fixed",
|
||||
target_type: "order",
|
||||
max_quantity: 0,
|
||||
allocation: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
}),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should get the requested promotion with filtered fields and relations", async () => {
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "order",
|
||||
value: "100",
|
||||
},
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(
|
||||
`/admin/promotions/${createdPromotion.id}?fields=id,code&expand=`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.promotion).toEqual({
|
||||
id: expect.any(String),
|
||||
code: "TEST",
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,118 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/campaigns/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should throw an error if id does not exist", async () => {
|
||||
const api = useApi() as any
|
||||
const { response } = await api
|
||||
.post(`/admin/campaigns/does-not-exist`, {}, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(404)
|
||||
expect(response.data.message).toEqual(
|
||||
`Campaign with id "does-not-exist" not found`
|
||||
)
|
||||
})
|
||||
|
||||
it("should update a campaign successfully", async () => {
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "TEST",
|
||||
type: "standard",
|
||||
})
|
||||
|
||||
const createdPromotion2 = await promotionModuleService.create({
|
||||
code: "TEST_2",
|
||||
type: "standard",
|
||||
})
|
||||
|
||||
const createdCampaign = await promotionModuleService.createCampaigns({
|
||||
name: "test",
|
||||
campaign_identifier: "test",
|
||||
starts_at: new Date("01/01/2024").toISOString(),
|
||||
ends_at: new Date("01/01/2029").toISOString(),
|
||||
promotions: [{ id: createdPromotion.id }],
|
||||
budget: {
|
||||
limit: 1000,
|
||||
type: "usage",
|
||||
used: 10,
|
||||
},
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/campaigns/${createdCampaign.id}`,
|
||||
{
|
||||
name: "test-2",
|
||||
campaign_identifier: "test-2",
|
||||
budget: {
|
||||
limit: 2000,
|
||||
},
|
||||
promotions: [{ id: createdPromotion2.id }],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.campaign).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "test-2",
|
||||
campaign_identifier: "test-2",
|
||||
budget: expect.objectContaining({
|
||||
limit: 2000,
|
||||
type: "usage",
|
||||
used: 10,
|
||||
}),
|
||||
promotions: [
|
||||
expect.objectContaining({
|
||||
id: createdPromotion2.id,
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,192 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IPromotionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { PromotionType } from "@medusajs/utils"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/promotions/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let promotionModuleService: IPromotionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
promotionModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.PROMOTION
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should throw an error if id does not exist", async () => {
|
||||
const api = useApi() as any
|
||||
const { response } = await api
|
||||
.post(
|
||||
`/admin/promotions/does-not-exist`,
|
||||
{ type: PromotionType.STANDARD },
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(404)
|
||||
expect(response.data.message).toEqual(
|
||||
`Promotion with id "does-not-exist" not found`
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when both campaign and campaign_id params are passed", async () => {
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
is_automatic: true,
|
||||
application_method: {
|
||||
target_type: "items",
|
||||
type: "fixed",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 100,
|
||||
},
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const { response } = await api
|
||||
.post(
|
||||
`/admin/promotions/${createdPromotion.id}`,
|
||||
{
|
||||
campaign: {
|
||||
name: "test campaign",
|
||||
},
|
||||
campaign_id: "test",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(response.status).toEqual(400)
|
||||
expect(response.data.message).toContain(
|
||||
`Failed XOR relation between "campaign_id" and "campaign"`
|
||||
)
|
||||
})
|
||||
|
||||
it("should update a promotion successfully", async () => {
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "TEST",
|
||||
type: PromotionType.STANDARD,
|
||||
is_automatic: true,
|
||||
application_method: {
|
||||
target_type: "items",
|
||||
type: "fixed",
|
||||
allocation: "each",
|
||||
value: "100",
|
||||
max_quantity: 100,
|
||||
},
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/promotions/${createdPromotion.id}`,
|
||||
{
|
||||
code: "TEST_TWO",
|
||||
application_method: {
|
||||
value: "200",
|
||||
},
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.promotion).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
code: "TEST_TWO",
|
||||
application_method: expect.objectContaining({
|
||||
value: 200,
|
||||
}),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should update a buyget promotion successfully", async () => {
|
||||
const createdPromotion = await promotionModuleService.create({
|
||||
code: "PROMOTION_TEST",
|
||||
type: PromotionType.BUYGET,
|
||||
application_method: {
|
||||
type: "fixed",
|
||||
target_type: "items",
|
||||
allocation: "across",
|
||||
value: "100",
|
||||
apply_to_quantity: 1,
|
||||
buy_rules_min_quantity: 1,
|
||||
buy_rules: [
|
||||
{
|
||||
attribute: "product_collection.id",
|
||||
operator: "eq",
|
||||
values: ["pcol_towel"],
|
||||
},
|
||||
],
|
||||
target_rules: [
|
||||
{
|
||||
attribute: "product.id",
|
||||
operator: "eq",
|
||||
values: "prod_mat",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.post(
|
||||
`/admin/promotions/${createdPromotion.id}`,
|
||||
{
|
||||
code: "TEST_TWO",
|
||||
application_method: {
|
||||
value: "200",
|
||||
buy_rules_min_quantity: 6,
|
||||
},
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.promotion).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
code: "TEST_TWO",
|
||||
application_method: expect.objectContaining({
|
||||
value: 200,
|
||||
buy_rules_min_quantity: 6,
|
||||
}),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,223 +0,0 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { IRegionModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("Regions - Admin", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let service: IRegionModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
service = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
|
||||
await service.createDefaultCountries()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create, update, and delete a region", async () => {
|
||||
const api = useApi() as any
|
||||
const created = await api.post(
|
||||
`/admin/regions`,
|
||||
{
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
countries: ["us", "ca"],
|
||||
metadata: { foo: "bar" },
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(created.status).toEqual(200)
|
||||
expect(created.data.region).toEqual(
|
||||
expect.objectContaining({
|
||||
id: created.data.region.id,
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
metadata: { foo: "bar" },
|
||||
})
|
||||
)
|
||||
expect(created.data.region.countries.map((c) => c.iso_2)).toEqual([
|
||||
"us",
|
||||
"ca",
|
||||
])
|
||||
|
||||
const updated = await api.post(
|
||||
`/admin/regions/${created.data.region.id}`,
|
||||
{
|
||||
name: "United States",
|
||||
currency_code: "usd",
|
||||
countries: ["us"],
|
||||
metadata: { foo: "baz" },
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.region).toEqual(
|
||||
expect.objectContaining({
|
||||
id: updated.data.region.id,
|
||||
name: "United States",
|
||||
currency_code: "usd",
|
||||
metadata: { foo: "baz" },
|
||||
})
|
||||
)
|
||||
expect(updated.data.region.countries.map((c) => c.iso_2)).toEqual(["us"])
|
||||
|
||||
const deleted = await api.delete(
|
||||
`/admin/regions/${updated.data.region.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(deleted.status).toEqual(200)
|
||||
expect(deleted.data).toEqual({
|
||||
id: updated.data.region.id,
|
||||
object: "region",
|
||||
deleted: true,
|
||||
})
|
||||
|
||||
const deletedRegion = await service.retrieve(updated.data.region.id, {
|
||||
withDeleted: true,
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
expect(deletedRegion.deleted_at).toBeTruthy()
|
||||
})
|
||||
|
||||
it("should throw on missing required properties in create", async () => {
|
||||
const api = useApi() as any
|
||||
const err = await api
|
||||
.post(`/admin/regions`, {}, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(err.response.status).toEqual(400)
|
||||
expect(err.response.data.message).toEqual(
|
||||
"name must be a string, currency_code must be a string"
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw on unknown properties in create", async () => {
|
||||
const api = useApi() as any
|
||||
const error = await api
|
||||
.post(
|
||||
`/admin/regions`,
|
||||
{
|
||||
foo: "bar",
|
||||
currency_code: "usd",
|
||||
name: "Test Region",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data.message).toEqual("property foo should not exist")
|
||||
})
|
||||
|
||||
it("should throw on unknown properties in update", async () => {
|
||||
const api = useApi() as any
|
||||
|
||||
const created = await service.create({
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
})
|
||||
|
||||
const error = await api
|
||||
.post(
|
||||
`/admin/regions/${created.id}`,
|
||||
{
|
||||
foo: "bar",
|
||||
currency_code: "usd",
|
||||
name: "Test Region",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data.message).toEqual("property foo should not exist")
|
||||
})
|
||||
|
||||
it("should get all regions and count", async () => {
|
||||
await service.create([
|
||||
{
|
||||
name: "Test",
|
||||
currency_code: "usd",
|
||||
countries: ["jp"],
|
||||
metadata: { foo: "bar" },
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/admin/regions`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.regions).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "Test",
|
||||
currency_code: "usd",
|
||||
metadata: { foo: "bar" },
|
||||
}),
|
||||
])
|
||||
expect(response.data.regions[0].countries.map((c) => c.iso_2)).toEqual([
|
||||
"jp",
|
||||
])
|
||||
})
|
||||
|
||||
it("should get a region", async () => {
|
||||
const [region] = await service.create([
|
||||
{
|
||||
name: "Test",
|
||||
currency_code: "usd",
|
||||
countries: ["jp"],
|
||||
metadata: { foo: "bar" },
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/admin/regions/${region.id}`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.region).toEqual(
|
||||
expect.objectContaining({
|
||||
id: region.id,
|
||||
name: "Test",
|
||||
currency_code: "usd",
|
||||
metadata: { foo: "bar" },
|
||||
})
|
||||
)
|
||||
expect(response.data.region.countries.map((c) => c.iso_2)).toEqual(["jp"])
|
||||
})
|
||||
})
|
||||
@@ -1,139 +0,0 @@
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("product", () => {
|
||||
let medusaContainer
|
||||
let productService
|
||||
|
||||
let shutdownServer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
await initDb({ cwd })
|
||||
shutdownServer = shutdownServer = await startBootstrapApp({ cwd })
|
||||
medusaContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
jest.clearAllMocks()
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
describe("product service", () => {
|
||||
it("should create variant prices correctly in service creation", async () => {
|
||||
productService = medusaContainer.resolve("productService")
|
||||
|
||||
const payload = {
|
||||
title: "test-product",
|
||||
handle: "test-product",
|
||||
options: [{ title: "test-option" }],
|
||||
variants: [
|
||||
{
|
||||
title: "test-variant",
|
||||
inventory_quantity: 10,
|
||||
sku: "test",
|
||||
options: [{ value: "large", title: "test-option" }],
|
||||
prices: [{ amount: "100", currency_code: "usd" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const { id } = await productService.create(payload)
|
||||
|
||||
const result = await productService.retrieve(id, {
|
||||
relations: ["variants", "variants.prices", "variants.options"],
|
||||
})
|
||||
|
||||
expect(result).toEqual(
|
||||
expect.objectContaining({
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
options: [expect.objectContaining({ value: "large" })],
|
||||
prices: [
|
||||
expect.objectContaining({ amount: 100, currency_code: "usd" }),
|
||||
],
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should fail to create a variant without options on for a product with options", async () => {
|
||||
const payload = {
|
||||
title: "test-product",
|
||||
handle: "test-product",
|
||||
options: [{ title: "test-option" }],
|
||||
variants: [
|
||||
{
|
||||
title: "test-variant",
|
||||
inventory_quantity: 10,
|
||||
sku: "test",
|
||||
prices: [{ amount: "100", currency_code: "usd" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let error
|
||||
|
||||
try {
|
||||
await productService.create(payload)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error.message).toEqual(
|
||||
"Product options length does not match variant options length. Product has 1 and variant has 0."
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a product and variant without options", async () => {
|
||||
const payload = {
|
||||
title: "test-product",
|
||||
handle: "test-product",
|
||||
variants: [
|
||||
{
|
||||
title: "test-variant",
|
||||
inventory_quantity: 10,
|
||||
sku: "test",
|
||||
prices: [{ amount: "100", currency_code: "usd" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const { id } = await productService.create(payload)
|
||||
|
||||
const result = await productService.retrieve(id, {
|
||||
relations: [
|
||||
"options",
|
||||
"variants",
|
||||
"variants.prices",
|
||||
"variants.options",
|
||||
],
|
||||
})
|
||||
|
||||
expect(result).toEqual(
|
||||
expect.objectContaining({
|
||||
options: [],
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
prices: [
|
||||
expect.objectContaining({ amount: 100, currency_code: "usd" }),
|
||||
],
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,81 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IStoreModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { DataSource } from "typeorm"
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("Store - Admin", () => {
|
||||
let dbConnection: DataSource
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let service: IStoreModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
service = appContainer.resolve(ModuleRegistrationName.STORE)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
|
||||
const existingStores = await service.list({})
|
||||
await service.delete(existingStores.map((s) => s.id))
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should correctly implement the entire lifecycle of a store", async () => {
|
||||
const api = useApi() as any
|
||||
const createdStore = await service.create({ name: "Test store" })
|
||||
|
||||
expect(createdStore).toEqual(
|
||||
expect.objectContaining({
|
||||
id: createdStore.id,
|
||||
name: "Test store",
|
||||
})
|
||||
)
|
||||
|
||||
const updated = await api.post(
|
||||
`/admin/stores/${createdStore.id}`,
|
||||
{
|
||||
name: "Updated store",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.store).toEqual(
|
||||
expect.objectContaining({
|
||||
id: createdStore.id,
|
||||
name: "Updated store",
|
||||
})
|
||||
)
|
||||
|
||||
await service.delete(createdStore.id)
|
||||
const listedStores = await api.get(`/admin/stores`, adminHeaders)
|
||||
expect(listedStores.data.stores).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
@@ -1,376 +0,0 @@
|
||||
import path from "path"
|
||||
import { ITaxModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
|
||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("Taxes - Admin", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let service: ITaxModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
service = appContainer.resolve(ModuleRegistrationName.TAX)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("can retrieve a tax rate", async () => {
|
||||
const region = await service.createTaxRegions({
|
||||
country_code: "us",
|
||||
})
|
||||
const rate = await service.create({
|
||||
tax_region_id: region.id,
|
||||
code: "test",
|
||||
rate: 2.5,
|
||||
name: "Test Rate",
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const response = await api.get(`/admin/tax-rates/${rate.id}`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
tax_rate: {
|
||||
id: rate.id,
|
||||
code: "test",
|
||||
rate: 2.5,
|
||||
name: "Test Rate",
|
||||
metadata: null,
|
||||
tax_region_id: region.id,
|
||||
is_default: false,
|
||||
is_combinable: false,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
created_by: null,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("can create a tax region with rates and rules", async () => {
|
||||
const api = useApi() as any
|
||||
const regionRes = await api.post(
|
||||
`/admin/tax-regions`,
|
||||
{
|
||||
country_code: "us",
|
||||
default_tax_rate: {
|
||||
code: "default",
|
||||
rate: 2,
|
||||
name: "default rate",
|
||||
},
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const usRegionId = regionRes.data.tax_region.id
|
||||
|
||||
expect(regionRes.status).toEqual(200)
|
||||
expect(regionRes.data).toEqual({
|
||||
tax_region: {
|
||||
id: expect.any(String),
|
||||
country_code: "us",
|
||||
parent_id: null,
|
||||
province_code: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
created_by: "admin_user",
|
||||
provider_id: null,
|
||||
metadata: null,
|
||||
},
|
||||
})
|
||||
|
||||
const rateRes = await api.post(
|
||||
`/admin/tax-rates`,
|
||||
{
|
||||
tax_region_id: usRegionId,
|
||||
code: "RATE2",
|
||||
name: "another rate",
|
||||
rate: 10,
|
||||
rules: [{ reference: "product", reference_id: "prod_1234" }],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(rateRes.status).toEqual(200)
|
||||
expect(rateRes.data).toEqual({
|
||||
tax_rate: {
|
||||
id: expect.any(String),
|
||||
code: "RATE2",
|
||||
rate: 10,
|
||||
name: "another rate",
|
||||
is_default: false,
|
||||
metadata: null,
|
||||
tax_region_id: usRegionId,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
created_by: "admin_user",
|
||||
is_combinable: false,
|
||||
},
|
||||
})
|
||||
|
||||
const provRegRes = await api.post(
|
||||
`/admin/tax-regions`,
|
||||
{
|
||||
country_code: "US",
|
||||
parent_id: usRegionId,
|
||||
province_code: "cA",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(provRegRes.status).toEqual(200)
|
||||
expect(provRegRes.data).toEqual({
|
||||
tax_region: {
|
||||
id: expect.any(String),
|
||||
country_code: "us",
|
||||
parent_id: usRegionId,
|
||||
province_code: "ca",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
created_by: "admin_user",
|
||||
metadata: null,
|
||||
provider_id: null,
|
||||
},
|
||||
})
|
||||
|
||||
const defRes = await api.post(
|
||||
`/admin/tax-rates`,
|
||||
{
|
||||
tax_region_id: provRegRes.data.tax_region.id,
|
||||
code: "DEFAULT",
|
||||
name: "DEFAULT",
|
||||
rate: 10,
|
||||
is_default: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const listRes = await api.get(`/admin/tax-rates`, adminHeaders)
|
||||
|
||||
expect(listRes.status).toEqual(200)
|
||||
expect(listRes.data.tax_rates).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: rateRes.data.tax_rate.id,
|
||||
code: "RATE2",
|
||||
rate: 10,
|
||||
name: "another rate",
|
||||
is_default: false,
|
||||
metadata: null,
|
||||
tax_region_id: usRegionId,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
created_by: "admin_user",
|
||||
}),
|
||||
expect.objectContaining({ id: defRes.data.tax_rate.id }),
|
||||
expect.objectContaining({
|
||||
tax_region_id: usRegionId,
|
||||
is_default: true,
|
||||
rate: 2,
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("can create a tax rate and update it", async () => {
|
||||
const api = useApi() as any
|
||||
const regionRes = await api.post(
|
||||
`/admin/tax-regions`,
|
||||
{
|
||||
country_code: "us",
|
||||
default_tax_rate: { code: "default", rate: 2, name: "default rate" },
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const usRegionId = regionRes.data.tax_region.id
|
||||
|
||||
expect(regionRes.status).toEqual(200)
|
||||
expect(regionRes.data).toEqual({
|
||||
tax_region: {
|
||||
id: expect.any(String),
|
||||
country_code: "us",
|
||||
parent_id: null,
|
||||
province_code: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
created_by: "admin_user",
|
||||
provider_id: null,
|
||||
metadata: null,
|
||||
},
|
||||
})
|
||||
|
||||
const rateRes = await api.post(
|
||||
`/admin/tax-rates`,
|
||||
{
|
||||
tax_region_id: usRegionId,
|
||||
code: "RATE2",
|
||||
name: "another rate",
|
||||
rate: 10,
|
||||
rules: [{ reference: "product", reference_id: "prod_1234" }],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(rateRes.status).toEqual(200)
|
||||
expect(rateRes.data).toEqual({
|
||||
tax_rate: {
|
||||
id: expect.any(String),
|
||||
code: "RATE2",
|
||||
rate: 10,
|
||||
name: "another rate",
|
||||
is_default: false,
|
||||
metadata: null,
|
||||
tax_region_id: usRegionId,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
created_by: "admin_user",
|
||||
is_combinable: false,
|
||||
},
|
||||
})
|
||||
|
||||
const updateRes = await api.post(
|
||||
`/admin/tax-rates/${rateRes.data.tax_rate.id}`,
|
||||
{
|
||||
code: "updatedcode",
|
||||
rate: 12,
|
||||
is_combinable: true,
|
||||
name: "Another Name",
|
||||
metadata: { you: "know it" },
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(updateRes.status).toEqual(200)
|
||||
expect(updateRes.data).toEqual({
|
||||
tax_rate: {
|
||||
id: expect.any(String),
|
||||
code: "updatedcode",
|
||||
rate: 12,
|
||||
name: "Another Name",
|
||||
is_default: false,
|
||||
metadata: { you: "know it" },
|
||||
tax_region_id: usRegionId,
|
||||
deleted_at: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
is_combinable: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("can create a tax rate and delete it", async () => {
|
||||
const api = useApi() as any
|
||||
const regionRes = await api.post(
|
||||
`/admin/tax-regions`,
|
||||
{
|
||||
country_code: "us",
|
||||
default_tax_rate: { code: "default", rate: 2, name: "default rate" },
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const usRegionId = regionRes.data.tax_region.id
|
||||
|
||||
const rateRes = await api.post(
|
||||
`/admin/tax-rates`,
|
||||
{
|
||||
tax_region_id: usRegionId,
|
||||
code: "RATE2",
|
||||
name: "another rate",
|
||||
rate: 10,
|
||||
rules: [{ reference: "product", reference_id: "prod_1234" }],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/tax-rates/${rateRes.data.tax_rate.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
expect(deleteRes.data).toEqual({
|
||||
id: rateRes.data.tax_rate.id,
|
||||
object: "tax_rate",
|
||||
deleted: true,
|
||||
})
|
||||
|
||||
const rates = await service.list(
|
||||
{ id: rateRes.data.tax_rate.id },
|
||||
{ withDeleted: true }
|
||||
)
|
||||
expect(rates.length).toEqual(1)
|
||||
expect(rates[0].deleted_at).not.toBeNull()
|
||||
})
|
||||
|
||||
it("can create a tax region and delete it", async () => {
|
||||
const api = useApi() as any
|
||||
const regionRes = await api.post(
|
||||
`/admin/tax-regions`,
|
||||
{
|
||||
country_code: "us",
|
||||
default_tax_rate: { code: "default", rate: 2, name: "default rate" },
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const usRegionId = regionRes.data.tax_region.id
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/tax-regions/${usRegionId}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
expect(deleteRes.data).toEqual({
|
||||
id: usRegionId,
|
||||
object: "tax_region",
|
||||
deleted: true,
|
||||
})
|
||||
|
||||
const rates = await service.listTaxRegions(
|
||||
{ id: usRegionId },
|
||||
{ withDeleted: true }
|
||||
)
|
||||
expect(rates.length).toEqual(1)
|
||||
expect(rates[0].deleted_at).not.toBeNull()
|
||||
})
|
||||
})
|
||||
@@ -1,55 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/users", () => {
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("create a user", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const body = {
|
||||
email: "test_member@test.com",
|
||||
}
|
||||
|
||||
const response = await api.post(`/admin/users`, body, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
user: expect.objectContaining(body),
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,71 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import { IUserModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("DELETE /admin/users/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete a single user", async () => {
|
||||
const user = await userModuleService.create({
|
||||
email: "member@test.com",
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.delete(`/admin/users/${user.id}`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
id: user.id,
|
||||
object: "user",
|
||||
deleted: true,
|
||||
})
|
||||
|
||||
const { response: deletedResponse } = await api
|
||||
.get(`/admin/users/${user.id}`, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(deletedResponse.status).toEqual(404)
|
||||
expect(deletedResponse.data.type).toEqual("not_found")
|
||||
})
|
||||
})
|
||||
@@ -1,72 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import { IUserModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/users", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should list users", async () => {
|
||||
await userModuleService.create([
|
||||
{
|
||||
email: "member@test.com",
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.get(`/admin/users`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
users: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
email: "admin@medusa.js",
|
||||
}),
|
||||
expect.objectContaining({ email: "member@test.com" }),
|
||||
]),
|
||||
count: 2,
|
||||
offset: 0,
|
||||
limit: 50,
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,62 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import { IUserModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("GET /admin/users/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should retrieve a single user", async () => {
|
||||
const user = await userModuleService.create({
|
||||
email: "member@test.com",
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const response = await api.get(`/admin/users/${user.id}`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.user).toEqual(
|
||||
expect.objectContaining({ email: "member@test.com" })
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,68 +0,0 @@
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import { IUserModuleService } from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
describe("POST /admin/users/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let userModuleService: IUserModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
userModuleService = appContainer.resolve(ModuleRegistrationName.USER)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update a single user", async () => {
|
||||
const user = await userModuleService.create({
|
||||
email: "member@test.com",
|
||||
})
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const body = {
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
}
|
||||
const response = await api.post(
|
||||
`/admin/users/${user.id}`,
|
||||
body,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.user).toEqual(expect.objectContaining(body))
|
||||
})
|
||||
})
|
||||
@@ -1,9 +0,0 @@
|
||||
import { workflowEngineTestSuite } from "./tests"
|
||||
|
||||
jest.setTimeout(5000000)
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: false,
|
||||
}
|
||||
|
||||
workflowEngineTestSuite(env, { force_modules_migration: true })
|
||||
@@ -1,9 +0,0 @@
|
||||
import { workflowEngineTestSuite } from "./tests"
|
||||
|
||||
jest.setTimeout(5000000)
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
workflowEngineTestSuite(env)
|
||||
@@ -1,274 +0,0 @@
|
||||
import {
|
||||
createStep,
|
||||
createWorkflow,
|
||||
StepResponse,
|
||||
WorkflowData,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
import { AxiosInstance } from "axios"
|
||||
import adminSeeder from "../../../helpers/admin-seeder"
|
||||
import { createAdminUser } from "../../helpers/create-admin-user"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../environment-helpers/use-api"
|
||||
|
||||
export const workflowEngineTestSuite = (env, extraParams = {}) => {
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
describe("Workflow Engine API", () => {
|
||||
let medusaContainer
|
||||
let dbConnection
|
||||
let shutdownServer
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env, ...extraParams } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
medusaContainer = getContainer()
|
||||
|
||||
await createAdminUser(dbConnection, adminHeaders)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
describe("running workflows", () => {
|
||||
beforeAll(async () => {
|
||||
const step1 = createStep(
|
||||
{
|
||||
name: "my-step",
|
||||
},
|
||||
async (input: { initial: string }) => {
|
||||
return new StepResponse({
|
||||
result: input.initial,
|
||||
})
|
||||
}
|
||||
)
|
||||
const step2 = createStep(
|
||||
{
|
||||
name: "my-step-async",
|
||||
async: true,
|
||||
},
|
||||
async () => {}
|
||||
)
|
||||
|
||||
createWorkflow(
|
||||
{
|
||||
name: "my-workflow-name",
|
||||
retentionTime: 1000,
|
||||
},
|
||||
function (input: WorkflowData<{ initial: string }>) {
|
||||
step1(input)
|
||||
return step2()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("Should list all workflows in execution or completed and retrieve them by id", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
for (let i = 3; i--; ) {
|
||||
await api.post(
|
||||
`/admin/workflows-executions/my-workflow-name/run`,
|
||||
{
|
||||
input: {
|
||||
initial: "abc",
|
||||
},
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
}
|
||||
|
||||
const executions = await api.get(
|
||||
`/admin/workflows-executions`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(executions.data.count).toEqual(3)
|
||||
expect(executions.data.workflow_executions.length).toEqual(3)
|
||||
expect(executions.data.workflow_executions[0]).toEqual({
|
||||
workflow_id: "my-workflow-name",
|
||||
transaction_id: expect.any(String),
|
||||
id: expect.any(String),
|
||||
state: "invoking",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
})
|
||||
|
||||
const retrivedById = await api.get(
|
||||
`/admin/workflows-executions/` +
|
||||
executions.data.workflow_executions[0].id,
|
||||
adminHeaders
|
||||
)
|
||||
expect(retrivedById.data.workflow_execution).toEqual(
|
||||
expect.objectContaining(executions.data.workflow_executions[0])
|
||||
)
|
||||
})
|
||||
|
||||
it("Should list all workflows matching the filters", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
for (let i = 3; i--; ) {
|
||||
await api.post(
|
||||
`/admin/workflows-executions/my-workflow-name/run`,
|
||||
{
|
||||
input: {
|
||||
initial: "abc",
|
||||
},
|
||||
transaction_id: "transaction_" + (i + 1),
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
}
|
||||
|
||||
const executions = await api.get(
|
||||
`/admin/workflows-executions?transaction_id[]=transaction_1&transaction_id[]=transaction_2`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(executions.data.count).toEqual(2)
|
||||
expect(executions.data.workflow_executions.length).toEqual(2)
|
||||
expect(executions.data.workflow_executions[0]).toEqual({
|
||||
workflow_id: "my-workflow-name",
|
||||
transaction_id: expect.stringMatching(/transaction_1|transaction_2/),
|
||||
id: expect.any(String),
|
||||
state: "invoking",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
})
|
||||
expect(executions.data.workflow_executions[1]).toEqual({
|
||||
workflow_id: "my-workflow-name",
|
||||
transaction_id: expect.stringMatching(/transaction_1|transaction_2/),
|
||||
id: expect.any(String),
|
||||
state: "invoking",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
})
|
||||
})
|
||||
|
||||
it("Should execute a workflow and retrieve its execution while running and when it is completed", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const wf = await api.post(
|
||||
`/admin/workflows-executions/my-workflow-name/run`,
|
||||
{
|
||||
input: {
|
||||
initial: "abc",
|
||||
},
|
||||
transaction_id: "trx_123",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(wf.data).toEqual({
|
||||
acknowledgement: {
|
||||
transactionId: "trx_123",
|
||||
workflowId: "my-workflow-name",
|
||||
},
|
||||
})
|
||||
|
||||
const execution = await api.get(
|
||||
`/admin/workflows-executions/my-workflow-name/trx_123`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(execution.data).toEqual({
|
||||
workflow_execution: expect.objectContaining({
|
||||
workflow_id: "my-workflow-name",
|
||||
transaction_id: "trx_123",
|
||||
id: expect.any(String),
|
||||
state: "invoking",
|
||||
execution: expect.objectContaining({
|
||||
hasAsyncSteps: true,
|
||||
hasFailedSteps: false,
|
||||
hasSkippedSteps: false,
|
||||
hasWaitingSteps: false,
|
||||
hasRevertedSteps: false,
|
||||
}),
|
||||
context: expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
invoke: {
|
||||
"my-step": {
|
||||
__type: "Symbol(WorkflowWorkflowData)",
|
||||
output: {
|
||||
__type: "Symbol(WorkflowStepResponse)",
|
||||
output: {
|
||||
result: "abc",
|
||||
},
|
||||
compensateInput: {
|
||||
result: "abc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
payload: {
|
||||
initial: "abc",
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
const respondAsync = await api.post(
|
||||
`/admin/workflows-executions/my-workflow-name/steps/success`,
|
||||
{
|
||||
transaction_id: "trx_123",
|
||||
step_id: "my-step-async",
|
||||
response: {
|
||||
all: "good",
|
||||
},
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(respondAsync.data.success).toEqual(true)
|
||||
|
||||
const completed = await api.get(
|
||||
`/admin/workflows-executions/my-workflow-name/trx_123`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(completed.data).toEqual({
|
||||
workflow_execution: expect.objectContaining({
|
||||
workflow_id: "my-workflow-name",
|
||||
transaction_id: "trx_123",
|
||||
state: "done",
|
||||
context: expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
invoke: expect.objectContaining({
|
||||
"my-step-async": {
|
||||
__type: "Symbol(WorkflowStepResponse)",
|
||||
output: {
|
||||
all: "good",
|
||||
},
|
||||
compensateInput: {
|
||||
all: "good",
|
||||
},
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe("Noop test", () => {
|
||||
it("noop check", async () => {
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user