create product endpoint
This commit is contained in:
@@ -2,6 +2,7 @@ import { Router } from "express"
|
||||
import admin from "./routes/admin"
|
||||
import store from "./routes/store"
|
||||
import users from "./routes/users"
|
||||
import errorHandler from "./middlewares/error-handler"
|
||||
|
||||
// guaranteed to get dependencies
|
||||
export default () => {
|
||||
@@ -11,5 +12,7 @@ export default () => {
|
||||
admin(app)
|
||||
store(app)
|
||||
|
||||
app.use(errorHandler())
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
22
packages/medusa/src/api/middlewares/error-handler.js
Normal file
22
packages/medusa/src/api/middlewares/error-handler.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
|
||||
export default () => {
|
||||
return (err, req, res, next) => {
|
||||
const logger = req.scope.resolve("logger")
|
||||
logger.error(err.message)
|
||||
|
||||
let statusCode = 500
|
||||
switch (err.name) {
|
||||
case MedusaError.Types.INVALID_DATA:
|
||||
statusCode = 400
|
||||
break
|
||||
case MedusaError.Types.DB_ERROR:
|
||||
statusCode = 500
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
res.status(statusCode).json(err)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,76 @@
|
||||
import IdMap from "../../../../../helpers/id-map"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductServiceMock } from "../../../../../services/__mocks__/product"
|
||||
|
||||
describe("POST /admin/products", () => {
|
||||
describe("successful creation", () => {
|
||||
it("calls mock function", async () => {
|
||||
const res = await request("POST", "/admin/products", {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("POST", "/admin/products", {
|
||||
payload: {
|
||||
title: "Test Product",
|
||||
description: "Test Description",
|
||||
tags: "hi,med,dig",
|
||||
handle: "test-product",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(res.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(201)
|
||||
})
|
||||
|
||||
it("returns created product draft", () => {
|
||||
expect(subject.body).toEqual({
|
||||
title: "Test Product",
|
||||
description: "Test Description",
|
||||
tags: "hi,med,dig",
|
||||
handle: "test-product",
|
||||
})
|
||||
})
|
||||
|
||||
it("calls service createDraft", () => {
|
||||
expect(ProductServiceMock.createDraft).toHaveBeenCalledTimes(1)
|
||||
expect(ProductServiceMock.createDraft).toHaveBeenCalledWith({
|
||||
title: "Test Product",
|
||||
description: "Test Description",
|
||||
tags: "hi,med,dig",
|
||||
handle: "test-product",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("invalid data returns error details", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("POST", "/admin/products", {
|
||||
payload: {
|
||||
description: "Test Description",
|
||||
tags: "hi,med,dig",
|
||||
handle: "test-product",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 400", () => {
|
||||
expect(subject.status).toEqual(400)
|
||||
})
|
||||
|
||||
it("returns error details", () => {
|
||||
expect(subject.body.name).toEqual("invalid_data")
|
||||
expect(subject.body.message[0].message).toEqual(`"title" is required`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,11 +1,28 @@
|
||||
import { Validator } from "medusa-core-utils"
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
try {
|
||||
const variantService = req.scope.resolve("productVariantService")
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
const schema = Validator.object().keys({
|
||||
title: Validator.string().required(),
|
||||
description: Validator.string(),
|
||||
tags: Validator.string(),
|
||||
images: Validator.array().items(Validator.string()),
|
||||
variants: Validator.array().items(Validator.string()),
|
||||
metadata: Validator.object(),
|
||||
handle: Validator.string().required(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
res.sendStatus(200)
|
||||
try {
|
||||
const productService = req.scope.resolve("productService")
|
||||
const data = await productService.createDraft(value)
|
||||
|
||||
// Return the created product draft
|
||||
res.status(201).json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import "core-js/stable"
|
||||
import "regenerator-runtime/runtime"
|
||||
import express from "express"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import loaders from "./loaders"
|
||||
import Logger from "./loaders/logger"
|
||||
|
||||
@@ -12,28 +11,6 @@ const startServer = async () => {
|
||||
|
||||
await loaders({ expressApp: app })
|
||||
|
||||
app.use((err, req, res, next) => {
|
||||
const logger = req.scope.resolve("logger")
|
||||
logger.error(err.message)
|
||||
|
||||
let statusCode = 500
|
||||
switch (err.name) {
|
||||
case "ValidationError":
|
||||
statusCode = 400
|
||||
break
|
||||
case MedusaError.Types.INVALID_DATA:
|
||||
statusCode = 400
|
||||
break
|
||||
case MedusaError.Types.DB_ERROR:
|
||||
statusCode = 500
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
res.json(err).status(statusCode)
|
||||
})
|
||||
|
||||
app.listen(PORT, err => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createContainer } from "awilix"
|
||||
import { createContainer, asValue } from "awilix"
|
||||
import express from "express"
|
||||
import supertest from "supertest"
|
||||
import jwt from "jsonwebtoken"
|
||||
@@ -13,6 +13,11 @@ import config from "../config"
|
||||
const testApp = express()
|
||||
|
||||
const container = createContainer()
|
||||
container.register({
|
||||
logger: asValue({
|
||||
error: () => {},
|
||||
}),
|
||||
})
|
||||
|
||||
servicesLoader({ container })
|
||||
expressLoader({ app: testApp })
|
||||
@@ -29,13 +34,13 @@ apiLoader({ app: testApp })
|
||||
const supertestRequest = supertest(testApp)
|
||||
|
||||
let adminSessionOpts = {
|
||||
cookieName: "adminSession",
|
||||
cookieName: "session",
|
||||
secret: "test",
|
||||
}
|
||||
export { adminSessionOpts }
|
||||
|
||||
let clientSessionOpts = {
|
||||
cookieName: "clientSession",
|
||||
cookieName: "session",
|
||||
secret: "test",
|
||||
}
|
||||
export { clientSessionOpts }
|
||||
|
||||
@@ -90,39 +90,39 @@ export const variants = {
|
||||
empty_variant: emptyVariant,
|
||||
}
|
||||
|
||||
export const ProductVariantServiceMock = {
|
||||
retrieve: jest.fn().mockImplementation(variantId => {
|
||||
if (variantId === "1") {
|
||||
return Promise.resolve(variant1)
|
||||
}
|
||||
if (variantId === "2") {
|
||||
return Promise.resolve(variant2)
|
||||
}
|
||||
if (variantId === "3") {
|
||||
return Promise.resolve(variant3)
|
||||
}
|
||||
if (variantId === "4") {
|
||||
return Promise.resolve(variant4)
|
||||
}
|
||||
if (variantId === "invalid_option") {
|
||||
return Promise.resolve(invalidVariant)
|
||||
}
|
||||
if (variantId === "empty_option") {
|
||||
return Promise.resolve(emptyVariant)
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
delete: jest.fn().mockReturnValue(Promise.resolve()),
|
||||
addOptionValue: jest.fn().mockImplementation((variantId, optionId, value) => {
|
||||
return Promise.resolve({})
|
||||
}),
|
||||
deleteOptionValue: jest.fn().mockImplementation((variantId, optionId) => {
|
||||
return Promise.resolve({})
|
||||
}),
|
||||
}
|
||||
|
||||
const mock = jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
retrieve: jest.fn().mockImplementation(variantId => {
|
||||
if (variantId === "1") {
|
||||
return Promise.resolve(variant1)
|
||||
}
|
||||
if (variantId === "2") {
|
||||
return Promise.resolve(variant2)
|
||||
}
|
||||
if (variantId === "3") {
|
||||
return Promise.resolve(variant3)
|
||||
}
|
||||
if (variantId === "4") {
|
||||
return Promise.resolve(variant4)
|
||||
}
|
||||
if (variantId === "invalid_option") {
|
||||
return Promise.resolve(invalidVariant)
|
||||
}
|
||||
if (variantId === "empty_option") {
|
||||
return Promise.resolve(emptyVariant)
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
delete: jest.fn().mockReturnValue(Promise.resolve()),
|
||||
addOptionValue: jest
|
||||
.fn()
|
||||
.mockImplementation((variantId, optionId, value) => {
|
||||
return Promise.resolve({})
|
||||
}),
|
||||
deleteOptionValue: jest.fn().mockImplementation((variantId, optionId) => {
|
||||
return Promise.resolve({})
|
||||
}),
|
||||
}
|
||||
return ProductVariantServiceMock
|
||||
})
|
||||
|
||||
export default mock
|
||||
|
||||
11
packages/medusa/src/services/__mocks__/product.js
Normal file
11
packages/medusa/src/services/__mocks__/product.js
Normal file
@@ -0,0 +1,11 @@
|
||||
export const ProductServiceMock = {
|
||||
createDraft: jest.fn().mockImplementation(data => {
|
||||
return Promise.resolve(data)
|
||||
}),
|
||||
}
|
||||
|
||||
const mock = jest.fn().mockImplementation(() => {
|
||||
return ProductServiceMock
|
||||
})
|
||||
|
||||
export default mock
|
||||
Reference in New Issue
Block a user