Creates ShippingProfileService & ShippingOptionService (#30)
Adds ShippingProfiles: With Shipping Profiles store operators can group products together and select which shipping options can fulfill the products. The shipping profiles are region agnostic, but for products to be shippable to a given region the shipping profile must have a shipping option associated that ships to this region. Adds Shipping Options: Shipping Options represents a way that the customer can have their order shipped. The shipping option has a fulfillment provider associated to determine who fulfills orders with the given shipping method. If a fulfillment provider has multiple ways that they can ship a shipping option for each of the fulfillment provider's shipping options can be created.
This commit is contained in:
1 parent
aff1ec3390
commit
ea4185eddd
72 files changed
+3658
-370
No files matched your search
@@ -3,6 +3,8 @@ import middlewares from "../../middlewares"
|
||||
import authRoutes from "./auth"
|
||||
import productRoutes from "./products"
|
||||
import productVariantRoutes from "./product-variants"
|
||||
import shippingOptionRoutes from "./shipping-options"
|
||||
import shippingProfileRoutes from "./shipping-profiles"
|
||||
|
||||
const route = Router()
|
||||
|
||||
@@ -16,6 +18,8 @@ export default app => {
|
||||
route.use(middlewares.authenticate())
|
||||
|
||||
productRoutes(route)
|
||||
shippingOptionRoutes(route)
|
||||
shippingProfileRoutes(route)
|
||||
// productVariantRoutes(route)
|
||||
|
||||
return app
|
||||
|
||||
@@ -4,11 +4,6 @@ import middlewares from "../../../middlewares"
|
||||
const route = Router()
|
||||
|
||||
export default app => {
|
||||
// Inject <rootDir>/api/routes/admin/products/router.js
|
||||
// Inject <rootDir>/plugins/*/api/routes/admin/products/router.js
|
||||
// Inject <rootDir>/node_modules/*/api/routes/admin/products/router.js
|
||||
|
||||
|
||||
app.use("/products", route)
|
||||
|
||||
route.post("/", middlewares.wrap(require("./create-product").default))
|
||||
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingOptionServiceMock } from "../../../../../services/__mocks__/shipping-option"
|
||||
|
||||
describe("POST /admin/shipping-options", () => {
|
||||
describe("successful creation", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("POST", "/admin/shipping-options", {
|
||||
payload: {
|
||||
name: "Test option",
|
||||
region_id: "testregion",
|
||||
provider_id: "test_provider",
|
||||
price: {
|
||||
type: "flat_rate",
|
||||
amount: 100,
|
||||
},
|
||||
requirements: [
|
||||
{
|
||||
type: "min_subtotal",
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service create", () => {
|
||||
expect(ShippingOptionServiceMock.create).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingOptionServiceMock.create).toHaveBeenCalledWith({
|
||||
name: "Test option",
|
||||
region_id: "testregion",
|
||||
provider_id: "test_provider",
|
||||
price: {
|
||||
type: "flat_rate",
|
||||
amount: 100,
|
||||
},
|
||||
requirements: [
|
||||
{
|
||||
type: "min_subtotal",
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("fails on invalid data", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("POST", "/admin/shipping-options", {
|
||||
payload: {
|
||||
price: {
|
||||
type: "flat_rate",
|
||||
amount: 100,
|
||||
},
|
||||
requirements: [
|
||||
{
|
||||
type: "min_subtotal",
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 400", () => {
|
||||
expect(subject.status).toEqual(400)
|
||||
})
|
||||
|
||||
it("returns error", () => {
|
||||
expect(subject.body.message[0].message).toEqual(`"name" is required`)
|
||||
})
|
||||
})
|
||||
})
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingOptionServiceMock } from "../../../../../services/__mocks__/shipping-option"
|
||||
|
||||
describe("POST /admin/shipping-options", () => {
|
||||
describe("successful creation", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"DELETE",
|
||||
`/admin/shipping-options/${IdMap.getId("validId")}`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service delete", () => {
|
||||
expect(ShippingOptionServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingOptionServiceMock.delete).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingOptionServiceMock } from "../../../../../services/__mocks__/shipping-option"
|
||||
|
||||
describe("GET /admin/shipping-options/:optionId", () => {
|
||||
describe("successful retrieval", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"GET",
|
||||
`/admin/shipping-options/${IdMap.getId("validId")}`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service retrieve", () => {
|
||||
expect(ShippingOptionServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingOptionServiceMock.retrieve).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingOptionServiceMock } from "../../../../../services/__mocks__/shipping-option"
|
||||
|
||||
describe("GET /admin/shipping-options", () => {
|
||||
describe("successful retrieval", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("GET", `/admin/shipping-options`, {
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service retrieve", () => {
|
||||
expect(ShippingOptionServiceMock.list).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingOptionServiceMock.list).toHaveBeenCalledWith()
|
||||
})
|
||||
})
|
||||
})
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingOptionServiceMock } from "../../../../../services/__mocks__/shipping-option"
|
||||
|
||||
describe("POST /admin/shipping-options", () => {
|
||||
describe("successful creation", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/shipping-options/${IdMap.getId("validId")}`,
|
||||
{
|
||||
payload: {
|
||||
name: "Test option",
|
||||
price: {
|
||||
type: "flat_rate",
|
||||
amount: 100,
|
||||
},
|
||||
requirements: [
|
||||
{
|
||||
type: "min_subtotal",
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service method", () => {
|
||||
expect(ShippingOptionServiceMock.update).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingOptionServiceMock.update).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId"),
|
||||
{
|
||||
name: "Test option",
|
||||
price: {
|
||||
type: "flat_rate",
|
||||
amount: 100,
|
||||
},
|
||||
requirements: [
|
||||
{
|
||||
type: "min_subtotal",
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,36 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
name: Validator.string().required(),
|
||||
region_id: Validator.string().required(),
|
||||
provider_id: Validator.string().required(),
|
||||
data: Validator.object(),
|
||||
price: Validator.object().keys({
|
||||
type: Validator.string().required(),
|
||||
amount: Validator.number().optional(),
|
||||
}),
|
||||
requirements: Validator.array()
|
||||
.items(
|
||||
Validator.object({
|
||||
type: Validator.string().required(),
|
||||
value: Validator.number().required(),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const optionService = req.scope.resolve("shippingOptionService")
|
||||
const data = await optionService.create(value)
|
||||
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { option_id} = req.params
|
||||
try {
|
||||
const optionService = req.scope.resolve("shippingOptionService")
|
||||
|
||||
await optionService.delete(option_id)
|
||||
|
||||
res.sendStatus(200)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export default async (req, res) => {
|
||||
const { option_id } = req.params
|
||||
try {
|
||||
const optionService = req.scope.resolve("shippingOptionService")
|
||||
const data = await optionService.retrieve(option_id)
|
||||
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Router } from "express"
|
||||
import middlewares from "../../../middlewares"
|
||||
|
||||
const route = Router()
|
||||
|
||||
export default app => {
|
||||
app.use("/shipping-options", route)
|
||||
|
||||
route.get("/", middlewares.wrap(require("./list-shipping-options").default))
|
||||
route.post("/", middlewares.wrap(require("./create-shipping-option").default))
|
||||
|
||||
route.get(
|
||||
"/:option_id",
|
||||
middlewares.wrap(require("./get-shipping-option").default)
|
||||
)
|
||||
route.post(
|
||||
"/:option_id",
|
||||
middlewares.wrap(require("./update-shipping-option").default)
|
||||
)
|
||||
route.delete(
|
||||
"/:option_id",
|
||||
middlewares.wrap(require("./delete-shipping-option").default)
|
||||
)
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export default async (req, res) => {
|
||||
const { optionId } = req.params
|
||||
try {
|
||||
const optionService = req.scope.resolve("shippingOptionService")
|
||||
const data = await optionService.list()
|
||||
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { option_id } = req.params
|
||||
const schema = Validator.object().keys({
|
||||
name: Validator.string().optional(),
|
||||
price: Validator.object()
|
||||
.keys({
|
||||
type: Validator.string().required(),
|
||||
amount: Validator.number().optional(),
|
||||
})
|
||||
.optional(),
|
||||
requirements: Validator.array()
|
||||
.items(
|
||||
Validator.object({
|
||||
type: Validator.string().required(),
|
||||
value: Validator.number().required(),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const optionService = req.scope.resolve("shippingOptionService")
|
||||
|
||||
await optionService.update(option_id, value)
|
||||
|
||||
const data = await optionService.retrieve(option_id)
|
||||
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("POST /admin/shipping-profiles/:profile_id/products", () => {
|
||||
describe("successful addition", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
const profileId = IdMap.getId("validId")
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/shipping-profiles/${profileId}/products`,
|
||||
{
|
||||
payload: {
|
||||
product_id: IdMap.getId("validId"),
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service retrieve", () => {
|
||||
expect(ShippingProfileServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.retrieve).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
expect(ShippingProfileServiceMock.addProduct).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.addProduct).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId"),
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("POST /admin/shipping-profiles/:profile_id/products", () => {
|
||||
describe("successful addition", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
const profileId = IdMap.getId("validId")
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/shipping-profiles/${profileId}/shipping-options`,
|
||||
{
|
||||
payload: {
|
||||
option_id: IdMap.getId("validId"),
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service retrieve", () => {
|
||||
expect(ShippingProfileServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.retrieve).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
expect(
|
||||
ShippingProfileServiceMock.addShippingOption
|
||||
).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.addShippingOption).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId"),
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("POST /admin/shipping-profiles", () => {
|
||||
describe("successful creation", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("POST", "/admin/shipping-profiles", {
|
||||
payload: {
|
||||
name: "Test Profile",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service create", () => {
|
||||
expect(ShippingProfileServiceMock.create).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.create).toHaveBeenCalledWith({
|
||||
name: "Test Profile",
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingOptionServiceMock } from "../../../../../services/__mocks__/shipping-option"
|
||||
|
||||
describe("POST /admin/shipping-options", () => {
|
||||
describe("successful creation", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"DELETE",
|
||||
`/admin/shipping-options/${IdMap.getId("validId")}`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service delete", () => {
|
||||
expect(ShippingOptionServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingOptionServiceMock.delete).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("GET /admin/shipping-profiles/:profile_id", () => {
|
||||
describe("successful retrieval", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"GET",
|
||||
`/admin/shipping-profiles/${IdMap.getId("validId")}`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service retrieve", () => {
|
||||
expect(ShippingProfileServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.retrieve).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("GET /admin/shipping-profiles", () => {
|
||||
describe("successful retrieval", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("GET", `/admin/shipping-profiles`, {
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service retrieve", () => {
|
||||
expect(ShippingProfileServiceMock.list).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.list).toHaveBeenCalledWith()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,37 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("DELETE /admin/shipping-profiles/:profile_id/products/:product_id", () => {
|
||||
describe("successful addition", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
const profileId = IdMap.getId("validId")
|
||||
const productId = IdMap.getId("validId")
|
||||
subject = await request(
|
||||
"DELETE",
|
||||
`/admin/shipping-profiles/${profileId}/products/${productId}`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service retrieve", () => {
|
||||
expect(ShippingProfileServiceMock.removeProduct).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.removeProduct).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId"),
|
||||
IdMap.getId("validId")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("DELETE /admin/shipping-profiles/:profile_id/shipping-options/:option_id", () => {
|
||||
describe("successful addition", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
const profileId = IdMap.getId("validId")
|
||||
const optionId = IdMap.getId("validId")
|
||||
subject = await request(
|
||||
"DELETE",
|
||||
`/admin/shipping-profiles/${profileId}/shipping-options/${optionId}`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service retrieve", () => {
|
||||
expect(
|
||||
ShippingProfileServiceMock.removeShippingOption
|
||||
).toHaveBeenCalledTimes(1)
|
||||
expect(
|
||||
ShippingProfileServiceMock.removeShippingOption
|
||||
).toHaveBeenCalledWith(IdMap.getId("validId"), IdMap.getId("validId"))
|
||||
})
|
||||
})
|
||||
})
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("POST /admin/shipping-profile", () => {
|
||||
describe("successful update", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/shipping-profiles/${IdMap.getId("validId")}`,
|
||||
{
|
||||
payload: {
|
||||
name: "Test option",
|
||||
products: [IdMap.getId("product1")],
|
||||
shipping_options: [IdMap.getId("shipping1")],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service method", () => {
|
||||
expect(ShippingProfileServiceMock.update).toHaveBeenCalledTimes(1)
|
||||
expect(ShippingProfileServiceMock.update).toHaveBeenCalledWith(
|
||||
IdMap.getId("validId"),
|
||||
{
|
||||
name: "Test option",
|
||||
products: [IdMap.getId("product1")],
|
||||
shipping_options: [IdMap.getId("shipping1")],
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { profile_id } = req.params
|
||||
const schema = Validator.object().keys({
|
||||
product_id: Validator.objectId().required(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
await profileService.addProduct(profile_id, value.product_id)
|
||||
|
||||
const data = profileService.retrieve(profile_id)
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { profile_id } = req.params
|
||||
const schema = Validator.object().keys({
|
||||
option_id: Validator.objectId().required(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
await profileService.addShippingOption(profile_id, value.option_id)
|
||||
|
||||
const data = profileService.retrieve(profile_id)
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
name: Validator.string().required(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
const data = await profileService.create(value)
|
||||
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
export default async (req, res) => {
|
||||
const { profile_id } = req.params
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
await profileService.delete(profile_id)
|
||||
|
||||
res.status(200).json({
|
||||
id: profile_id,
|
||||
object: "shipping_profile",
|
||||
deleted: true,
|
||||
})
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
export default async (req, res) => {
|
||||
const { profile_id } = req.params
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
const data = await profileService.retrieve(profile_id)
|
||||
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Router } from "express"
|
||||
import middlewares from "../../../middlewares"
|
||||
|
||||
const route = Router()
|
||||
|
||||
export default app => {
|
||||
app.use("/shipping-profiles", route)
|
||||
|
||||
route.get("/", middlewares.wrap(require("./list-shipping-profiles").default))
|
||||
route.post(
|
||||
"/",
|
||||
middlewares.wrap(require("./create-shipping-profile").default)
|
||||
)
|
||||
|
||||
route.get(
|
||||
"/:profile_id",
|
||||
middlewares.wrap(require("./get-shipping-profile").default)
|
||||
)
|
||||
route.post(
|
||||
"/:profile_id",
|
||||
middlewares.wrap(require("./update-shipping-profile").default)
|
||||
)
|
||||
route.delete(
|
||||
"/:profile_id",
|
||||
middlewares.wrap(require("./delete-shipping-profile").default)
|
||||
)
|
||||
|
||||
// Product management
|
||||
route.post(
|
||||
"/:profile_id/products",
|
||||
middlewares.wrap(require("./add-product").default)
|
||||
)
|
||||
route.delete(
|
||||
"/:profile_id/products/:product_id",
|
||||
middlewares.wrap(require("./remove-product").default)
|
||||
)
|
||||
|
||||
// Shipping Option management
|
||||
route.post(
|
||||
"/:profile_id/shipping-options",
|
||||
middlewares.wrap(require("./add-shipping-option").default)
|
||||
)
|
||||
route.delete(
|
||||
"/:profile_id/shipping-options/:option_id",
|
||||
middlewares.wrap(require("./remove-shipping-option").default)
|
||||
)
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export default async (req, res) => {
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
const data = await profileService.list()
|
||||
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
export default async (req, res) => {
|
||||
const { profile_id, product_id } = req.params
|
||||
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
await profileService.removeProduct(profile_id, product_id)
|
||||
|
||||
const data = profileService.retrieve(profile_id)
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
export default async (req, res) => {
|
||||
const { profile_id, option_id } = req.params
|
||||
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
await profileService.removeShippingOption(profile_id, option_id)
|
||||
|
||||
const data = profileService.retrieve(profile_id)
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { profile_id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
name: Validator.string(),
|
||||
products: Validator.array().items(Validator.objectId()),
|
||||
shipping_options: Validator.array().items(Validator.objectId()),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const profileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
await profileService.update(profile_id, value)
|
||||
|
||||
const data = await profileService.retrieve(profile_id)
|
||||
res.status(200).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { CartServiceMock } from "../../../../../services/__mocks__/cart"
|
||||
import { LineItemServiceMock } from "../../../../../services/__mocks__/line-item"
|
||||
|
||||
describe("POST /store/carts/:id/shipping-methods", () => {
|
||||
describe("successfully adds a shipping method", () => {
|
||||
@@ -24,22 +23,12 @@ describe("POST /store/carts/:id/shipping-methods", () => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("calls CartService retrieveShippingOption", () => {
|
||||
expect(CartServiceMock.retrieveShippingOption).toHaveBeenCalledTimes(1)
|
||||
expect(CartServiceMock.retrieveShippingOption).toHaveBeenCalledWith(
|
||||
IdMap.getId("fr-cart"),
|
||||
IdMap.getId("freeShipping")
|
||||
)
|
||||
})
|
||||
|
||||
it("calls CartService addShipping", () => {
|
||||
expect(CartServiceMock.addShippingMethod).toHaveBeenCalledTimes(1)
|
||||
expect(CartServiceMock.addShippingMethod).toHaveBeenCalledWith(
|
||||
IdMap.getId("fr-cart"),
|
||||
{
|
||||
_id: IdMap.getId("freeShipping"),
|
||||
profile_id: "default_profile",
|
||||
}
|
||||
IdMap.getId("freeShipping"),
|
||||
{}
|
||||
)
|
||||
})
|
||||
|
||||
@@ -76,24 +65,13 @@ describe("POST /store/carts/:id/shipping-methods", () => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("calls CartService retrieveShippingOption", () => {
|
||||
expect(CartServiceMock.retrieveShippingOption).toHaveBeenCalledTimes(1)
|
||||
expect(CartServiceMock.retrieveShippingOption).toHaveBeenCalledWith(
|
||||
IdMap.getId("fr-cart"),
|
||||
IdMap.getId("freeShipping")
|
||||
)
|
||||
})
|
||||
|
||||
it("calls CartService addShipping", () => {
|
||||
expect(CartServiceMock.addShippingMethod).toHaveBeenCalledTimes(1)
|
||||
expect(CartServiceMock.addShippingMethod).toHaveBeenCalledWith(
|
||||
IdMap.getId("fr-cart"),
|
||||
IdMap.getId("freeShipping"),
|
||||
{
|
||||
_id: IdMap.getId("freeShipping"),
|
||||
profile_id: "default_profile",
|
||||
data: {
|
||||
extra_id: "id",
|
||||
},
|
||||
extra_id: "id",
|
||||
}
|
||||
)
|
||||
})
|
||||
@@ -107,60 +85,4 @@ describe("POST /store/carts/:id/shipping-methods", () => {
|
||||
expect(subject.body.decorated).toEqual(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("additional data without overwriting", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
const cartId = IdMap.getId("emptyCart")
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/store/carts/${cartId}/shipping-methods`,
|
||||
{
|
||||
payload: {
|
||||
option_id: IdMap.getId("withData"),
|
||||
data: {
|
||||
extra_id: "id",
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("calls CartService retrieveShippingOption", () => {
|
||||
expect(CartServiceMock.retrieveShippingOption).toHaveBeenCalledTimes(1)
|
||||
expect(CartServiceMock.retrieveShippingOption).toHaveBeenCalledWith(
|
||||
IdMap.getId("emptyCart"),
|
||||
IdMap.getId("withData")
|
||||
)
|
||||
})
|
||||
|
||||
it("calls CartService addShipping", () => {
|
||||
expect(CartServiceMock.addShippingMethod).toHaveBeenCalledTimes(1)
|
||||
expect(CartServiceMock.addShippingMethod).toHaveBeenCalledWith(
|
||||
IdMap.getId("emptyCart"),
|
||||
{
|
||||
_id: IdMap.getId("withData"),
|
||||
profile_id: "default_profile",
|
||||
data: {
|
||||
extra_id: "id",
|
||||
some_data: "yes",
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("returns the cart", () => {
|
||||
expect(subject.body._id).toEqual(IdMap.getId("emptyCart"))
|
||||
expect(subject.body.decorated).toEqual(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -6,7 +6,9 @@ export default async (req, res) => {
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
option_id: Validator.string().required(),
|
||||
data: Validator.object().optional(),
|
||||
data: Validator.object()
|
||||
.optional()
|
||||
.default({}),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
@@ -17,17 +19,7 @@ export default async (req, res) => {
|
||||
try {
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
|
||||
const method = await cartService.retrieveShippingOption(id, value.option_id)
|
||||
|
||||
// If the option accepts additional data this will be added
|
||||
if (!_.isEmpty(value.data)) {
|
||||
method.data = {
|
||||
...method.data,
|
||||
...value.data,
|
||||
}
|
||||
}
|
||||
|
||||
await cartService.addShippingMethod(id, method)
|
||||
await cartService.addShippingMethod(id, value.option_id, value.data)
|
||||
|
||||
let cart = await cartService.retrieve(id)
|
||||
cart = await cartService.decorate(cart)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Router } from "express"
|
||||
import productRoutes from "./products"
|
||||
import cartRoutes from "./carts"
|
||||
import shippingOptionRoutes from "./shipping-options"
|
||||
import middlewares from "../../middlewares"
|
||||
|
||||
const route = Router()
|
||||
@@ -10,6 +11,7 @@ export default app => {
|
||||
|
||||
productRoutes(route)
|
||||
cartRoutes(route)
|
||||
shippingOptionRoutes(route)
|
||||
|
||||
return app
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { carts, CartServiceMock } from "../../../../../services/__mocks__/cart"
|
||||
import { ShippingProfileServiceMock } from "../../../../../services/__mocks__/shipping-profile"
|
||||
|
||||
describe("GET /store/shipping-options", () => {
|
||||
describe("retrieves shipping options", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("GET", `/store/shipping-options`, {
|
||||
payload: {
|
||||
cart_id: IdMap.getId("emptyCart"),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("calls CartService retrieve", () => {
|
||||
expect(CartServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||
expect(CartServiceMock.retrieve).toHaveBeenCalledWith(
|
||||
IdMap.getId("emptyCart")
|
||||
)
|
||||
})
|
||||
|
||||
it("calls ShippingProfileService fetchCartOptions", () => {
|
||||
expect(ShippingProfileServiceMock.fetchCartOptions).toHaveBeenCalledTimes(
|
||||
1
|
||||
)
|
||||
expect(ShippingProfileServiceMock.fetchCartOptions).toHaveBeenCalledWith(
|
||||
carts.emptyCart
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("returns the cart", () => {
|
||||
expect(subject.body[0]._id).toEqual(IdMap.getId("cartShippingOption"))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Validator, MedusaError } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
cart_id: Validator.string(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
const shippingProfileService = req.scope.resolve("shippingProfileService")
|
||||
|
||||
const cart = await cartService.retrieve(value.cart_id)
|
||||
const options = await shippingProfileService.fetchCartOptions(cart)
|
||||
|
||||
res.status(200).json(options)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Router } from "express"
|
||||
import middlewares from "../../../middlewares"
|
||||
|
||||
const route = Router()
|
||||
|
||||
export default app => {
|
||||
app.use("/shipping-options", route)
|
||||
|
||||
route.get("/", middlewares.wrap(require("./get-shipping-options").default))
|
||||
|
||||
return app
|
||||
}
|
||||
Reference in new issue
Block a user