Updates API endpoints to match new product-to-variant structure
This commit is contained in:
@@ -16,6 +16,7 @@ export default () => {
|
|||||||
break
|
break
|
||||||
case MedusaError.Types.DB_ERROR:
|
case MedusaError.Types.DB_ERROR:
|
||||||
statusCode = 500
|
statusCode = 500
|
||||||
|
logger.error(err)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -36,8 +36,10 @@ describe("POST /admin/products/:id/options", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns the updated product decorated", () => {
|
it("returns the updated product decorated", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
expect(subject.body.product._id).toEqual(
|
||||||
expect(subject.body.decorated).toEqual(true)
|
IdMap.getId("productWithOptions")
|
||||||
|
)
|
||||||
|
expect(subject.body.product.decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ describe("POST /admin/products", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns created product draft", () => {
|
it("returns created product draft", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("product1"))
|
expect(subject.body.product._id).toEqual(IdMap.getId("product1"))
|
||||||
expect(subject.body.decorated).toEqual(true)
|
expect(subject.body.product.decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("calls service createDraft", () => {
|
it("calls service createDraft", () => {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ describe("POST /admin/products/:id/variants", () => {
|
|||||||
IdMap.getId("productWithOptions"),
|
IdMap.getId("productWithOptions"),
|
||||||
{
|
{
|
||||||
title: "Test Product Variant",
|
title: "Test Product Variant",
|
||||||
|
options: [],
|
||||||
prices: [
|
prices: [
|
||||||
{
|
{
|
||||||
currency_code: "DKK",
|
currency_code: "DKK",
|
||||||
@@ -50,8 +51,10 @@ describe("POST /admin/products/:id/variants", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns the updated product decorated", () => {
|
it("returns the updated product decorated", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
expect(subject.body.product._id).toEqual(
|
||||||
expect(subject.body.decorated).toEqual(true)
|
IdMap.getId("productWithOptions")
|
||||||
|
)
|
||||||
|
expect(subject.body.product.decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe("DELETE /admin/products/:id/options/:optionId", () => {
|
|||||||
it("returns 200 and correct delete info", () => {
|
it("returns 200 and correct delete info", () => {
|
||||||
expect(subject.status).toEqual(200)
|
expect(subject.status).toEqual(200)
|
||||||
expect(subject.body).toEqual({
|
expect(subject.body).toEqual({
|
||||||
optionId: IdMap.getId("option1"),
|
option_id: IdMap.getId("option1"),
|
||||||
object: "option",
|
object: "option",
|
||||||
deleted: true,
|
deleted: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -34,9 +34,12 @@ describe("POST /admin/products/:id/variants/:variantId", () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("returns decorated product with variant removed", () => {
|
it("returns delete result", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
expect(subject.body).toEqual({
|
||||||
expect(subject.body.decorated).toEqual(true)
|
variant_id: IdMap.getId("variant1"),
|
||||||
|
object: "product-variant",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ describe("GET /admin/products/:id", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns product decorated", () => {
|
it("returns product decorated", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("product1"))
|
expect(subject.body.product._id).toEqual(IdMap.getId("product1"))
|
||||||
expect(subject.body.decorated).toEqual(true)
|
expect(subject.body.product.decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { IdMap } from "medusa-test-utils"
|
||||||
|
import { request } from "../../../../../helpers/test-request"
|
||||||
|
import { ProductServiceMock } from "../../../../../services/__mocks__/product"
|
||||||
|
|
||||||
|
describe("GET /admin/products/:id/variants", () => {
|
||||||
|
describe("successfully gets a product", () => {
|
||||||
|
let subject
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
subject = await request(
|
||||||
|
"GET",
|
||||||
|
`/admin/products/${IdMap.getId("product1")}/variants`,
|
||||||
|
{
|
||||||
|
adminSession: {
|
||||||
|
jwt: {
|
||||||
|
userId: IdMap.getId("admin_user"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls get product from productSerice", () => {
|
||||||
|
expect(ProductServiceMock.retrieveVariants).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ProductServiceMock.retrieveVariants).toHaveBeenCalledWith(
|
||||||
|
IdMap.getId("product1")
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns variants", () => {
|
||||||
|
expect(subject.body.variants[0]._id).toEqual(IdMap.getId("1"))
|
||||||
|
expect(subject.body.variants[1]._id).toEqual(IdMap.getId("2"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -21,10 +21,10 @@ describe("GET /admin/products", () => {
|
|||||||
|
|
||||||
it("returns 200 and decorated products", () => {
|
it("returns 200 and decorated products", () => {
|
||||||
expect(subject.status).toEqual(200)
|
expect(subject.status).toEqual(200)
|
||||||
expect(subject.body[0]._id).toEqual(products.product1._id)
|
expect(subject.body.products[0]._id).toEqual(products.product1._id)
|
||||||
expect(subject.body[0].decorated).toEqual(true)
|
expect(subject.body.products[0].decorated).toEqual(true)
|
||||||
expect(subject.body[1]._id).toEqual(products.product2._id)
|
expect(subject.body.products[1]._id).toEqual(products.product2._id)
|
||||||
expect(subject.body[1].decorated).toEqual(true)
|
expect(subject.body.products[1].decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("calls update", () => {
|
it("calls update", () => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe("POST /admin/products/:id/publish", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns product with published flag true", () => {
|
it("returns product with published flag true", () => {
|
||||||
expect(subject.body.published).toEqual(true)
|
expect(subject.body.product.published).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("calls service publish", () => {
|
it("calls service publish", () => {
|
||||||
|
|||||||
@@ -70,8 +70,10 @@ describe("POST /admin/products/:id/variants/:variantId", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns decorated product with variant removed", () => {
|
it("returns decorated product with variant removed", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
expect(subject.body.product._id).toEqual(
|
||||||
expect(subject.body.decorated).toEqual(true)
|
IdMap.getId("productWithOptions")
|
||||||
|
)
|
||||||
|
expect(subject.body.product.decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -118,8 +120,10 @@ describe("POST /admin/products/:id/variants/:variantId", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns decorated product with variant removed", () => {
|
it("returns decorated product with variant removed", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
expect(subject.body.product._id).toEqual(
|
||||||
expect(subject.body.decorated).toEqual(true)
|
IdMap.getId("productWithOptions")
|
||||||
|
)
|
||||||
|
expect(subject.body.product.decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -165,8 +169,10 @@ describe("POST /admin/products/:id/variants/:variantId", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns decorated product with variant removed", () => {
|
it("returns decorated product with variant removed", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
expect(subject.body.product._id).toEqual(
|
||||||
expect(subject.body.decorated).toEqual(true)
|
IdMap.getId("productWithOptions")
|
||||||
|
)
|
||||||
|
expect(subject.body.product.decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default async (req, res) => {
|
|||||||
"variants",
|
"variants",
|
||||||
"published",
|
"published",
|
||||||
])
|
])
|
||||||
res.json(data)
|
res.json({ product: data })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default async (req, res) => {
|
|||||||
"variants",
|
"variants",
|
||||||
"published",
|
"published",
|
||||||
])
|
])
|
||||||
res.json(newProduct)
|
res.json({ product: newProduct })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ export default async (req, res) => {
|
|||||||
amount: Validator.number().required(),
|
amount: Validator.number().required(),
|
||||||
})
|
})
|
||||||
.required(),
|
.required(),
|
||||||
options: Validator.array().items({
|
options: Validator.array()
|
||||||
option_id: Validator.objectId().required(),
|
.items({
|
||||||
value: Validator.string().required(),
|
option_id: Validator.objectId().required(),
|
||||||
}),
|
value: Validator.string().required(),
|
||||||
|
})
|
||||||
|
.default([]),
|
||||||
image: Validator.string().optional(),
|
image: Validator.string().optional(),
|
||||||
inventory_quantity: Validator.number().optional(),
|
inventory_quantity: Validator.number().optional(),
|
||||||
allow_backorder: Validator.boolean().optional(),
|
allow_backorder: Validator.boolean().optional(),
|
||||||
@@ -39,7 +41,7 @@ export default async (req, res) => {
|
|||||||
"variants",
|
"variants",
|
||||||
"published",
|
"published",
|
||||||
])
|
])
|
||||||
res.json(data)
|
res.json({ product: data })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id, optionId } = req.params
|
const { id, option_id } = req.params
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const productService = req.scope.resolve("productService")
|
const productService = req.scope.resolve("productService")
|
||||||
await productService.deleteOption(id, optionId)
|
await productService.deleteOption(id, option_id)
|
||||||
res.json({
|
res.json({
|
||||||
optionId,
|
option_id,
|
||||||
object: "option",
|
object: "option",
|
||||||
deleted: true,
|
deleted: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id, variantId } = req.params
|
const { id, variant_id } = req.params
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const productService = req.scope.resolve("productService")
|
const productService = req.scope.resolve("productService")
|
||||||
const product = await productService.deleteVariant(id, variantId)
|
const product = await productService.deleteVariant(id, variant_id)
|
||||||
const data = await productService.decorate(product, [
|
const data = await productService.decorate(product, [
|
||||||
"title",
|
"title",
|
||||||
"description",
|
"description",
|
||||||
@@ -14,7 +14,12 @@ export default async (req, res) => {
|
|||||||
"variants",
|
"variants",
|
||||||
"published",
|
"published",
|
||||||
])
|
])
|
||||||
res.json(product)
|
|
||||||
|
res.json({
|
||||||
|
variant_id,
|
||||||
|
object: "product-variant",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ export default async (req, res) => {
|
|||||||
"published",
|
"published",
|
||||||
])
|
])
|
||||||
|
|
||||||
res.json(product)
|
res.json({ product })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default async (req, res) => {
|
||||||
|
const { id } = req.params
|
||||||
|
|
||||||
|
const productService = req.scope.resolve("productService")
|
||||||
|
const variants = await productService.retrieveVariants(id)
|
||||||
|
|
||||||
|
res.json({ variants })
|
||||||
|
}
|
||||||
@@ -18,24 +18,29 @@ export default app => {
|
|||||||
middlewares.wrap(require("./create-variant").default)
|
middlewares.wrap(require("./create-variant").default)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
"/:id/variants",
|
||||||
|
middlewares.wrap(require("./get-variants").default)
|
||||||
|
)
|
||||||
|
|
||||||
route.post(
|
route.post(
|
||||||
"/:id/variants/:variant_id",
|
"/:id/variants/:variant_id",
|
||||||
middlewares.wrap(require("./update-variant").default)
|
middlewares.wrap(require("./update-variant").default)
|
||||||
)
|
)
|
||||||
|
|
||||||
route.post(
|
route.post(
|
||||||
"/:id/options/:optionId",
|
"/:id/options/:option_id",
|
||||||
middlewares.wrap(require("./update-option").default)
|
middlewares.wrap(require("./update-option").default)
|
||||||
)
|
)
|
||||||
route.post("/:id/options", middlewares.wrap(require("./add-option").default))
|
route.post("/:id/options", middlewares.wrap(require("./add-option").default))
|
||||||
|
|
||||||
route.delete(
|
route.delete(
|
||||||
"/:id/variants/:variantId",
|
"/:id/variants/:variant_id",
|
||||||
middlewares.wrap(require("./delete-variant").default)
|
middlewares.wrap(require("./delete-variant").default)
|
||||||
)
|
)
|
||||||
route.delete("/:id", middlewares.wrap(require("./delete-product").default))
|
route.delete("/:id", middlewares.wrap(require("./delete-product").default))
|
||||||
route.delete(
|
route.delete(
|
||||||
"/:id/options/:optionId",
|
"/:id/options/:option_id",
|
||||||
middlewares.wrap(require("./delete-option").default)
|
middlewares.wrap(require("./delete-option").default)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export default async (req, res) => {
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
res.json(products)
|
res.json({ products })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default async (req, res) => {
|
|||||||
"variants",
|
"variants",
|
||||||
"published",
|
"published",
|
||||||
])
|
])
|
||||||
res.json(publishedProduct)
|
res.json({ product: publishedProduct })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { MedusaError, Validator } from "medusa-core-utils"
|
import { MedusaError, Validator } from "medusa-core-utils"
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id, optionId } = req.params
|
const { id, option_id } = req.params
|
||||||
|
|
||||||
const schema = Validator.object().keys({
|
const schema = Validator.object().keys({
|
||||||
title: Validator.string(),
|
title: Validator.string(),
|
||||||
values: Validator.array().items(),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const { value, error } = schema.validate(req.body)
|
const { value, error } = schema.validate(req.body)
|
||||||
@@ -15,23 +14,25 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const productService = req.scope.resolve("productService")
|
const productService = req.scope.resolve("productService")
|
||||||
const product = await productService.retrieve(id)
|
|
||||||
|
|
||||||
await productService.updateOption(product._id, optionId, value)
|
const product = await productService.updateOption(id, option_id, value)
|
||||||
|
|
||||||
let newProduct = await productService.retrieve(product._id)
|
const data = await productService.decorate(
|
||||||
newProduct = await productService.decorate(newProduct, [
|
product,
|
||||||
"title",
|
[
|
||||||
"description",
|
"title",
|
||||||
"tags",
|
"description",
|
||||||
"handle",
|
"tags",
|
||||||
"images",
|
"handle",
|
||||||
"options",
|
"images",
|
||||||
"variants",
|
"options",
|
||||||
"published",
|
"variants",
|
||||||
])
|
"published",
|
||||||
|
],
|
||||||
|
["variants"]
|
||||||
|
)
|
||||||
|
|
||||||
res.json(newProduct)
|
res.json({ product: data })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export default async (req, res) => {
|
|||||||
"variants",
|
"variants",
|
||||||
"published",
|
"published",
|
||||||
])
|
])
|
||||||
res.json(newProduct)
|
res.json({ product: newProduct })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export default async (req, res) => {
|
|||||||
"variants",
|
"variants",
|
||||||
"published",
|
"published",
|
||||||
])
|
])
|
||||||
res.json(data)
|
res.json({ product: data })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ describe("Get product by id", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns product decorated", () => {
|
it("returns product decorated", () => {
|
||||||
expect(subject.body._id).toEqual(IdMap.getId("product1"))
|
expect(subject.body.product._id).toEqual(IdMap.getId("product1"))
|
||||||
expect(subject.body.decorated).toEqual(true)
|
expect(subject.body.product.decorated).toEqual(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,16 +13,20 @@ export default async (req, res) => {
|
|||||||
const productService = req.scope.resolve("productService")
|
const productService = req.scope.resolve("productService")
|
||||||
let product = await productService.retrieve(value)
|
let product = await productService.retrieve(value)
|
||||||
|
|
||||||
product = await productService.decorate(product, [
|
product = await productService.decorate(
|
||||||
"title",
|
product,
|
||||||
"description",
|
[
|
||||||
"tags",
|
"title",
|
||||||
"handle",
|
"description",
|
||||||
"images",
|
"tags",
|
||||||
"options",
|
"handle",
|
||||||
"variants",
|
"images",
|
||||||
"published",
|
"options",
|
||||||
])
|
"variants",
|
||||||
|
"published",
|
||||||
|
],
|
||||||
|
["variants"]
|
||||||
|
)
|
||||||
|
|
||||||
res.json(product)
|
res.json(product)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,24 @@ export default async (req, res) => {
|
|||||||
const productService = req.scope.resolve("productService")
|
const productService = req.scope.resolve("productService")
|
||||||
const products = await productService.list(selector)
|
const products = await productService.list(selector)
|
||||||
|
|
||||||
res.json(products)
|
const data = await Promise.all(
|
||||||
|
products.map(p =>
|
||||||
|
productService.decorate(
|
||||||
|
p,
|
||||||
|
[
|
||||||
|
"title",
|
||||||
|
"description",
|
||||||
|
"tags",
|
||||||
|
"handle",
|
||||||
|
"images",
|
||||||
|
"options",
|
||||||
|
"variants",
|
||||||
|
"published",
|
||||||
|
],
|
||||||
|
["variants"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
res.json(data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ export const ProductModelMock = {
|
|||||||
}),
|
}),
|
||||||
deleteOne: jest.fn().mockReturnValue(Promise.resolve()),
|
deleteOne: jest.fn().mockReturnValue(Promise.resolve()),
|
||||||
findOne: jest.fn().mockImplementation(query => {
|
findOne: jest.fn().mockImplementation(query => {
|
||||||
|
if (query._id === IdMap.getId("fakeId")) {
|
||||||
|
return Promise.resolve({
|
||||||
|
_id: IdMap.getId("fakeId"),
|
||||||
|
title: "Product With Variants",
|
||||||
|
variants: ["1", "2", "3"],
|
||||||
|
})
|
||||||
|
}
|
||||||
if (query._id === IdMap.getId("productWithFourVariants")) {
|
if (query._id === IdMap.getId("productWithFourVariants")) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
_id: IdMap.getId("productWithFourVariants"),
|
_id: IdMap.getId("productWithFourVariants"),
|
||||||
|
|||||||
@@ -56,9 +56,16 @@ export const ProductServiceMock = {
|
|||||||
addOption: jest.fn().mockImplementation((productId, optionTitle) => {
|
addOption: jest.fn().mockImplementation((productId, optionTitle) => {
|
||||||
return Promise.resolve(products.productWithOptions)
|
return Promise.resolve(products.productWithOptions)
|
||||||
}),
|
}),
|
||||||
updateOption: jest.fn().mockReturnValue(Promise.resolve()),
|
updateOption: jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue(Promise.resolve(products.productWithOptions)),
|
||||||
updateOptionValue: jest.fn().mockReturnValue(Promise.resolve()),
|
updateOptionValue: jest.fn().mockReturnValue(Promise.resolve()),
|
||||||
deleteOption: jest.fn().mockReturnValue(Promise.resolve()),
|
deleteOption: jest.fn().mockReturnValue(Promise.resolve()),
|
||||||
|
retrieveVariants: jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue(
|
||||||
|
Promise.resolve([{ _id: IdMap.getId("1") }, { _id: IdMap.getId("2") }])
|
||||||
|
),
|
||||||
retrieve: jest.fn().mockImplementation(productId => {
|
retrieve: jest.fn().mockImplementation(productId => {
|
||||||
if (productId === IdMap.getId("product1")) {
|
if (productId === IdMap.getId("product1")) {
|
||||||
return Promise.resolve(products.product1)
|
return Promise.resolve(products.product1)
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ describe("ProductService", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const fakeProduct = {
|
const fakeProduct = {
|
||||||
_id: "1234",
|
_id: IdMap.getId("fakeId"),
|
||||||
variants: ["1", "2", "3"],
|
variants: ["1", "2", "3"],
|
||||||
tags: "testtag1, testtag2",
|
tags: "testtag1, testtag2",
|
||||||
handle: "test-product",
|
handle: "test-product",
|
||||||
@@ -148,7 +148,7 @@ describe("ProductService", () => {
|
|||||||
["variants"]
|
["variants"]
|
||||||
)
|
)
|
||||||
expect(decorated).toEqual({
|
expect(decorated).toEqual({
|
||||||
_id: "1234",
|
_id: IdMap.getId("fakeId"),
|
||||||
metadata: { testKey: "testValue" },
|
metadata: { testKey: "testValue" },
|
||||||
variants: [variants.one, variants.two, variants.three],
|
variants: [variants.one, variants.two, variants.three],
|
||||||
})
|
})
|
||||||
@@ -161,7 +161,7 @@ describe("ProductService", () => {
|
|||||||
["variants"]
|
["variants"]
|
||||||
)
|
)
|
||||||
expect(decorated).toEqual({
|
expect(decorated).toEqual({
|
||||||
_id: "1234",
|
_id: IdMap.getId("fakeId"),
|
||||||
metadata: { testKey: "testValue" },
|
metadata: { testKey: "testValue" },
|
||||||
handle: "test-product",
|
handle: "test-product",
|
||||||
variants: [variants.one, variants.two, variants.three],
|
variants: [variants.one, variants.two, variants.three],
|
||||||
@@ -174,7 +174,7 @@ describe("ProductService", () => {
|
|||||||
"tags",
|
"tags",
|
||||||
])
|
])
|
||||||
expect(decorated).toEqual({
|
expect(decorated).toEqual({
|
||||||
_id: "1234",
|
_id: IdMap.getId("fakeId"),
|
||||||
metadata: { testKey: "testValue" },
|
metadata: { testKey: "testValue" },
|
||||||
tags: "testtag1, testtag2",
|
tags: "testtag1, testtag2",
|
||||||
handle: "test-product",
|
handle: "test-product",
|
||||||
@@ -184,7 +184,7 @@ describe("ProductService", () => {
|
|||||||
it("returns decorated product with metadata", async () => {
|
it("returns decorated product with metadata", async () => {
|
||||||
const decorated = await productService.decorate(fakeProduct, [])
|
const decorated = await productService.decorate(fakeProduct, [])
|
||||||
expect(decorated).toEqual({
|
expect(decorated).toEqual({
|
||||||
_id: "1234",
|
_id: IdMap.getId("fakeId"),
|
||||||
metadata: { testKey: "testValue" },
|
metadata: { testKey: "testValue" },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -316,7 +316,7 @@ describe("ProductService", () => {
|
|||||||
productVariantService: ProductVariantServiceMock,
|
productVariantService: ProductVariantServiceMock,
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -350,7 +350,7 @@ describe("ProductService", () => {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(ProductModelMock.findOne).toBeCalledTimes(1)
|
expect(ProductModelMock.findOne).toBeCalledTimes(2)
|
||||||
expect(ProductModelMock.findOne).toBeCalledWith({
|
expect(ProductModelMock.findOne).toBeCalledWith({
|
||||||
_id: IdMap.getId("variantProductId"),
|
_id: IdMap.getId("variantProductId"),
|
||||||
})
|
})
|
||||||
@@ -362,6 +362,51 @@ describe("ProductService", () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("add variant to product successfully", async () => {
|
||||||
|
await productService.createVariant(
|
||||||
|
IdMap.getId("productWithFourVariants"),
|
||||||
|
{
|
||||||
|
title: "variant1",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
option_id: IdMap.getId("color_id"),
|
||||||
|
value: "blue",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
option_id: IdMap.getId("size_id"),
|
||||||
|
value: "1600",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(ProductVariantServiceMock.createDraft).toBeCalledTimes(1)
|
||||||
|
expect(ProductVariantServiceMock.createDraft).toBeCalledWith({
|
||||||
|
title: "variant1",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
option_id: IdMap.getId("color_id"),
|
||||||
|
value: "blue",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
option_id: IdMap.getId("size_id"),
|
||||||
|
value: "1600",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(ProductModelMock.findOne).toBeCalledTimes(2)
|
||||||
|
expect(ProductModelMock.findOne).toBeCalledWith({
|
||||||
|
_id: IdMap.getId("productWithFourVariants"),
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(ProductModelMock.updateOne).toBeCalledTimes(1)
|
||||||
|
expect(ProductModelMock.updateOne).toBeCalledWith(
|
||||||
|
{ _id: IdMap.getId("productWithFourVariants") },
|
||||||
|
{ $push: { variants: expect.stringMatching(/.*/) } }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it("throws error if option id is not present in product", async () => {
|
it("throws error if option id is not present in product", async () => {
|
||||||
await expect(
|
await expect(
|
||||||
productService.createVariant(IdMap.getId("variantProductId"), {
|
productService.createVariant(IdMap.getId("variantProductId"), {
|
||||||
|
|||||||
@@ -314,8 +314,8 @@ class ProductVariantService extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.productVariantModel_.updateOne(
|
return this.productVariantModel_.updateOne(
|
||||||
{ _id: variant._id, "options.option_id": optionId },
|
{ _id: variantId, "options.option_id": optionId },
|
||||||
{ $set: { "options.$.option_id": `${optionValue}` } }
|
{ $set: { "options.$.value": `${optionValue}` } }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,14 +202,17 @@ class ProductService extends BaseService {
|
|||||||
|
|
||||||
let combinationExists = false
|
let combinationExists = false
|
||||||
if (product.variants && product.variants.length) {
|
if (product.variants && product.variants.length) {
|
||||||
|
const variants = await this.retrieveVariants(productId)
|
||||||
// Check if option value of the variant to add already exists. Go through
|
// Check if option value of the variant to add already exists. Go through
|
||||||
// each existing variant. Check if this variants option values are
|
// each existing variant. Check if this variants option values are
|
||||||
// identical to the option values of the variant being added.
|
// identical to the option values of the variant being added.
|
||||||
combinationExists = product.variants.some(async vId => {
|
combinationExists = variants.some(v => {
|
||||||
const v = await this.productVariantService_.retrieve(vId)
|
return v.options.every(option => {
|
||||||
return v.options.reduce((acc, option, index) => {
|
const variantOption = variant.options.find(o =>
|
||||||
return acc && option.value === variant.options[index].value
|
option.option_id.equals(o.option_id)
|
||||||
}, true)
|
)
|
||||||
|
return option.value === variantOption.value
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,14 +443,14 @@ class ProductService extends BaseService {
|
|||||||
const firstVariant = await this.productVariantService_.retrieve(
|
const firstVariant = await this.productVariantService_.retrieve(
|
||||||
product.variants[0]
|
product.variants[0]
|
||||||
)
|
)
|
||||||
const valueToMatch = firstVariant.options.find(
|
const valueToMatch = firstVariant.options.find(o =>
|
||||||
o => o.option_id === optionId
|
o.option_id.equals(optionId)
|
||||||
).value
|
).value
|
||||||
|
|
||||||
const equalsFirst = await Promise.all(
|
const equalsFirst = await Promise.all(
|
||||||
product.variants.map(async vId => {
|
product.variants.map(async vId => {
|
||||||
const v = await this.productVariantService_.retrieve(vId)
|
const v = await this.productVariantService_.retrieve(vId)
|
||||||
const option = v.options.find(o => o.option_id === optionId)
|
const option = v.options.find(o => o.option_id.equals(optionId))
|
||||||
return option.value === valueToMatch
|
return option.value === valueToMatch
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -529,12 +532,12 @@ class ProductService extends BaseService {
|
|||||||
// Check if the variant's options are identical to the variant we
|
// Check if the variant's options are identical to the variant we
|
||||||
// are updating
|
// are updating
|
||||||
const hasMatchingOptions = v.options.every(option => {
|
const hasMatchingOptions = v.options.every(option => {
|
||||||
if (option.option_id === optionId) {
|
if (option.option_id.equals(optionId)) {
|
||||||
return option.value === value
|
return option.value === value
|
||||||
}
|
}
|
||||||
|
|
||||||
const toUpdateOption = toUpdate.options.find(
|
const toUpdateOption = toUpdate.options.find(o =>
|
||||||
o => o.option_id === option.option_id
|
option.option_id.equals(o.option_id)
|
||||||
)
|
)
|
||||||
return toUpdateOption.value === option.value
|
return toUpdateOption.value === option.value
|
||||||
})
|
})
|
||||||
@@ -567,11 +570,7 @@ class ProductService extends BaseService {
|
|||||||
const requiredFields = ["_id", "metadata"]
|
const requiredFields = ["_id", "metadata"]
|
||||||
const decorated = _.pick(product, fields.concat(requiredFields))
|
const decorated = _.pick(product, fields.concat(requiredFields))
|
||||||
if (expandFields.includes("variants")) {
|
if (expandFields.includes("variants")) {
|
||||||
decorated.variants = await Promise.all(
|
decorated.variants = await this.retrieveVariants(product._id)
|
||||||
product.variants.map(variantId =>
|
|
||||||
this.productVariantService_.retrieve(variantId)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return decorated
|
return decorated
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user