diff --git a/packages/medusa-interfaces/src/base-model.js b/packages/medusa-interfaces/src/base-model.js index 831b04956e..97920fb253 100644 --- a/packages/medusa-interfaces/src/base-model.js +++ b/packages/medusa-interfaces/src/base-model.js @@ -57,7 +57,7 @@ class BaseModel { * @return {?mongoose.Document} the retreived mongoose document or null. */ findOne(query, options = {}) { - return this.mongooseModel_.findOne(query, options) + return this.mongooseModel_.findOne(query, options).lean() } /** @@ -68,7 +68,7 @@ class BaseModel { * an empty array */ find(query, options) { - return this.mongooseModel_.find(query, options) + return this.mongooseModel_.find(query, options).lean() } /** @@ -80,7 +80,7 @@ class BaseModel { */ updateOne(query, update, options = {}) { options.new = true - return this.mongooseModel_.findOneAndUpdate(query, update, options) + return this.mongooseModel_.findOneAndUpdate(query, update, options).lean() } /** diff --git a/packages/medusa-test-utils/.eslintrc b/packages/medusa-test-utils/.eslintrc new file mode 100644 index 0000000000..2a889697f0 --- /dev/null +++ b/packages/medusa-test-utils/.eslintrc @@ -0,0 +1,9 @@ +{ + "plugins": ["prettier"], + "extends": ["prettier"], + "rules": { + "prettier/prettier": "error", + "semi": "error", + "no-unused-expressions": "true" + } +} diff --git a/packages/medusa/src/api/routes/admin/orders/__tests__/create-order.js b/packages/medusa/src/api/routes/admin/orders/__tests__/create-order.js index f210242999..3a68bab85e 100644 --- a/packages/medusa/src/api/routes/admin/orders/__tests__/create-order.js +++ b/packages/medusa/src/api/routes/admin/orders/__tests__/create-order.js @@ -21,6 +21,7 @@ describe("POST /admin/orders", () => { country_code: "US", province: "CA", postal_code: "93011", + phone: "+1 (222) 333 4444", }, shipping_address: { first_name: "Virgil", @@ -30,6 +31,7 @@ describe("POST /admin/orders", () => { country_code: "US", province: "CA", postal_code: "93011", + phone: "+1 (222) 333 4444", }, items: [ { @@ -90,6 +92,7 @@ describe("POST /admin/orders", () => { country_code: "US", province: "CA", postal_code: "93011", + phone: "+1 (222) 333 4444", }, shipping_address: { first_name: "Virgil", @@ -99,6 +102,7 @@ describe("POST /admin/orders", () => { country_code: "US", province: "CA", postal_code: "93011", + phone: "+1 (222) 333 4444", }, items: [ { diff --git a/packages/medusa/src/api/routes/admin/products/__tests__/delete-option.js b/packages/medusa/src/api/routes/admin/products/__tests__/delete-option.js index e77240935c..2b11908e88 100644 --- a/packages/medusa/src/api/routes/admin/products/__tests__/delete-option.js +++ b/packages/medusa/src/api/routes/admin/products/__tests__/delete-option.js @@ -1,6 +1,9 @@ import { IdMap } from "medusa-test-utils" import { request } from "../../../../../helpers/test-request" -import { ProductServiceMock } from "../../../../../services/__mocks__/product" +import { + ProductServiceMock, + products, +} from "../../../../../services/__mocks__/product" describe("DELETE /admin/products/:id/options/:optionId", () => { describe("successfully updates an option", () => { @@ -28,6 +31,7 @@ describe("DELETE /admin/products/:id/options/:optionId", () => { option_id: IdMap.getId("option1"), object: "option", deleted: true, + product: products.productWithOptions, }) }) diff --git a/packages/medusa/src/api/routes/admin/products/create-product.js b/packages/medusa/src/api/routes/admin/products/create-product.js index c4c7d700e5..d346c9e66f 100644 --- a/packages/medusa/src/api/routes/admin/products/create-product.js +++ b/packages/medusa/src/api/routes/admin/products/create-product.js @@ -46,7 +46,9 @@ export default async (req, res) => { const productService = req.scope.resolve("productService") const shippingProfileService = req.scope.resolve("shippingProfileService") - value.thumbnail = value.thumbnail || value.images[0] + if (!value.thumbnail && value.images && value.images.length) { + value.thumbnail = value.images[0] + } let newProduct = await productService.createDraft(value) if (variants) { diff --git a/packages/medusa/src/api/routes/admin/products/update-product.js b/packages/medusa/src/api/routes/admin/products/update-product.js index 505b6bbdc7..f4526c4afd 100644 --- a/packages/medusa/src/api/routes/admin/products/update-product.js +++ b/packages/medusa/src/api/routes/admin/products/update-product.js @@ -52,8 +52,13 @@ export default async (req, res) => { const productService = req.scope.resolve("productService") const oldProduct = await productService.retrieve(id) - if (!oldProduct.thumbnail && value.images) { - value.thumbnail = value.thumbnail || value.images[0] + if ( + !oldProduct.thumbnail && + !value.thumbnail && + value.images && + value.images.length + ) { + value.thumbnail = value.images[0] } const product = await productService.update(oldProduct._id, value) diff --git a/packages/medusa/src/api/routes/store/carts/__tests__/create-cart.js b/packages/medusa/src/api/routes/store/carts/__tests__/create-cart.js index 20841b58ec..9af2af862d 100644 --- a/packages/medusa/src/api/routes/store/carts/__tests__/create-cart.js +++ b/packages/medusa/src/api/routes/store/carts/__tests__/create-cart.js @@ -22,6 +22,8 @@ describe("POST /store/carts", () => { it("calls CartService create", () => { expect(CartServiceMock.create).toHaveBeenCalledTimes(1) expect(CartServiceMock.create).toHaveBeenCalledWith({ + email: "", + customer_id: "", region_id: IdMap.getId("testRegion"), }) }) diff --git a/packages/medusa/src/api/routes/store/carts/__tests__/update-cart.js b/packages/medusa/src/api/routes/store/carts/__tests__/update-cart.js index 91be6d326c..6bc1f081f6 100644 --- a/packages/medusa/src/api/routes/store/carts/__tests__/update-cart.js +++ b/packages/medusa/src/api/routes/store/carts/__tests__/update-cart.js @@ -14,6 +14,7 @@ describe("POST /store/carts/:id", () => { city: "Los Angeles", province: "CA", postal_code: "91092", + phone: "+1 (222) 333 4444", } beforeAll(async () => { @@ -73,8 +74,8 @@ describe("POST /store/carts/:id", () => { }) it("applies promo code", () => { - expect(CartServiceMock.applyPromoCode).toHaveBeenCalledTimes(1) - expect(CartServiceMock.applyPromoCode).toHaveBeenCalledWith( + expect(CartServiceMock.applyDiscount).toHaveBeenCalledTimes(1) + expect(CartServiceMock.applyDiscount).toHaveBeenCalledWith( IdMap.getId("emptyCart"), "TESTCODE" ) diff --git a/packages/medusa/src/api/routes/store/carts/__tests__/update-line-item.js b/packages/medusa/src/api/routes/store/carts/__tests__/update-line-item.js index 77b7121509..4816a29e69 100644 --- a/packages/medusa/src/api/routes/store/carts/__tests__/update-line-item.js +++ b/packages/medusa/src/api/routes/store/carts/__tests__/update-line-item.js @@ -8,14 +8,13 @@ describe("POST /store/carts/:id/line-items/:line_id", () => { let subject beforeAll(async () => { - const cartId = IdMap.getId("emptyCart") + const cartId = IdMap.getId("fr-cart") const lineId = IdMap.getId("existingLine") subject = await request( "POST", `/store/carts/${cartId}/line-items/${lineId}`, { payload: { - variant_id: IdMap.getId("can-cover"), quantity: 3, }, } @@ -33,9 +32,9 @@ describe("POST /store/carts/:id/line-items/:line_id", () => { it("calls LineItemService generate", () => { expect(LineItemServiceMock.generate).toHaveBeenCalledTimes(1) expect(LineItemServiceMock.generate).toHaveBeenCalledWith( - IdMap.getId("can-cover"), - 3, - IdMap.getId("testRegion") + IdMap.getId("eur-10-us-12"), + IdMap.getId("region-france"), + 3 ) }) @@ -44,25 +43,23 @@ describe("POST /store/carts/:id/line-items/:line_id", () => { }) it("returns the cart", () => { - expect(subject.body.cart._id).toEqual(IdMap.getId("emptyCart")) + expect(subject.body.cart._id).toEqual(IdMap.getId("fr-cart")) expect(subject.body.cart.decorated).toEqual(true) }) }) - describe("handles unsuccessful line item generation", () => { + describe("removes line item on quantity 0", () => { let subject beforeAll(async () => { - const cartId = IdMap.getId("emptyCart") + const cartId = IdMap.getId("fr-cart") const lineId = IdMap.getId("existingLine") - subject = await request( "POST", `/store/carts/${cartId}/line-items/${lineId}`, { payload: { - variant_id: IdMap.getId("fail"), - quantity: 3, + quantity: 0, }, } ) @@ -72,21 +69,21 @@ describe("POST /store/carts/:id/line-items/:line_id", () => { jest.clearAllMocks() }) - it("calls LineItemService generate", () => { - expect(LineItemServiceMock.generate).toHaveBeenCalledTimes(1) - expect(LineItemServiceMock.generate).toHaveBeenCalledWith( - IdMap.getId("fail"), - 3, - IdMap.getId("testRegion") + it("calls CartService create", () => { + expect(CartServiceMock.removeLineItem).toHaveBeenCalledTimes(1) + expect(CartServiceMock.removeLineItem).toHaveBeenCalledWith( + IdMap.getId("fr-cart"), + IdMap.getId("existingLine") ) }) - it("returns 400", () => { - expect(subject.status).toEqual(400) + it("returns 200", () => { + expect(subject.status).toEqual(200) }) - it("returns error", () => { - expect(subject.body.message).toEqual("Doesn't exist") + it("returns the cart", () => { + expect(subject.body.cart._id).toEqual(IdMap.getId("fr-cart")) + expect(subject.body.cart.decorated).toEqual(true) }) }) }) diff --git a/packages/medusa/src/api/routes/store/carts/__tests__/update-payment-method.js b/packages/medusa/src/api/routes/store/carts/__tests__/update-payment-method.js index d151cbc011..7ec1ba34fe 100644 --- a/packages/medusa/src/api/routes/store/carts/__tests__/update-payment-method.js +++ b/packages/medusa/src/api/routes/store/carts/__tests__/update-payment-method.js @@ -12,6 +12,9 @@ describe("POST /store/carts/:id/payment-method", () => { subject = await request("POST", `/store/carts/${cartId}/payment-method`, { payload: { provider_id: "default_provider", + data: { + money_id: "success", + }, }, }) }) @@ -20,14 +23,6 @@ describe("POST /store/carts/:id/payment-method", () => { jest.clearAllMocks() }) - it("calls CartService retrievePaymentSession", () => { - expect(CartServiceMock.retrievePaymentSession).toHaveBeenCalledTimes(1) - expect(CartServiceMock.retrievePaymentSession).toHaveBeenCalledWith( - IdMap.getId("cartWithPaySessions"), - "default_provider" - ) - }) - it("calls CartService setPaymentMethod", () => { expect(CartServiceMock.setPaymentMethod).toHaveBeenCalledTimes(1) expect(CartServiceMock.setPaymentMethod).toHaveBeenCalledWith( @@ -50,50 +45,4 @@ describe("POST /store/carts/:id/payment-method", () => { expect(subject.body.cart.decorated).toEqual(true) }) }) - - describe("fails when pay session not authorized", () => { - let subject - - beforeAll(async () => { - const cartId = IdMap.getId("cartWithPaySessions") - subject = await request("POST", `/store/carts/${cartId}/payment-method`, { - payload: { - provider_id: "nono", - }, - }) - }) - - afterAll(() => { - jest.clearAllMocks() - }) - - it("calls CartService retrievePaymentSession", () => { - expect(CartServiceMock.retrievePaymentSession).toHaveBeenCalledTimes(1) - expect(CartServiceMock.retrievePaymentSession).toHaveBeenCalledWith( - IdMap.getId("cartWithPaySessions"), - "nono" - ) - }) - - it("calls CartService setPaymentMethod", () => { - expect(CartServiceMock.setPaymentMethod).toHaveBeenCalledTimes(1) - expect(CartServiceMock.setPaymentMethod).toHaveBeenCalledWith( - IdMap.getId("cartWithPaySessions"), - { - provider_id: "nono", - data: { - money_id: "fail", - }, - } - ) - }) - - it("returns 400", () => { - expect(subject.status).toEqual(400) - }) - - it("returns the cart", () => { - expect(subject.body.message).toEqual("Not allowed") - }) - }) }) diff --git a/packages/medusa/src/api/routes/store/carts/update-line-item.js b/packages/medusa/src/api/routes/store/carts/update-line-item.js index 4c500064ae..5db4dcf80a 100644 --- a/packages/medusa/src/api/routes/store/carts/update-line-item.js +++ b/packages/medusa/src/api/routes/store/carts/update-line-item.js @@ -9,6 +9,7 @@ export default async (req, res) => { const { value, error } = schema.validate(req.body) if (error) { + console.log(error) throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details) } @@ -23,6 +24,13 @@ export default async (req, res) => { cart = await cartService.retrieve(id) const existing = cart.items.find(i => i._id.equals(line_id)) + if (!existing) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + "Could not find the line item" + ) + } + const lineItem = await lineItemService.generate( existing.content.variant._id, cart.region_id, diff --git a/packages/medusa/src/api/routes/store/customers/__tests__/update-password.js b/packages/medusa/src/api/routes/store/customers/__tests__/update-password.js deleted file mode 100644 index 0882ec89d0..0000000000 --- a/packages/medusa/src/api/routes/store/customers/__tests__/update-password.js +++ /dev/null @@ -1,73 +0,0 @@ -import { IdMap } from "medusa-test-utils" -import { request } from "../../../../../helpers/test-request" -import { CustomerServiceMock } from "../../../../../services/__mocks__/customer" - -describe("POST /store/customers/:id/password", () => { - describe("successfully updates a customer", () => { - let subject - beforeAll(async () => { - subject = await request( - "POST", - `/store/customers/${IdMap.getId("lebron")}/password`, - { - payload: { - password: "NewPass", - }, - clientSession: { - jwt: { - customer_id: IdMap.getId("lebron"), - }, - }, - } - ) - }) - - afterAll(() => { - jest.clearAllMocks() - }) - - it("calls CustomerService update", () => { - expect(CustomerServiceMock.update).toHaveBeenCalledTimes(1) - expect(CustomerServiceMock.update).toHaveBeenCalledWith( - IdMap.getId("lebron"), - { - password: "NewPass", - } - ) - }) - - it("returns product decorated", () => { - expect(subject.body.customer.first_name).toEqual("LeBron") - expect(subject.body.customer.decorated).toEqual(true) - }) - }) - - describe("fails if not authenticated", () => { - let subject - beforeAll(async () => { - subject = await request( - "POST", - `/store/customers/${IdMap.getId("customer1")}/password`, - { - payload: { - first_name: "LeBron", - last_name: "James", - }, - clientSession: { - jwt: { - customer_id: IdMap.getId("lebron"), - }, - }, - } - ) - }) - - afterAll(() => { - jest.clearAllMocks() - }) - - it("status code 400", () => { - expect(subject.status).toEqual(400) - }) - }) -}) diff --git a/packages/medusa/src/api/routes/store/orders/__tests__/create-order.js b/packages/medusa/src/api/routes/store/orders/__tests__/create-order.js index 100f4a3a5f..1cc93d7a5d 100644 --- a/packages/medusa/src/api/routes/store/orders/__tests__/create-order.js +++ b/packages/medusa/src/api/routes/store/orders/__tests__/create-order.js @@ -12,11 +12,6 @@ describe("POST /store/orders", () => { payload: { cartId: IdMap.getId("fr-cart"), }, - adminSession: { - jwt: { - userId: IdMap.getId("admin_user"), - }, - }, }) }) @@ -25,8 +20,8 @@ describe("POST /store/orders", () => { }) it("calls service create", () => { - expect(OrderServiceMock.create).toHaveBeenCalledTimes(1) - expect(OrderServiceMock.create).toHaveBeenCalledWith(carts.frCart) + expect(OrderServiceMock.createFromCart).toHaveBeenCalledTimes(1) + expect(OrderServiceMock.createFromCart).toHaveBeenCalledWith(carts.frCart) }) }) }) diff --git a/packages/medusa/src/api/routes/store/orders/create-order.js b/packages/medusa/src/api/routes/store/orders/create-order.js index 2c09bf7548..1ddaf6c5d7 100644 --- a/packages/medusa/src/api/routes/store/orders/create-order.js +++ b/packages/medusa/src/api/routes/store/orders/create-order.js @@ -16,8 +16,6 @@ export default async (req, res) => { const cart = await cartService.retrieve(value.cartId) let order = await orderService.createFromCart(cart) - - order = await orderService.retrieveByCartId(value.cartId) order = await orderService.decorate(order, [ "status", "fulfillment_status", @@ -36,6 +34,7 @@ export default async (req, res) => { res.status(200).json({ order }) } catch (err) { + console.log(err) // If something fails it might be because the order has already been created // if it has we find it from the cart id const orderService = req.scope.resolve("orderService") diff --git a/packages/medusa/src/api/routes/store/shipping-options/__tests__/get-shipping-options.js b/packages/medusa/src/api/routes/store/shipping-options/__tests__/list-shipping-options.js similarity index 89% rename from packages/medusa/src/api/routes/store/shipping-options/__tests__/get-shipping-options.js rename to packages/medusa/src/api/routes/store/shipping-options/__tests__/list-shipping-options.js index 7544d70bf4..da2686f982 100644 --- a/packages/medusa/src/api/routes/store/shipping-options/__tests__/get-shipping-options.js +++ b/packages/medusa/src/api/routes/store/shipping-options/__tests__/list-shipping-options.js @@ -8,11 +8,10 @@ describe("GET /store/shipping-options", () => { let subject beforeAll(async () => { - subject = await request("GET", `/store/shipping-options`, { - payload: { - cart_id: IdMap.getId("emptyCart"), - }, - }) + subject = await request( + "GET", + `/store/shipping-options/${IdMap.getId("emptyCart")}` + ) }) afterAll(() => { diff --git a/packages/medusa/src/models/__mocks__/cart.js b/packages/medusa/src/models/__mocks__/cart.js index f3a0e0bcb8..238953e88d 100644 --- a/packages/medusa/src/models/__mocks__/cart.js +++ b/packages/medusa/src/models/__mocks__/cart.js @@ -168,13 +168,21 @@ export const carts = { }, completeCart: { _id: IdMap.getId("complete-cart"), - title: "test", region_id: IdMap.getId("region-france"), items: [], + email: "test", + payment_sessions: [ + { + provider_id: "default_provider", + data: { + money_id: "success", + }, + }, + ], payment_method: { - provider_id: "stripe", + provider_id: "default_provider", data: { - yes: "sir", + money_id: "success", }, }, shipping_methods: [ @@ -259,7 +267,7 @@ export const carts = { shipping_methods: [ { _id: IdMap.getId("freeShipping"), - profile_id: "default_profile", + profile_id: IdMap.getId("default_profile"), }, ], shipping_options: [ diff --git a/packages/medusa/src/models/__mocks__/order.js b/packages/medusa/src/models/__mocks__/order.js index 67530bf4e4..5b8d16be3e 100644 --- a/packages/medusa/src/models/__mocks__/order.js +++ b/packages/medusa/src/models/__mocks__/order.js @@ -209,11 +209,16 @@ export const orders = { } export const OrderModelMock = { - create: jest.fn().mockReturnValue(Promise.resolve()), + create: jest.fn().mockImplementation(data => Promise.resolve(data)), updateOne: jest.fn().mockImplementation((query, update) => { return Promise.resolve() }), deleteOne: jest.fn().mockReturnValue(Promise.resolve()), + startSession: jest.fn().mockReturnValue( + Promise.resolve({ + withTransaction: fn => fn(), + }) + ), findOne: jest.fn().mockImplementation(query => { if (query._id === IdMap.getId("test-order")) { orders.testOrder.payment_status = "awaiting" @@ -240,7 +245,7 @@ export const OrderModelMock = { orders.orderToRefund.payment_status = "captured" return Promise.resolve(orders.orderToRefund) } - if (query.metadata.cart_id === IdMap.getId("test-cart")) { + if (query.cart_id === IdMap.getId("test-cart")) { return Promise.resolve(orders.testOrder) } return Promise.resolve(undefined) diff --git a/packages/medusa/src/services/__mocks__/cart.js b/packages/medusa/src/services/__mocks__/cart.js index 4d8b8c61c7..be59dbebbc 100644 --- a/packages/medusa/src/services/__mocks__/cart.js +++ b/packages/medusa/src/services/__mocks__/cart.js @@ -215,13 +215,40 @@ export const CartServiceMock = { }), setPaymentMethod: jest.fn().mockImplementation((cartId, method) => { if (method.provider_id === "default_provider") { - return Promise.resolve() + return Promise.resolve(carts.cartWithPaySessions) } throw new MedusaError(MedusaError.Types.NOT_ALLOWED, "Not allowed") }), + removeLineItem: jest.fn().mockImplementation((cartId, lineItem) => { + if (cartId === IdMap.getId("fr-cart")) { + return Promise.resolve(carts.frCart) + } + if (cartId === IdMap.getId("regionCart")) { + return Promise.resolve(carts.regionCart) + } + if (cartId === IdMap.getId("emptyCart")) { + return Promise.resolve(carts.emptyCart) + } + if (cartId === IdMap.getId("cartWithPaySessions")) { + return Promise.resolve(carts.cartWithPaySessions) + } + throw new MedusaError(MedusaError.Types.NOT_FOUND, "cart not found") + }), updateLineItem: jest.fn().mockImplementation((cartId, lineItem) => { - return Promise.resolve() + if (cartId === IdMap.getId("fr-cart")) { + return Promise.resolve(carts.frCart) + } + if (cartId === IdMap.getId("regionCart")) { + return Promise.resolve(carts.regionCart) + } + if (cartId === IdMap.getId("emptyCart")) { + return Promise.resolve(carts.emptyCart) + } + if (cartId === IdMap.getId("cartWithPaySessions")) { + return Promise.resolve(carts.cartWithPaySessions) + } + throw new MedusaError(MedusaError.Types.NOT_FOUND, "cart not found") }), setRegion: jest.fn().mockImplementation((cartId, regionId) => { if (regionId === IdMap.getId("fail")) { @@ -238,7 +265,7 @@ export const CartServiceMock = { updateBillingAddress: jest.fn().mockImplementation((cartId, address) => { return Promise.resolve() }), - applyPromoCode: jest.fn().mockImplementation((cartId, code) => { + applyDiscount: jest.fn().mockImplementation((cartId, code) => { return Promise.resolve() }), setPaymentSessions: jest.fn().mockImplementation(cartId => { diff --git a/packages/medusa/src/services/__mocks__/customer.js b/packages/medusa/src/services/__mocks__/customer.js index 195bb4e674..4d19c6007c 100644 --- a/packages/medusa/src/services/__mocks__/customer.js +++ b/packages/medusa/src/services/__mocks__/customer.js @@ -35,6 +35,13 @@ export const CustomerServiceMock = { password_hash: "1234", }) } + if (email === "test@testdom.com") { + return Promise.resolve({ + _id: IdMap.getId("testdom"), + email, + password_hash: "1234", + }) + } if (email === "oliver@test.dk") { return bcrypt .hash("123456789", 10) diff --git a/packages/medusa/src/services/__mocks__/line-item.js b/packages/medusa/src/services/__mocks__/line-item.js index 5b9d5dbb8c..a459e534e2 100644 --- a/packages/medusa/src/services/__mocks__/line-item.js +++ b/packages/medusa/src/services/__mocks__/line-item.js @@ -8,7 +8,28 @@ export const LineItemServiceMock = { } return data }), - generate: jest.fn().mockImplementation((variantId, quantity, regionId) => { + isEqual: jest.fn().mockImplementation((line, match) => { + if (Array.isArray(line.content)) { + if ( + Array.isArray(match.content) && + match.content.length === line.content.length + ) { + return line.content.every( + (c, index) => + c.variant._id === match[index].variant._id && + c.quantity === match[index].quantity + ) + } + } else if (!Array.isArray(match.content)) { + return ( + line.content.variant._id === match.content.variant._id && + line.content.quantity === match.content.quantity + ) + } + + return false + }), + generate: jest.fn().mockImplementation((variantId, regionId, quantity) => { if (variantId === IdMap.getId("fail") || regionId === IdMap.getId("fail")) { throw new MedusaError(MedusaError.Types.INVALID_DATA, "Doesn't exist") } diff --git a/packages/medusa/src/services/__mocks__/order.js b/packages/medusa/src/services/__mocks__/order.js index 0d3eee56fa..428fe94f9b 100644 --- a/packages/medusa/src/services/__mocks__/order.js +++ b/packages/medusa/src/services/__mocks__/order.js @@ -125,6 +125,9 @@ export const OrderServiceMock = { create: jest.fn().mockImplementation(data => { return Promise.resolve(orders.testOrder) }), + createFromCart: jest.fn().mockImplementation(data => { + return Promise.resolve(orders.testOrder) + }), update: jest.fn().mockImplementation(data => Promise.resolve()), retrieve: jest.fn().mockImplementation(orderId => { if (orderId === IdMap.getId("test-order")) { @@ -135,6 +138,9 @@ export const OrderServiceMock = { } return Promise.resolve(undefined) }), + retrieveByCartId: jest.fn().mockImplementation(cartId => { + return Promise.resolve() + }), decorate: jest.fn().mockImplementation(order => { order.decorated = true return order diff --git a/packages/medusa/src/services/__mocks__/payment-provider.js b/packages/medusa/src/services/__mocks__/payment-provider.js index 8f705a58be..e4a1030f09 100644 --- a/packages/medusa/src/services/__mocks__/payment-provider.js +++ b/packages/medusa/src/services/__mocks__/payment-provider.js @@ -10,6 +10,9 @@ export const DefaultProviderMock = { return Promise.resolve("initial") }), + retrievePayment: jest.fn().mockImplementation(data => { + return Promise.resolve(data) + }), capturePayment: jest.fn().mockReturnValue(Promise.resolve()), refundPayment: jest.fn().mockReturnValue(Promise.resolve()), } diff --git a/packages/medusa/src/services/__mocks__/product.js b/packages/medusa/src/services/__mocks__/product.js index 29cfbc6ea2..e7514af73f 100644 --- a/packages/medusa/src/services/__mocks__/product.js +++ b/packages/medusa/src/services/__mocks__/product.js @@ -60,7 +60,9 @@ export const ProductServiceMock = { .fn() .mockReturnValue(Promise.resolve(products.productWithOptions)), updateOptionValue: jest.fn().mockReturnValue(Promise.resolve()), - deleteOption: jest.fn().mockReturnValue(Promise.resolve()), + deleteOption: jest + .fn() + .mockReturnValue(Promise.resolve(products.productWithOptions)), retrieveVariants: jest .fn() .mockReturnValue( @@ -84,8 +86,8 @@ export const ProductServiceMock = { } return Promise.resolve(undefined) }), - update: jest.fn().mockImplementation((userId, data) => { - return Promise.resolve() + update: jest.fn().mockImplementation((product, data) => { + return Promise.resolve(products.product1) }), list: jest.fn().mockImplementation(data => { // Used to retrieve a product based on a variant id see diff --git a/packages/medusa/src/services/__mocks__/shipping-profile.js b/packages/medusa/src/services/__mocks__/shipping-profile.js index c94b917535..68f76af3d4 100644 --- a/packages/medusa/src/services/__mocks__/shipping-profile.js +++ b/packages/medusa/src/services/__mocks__/shipping-profile.js @@ -42,10 +42,10 @@ export const ShippingProfileServiceMock = { return Promise.resolve([]) } if (selector.shipping_options === IdMap.getId("freeShipping")) { - return Promise.resolve([{ _id: "default_profile" }]) + return Promise.resolve([{ _id: IdMap.getId("default_profile") }]) } if (selector.shipping_options === IdMap.getId("additional")) { - return Promise.resolve([{ _id: "additional_profile" }]) + return Promise.resolve([{ _id: IdMap.getId("additional_profile") }]) } if ( selector.products && diff --git a/packages/medusa/src/services/__tests__/cart.js b/packages/medusa/src/services/__tests__/cart.js index 671ec0b421..2d538ae06f 100644 --- a/packages/medusa/src/services/__tests__/cart.js +++ b/packages/medusa/src/services/__tests__/cart.js @@ -8,6 +8,7 @@ import { import { ProductVariantServiceMock } from "../__mocks__/product-variant" import { RegionServiceMock } from "../__mocks__/region" import { EventBusServiceMock } from "../__mocks__/event-bus" +import { CustomerServiceMock } from "../__mocks__/customer" import { ShippingOptionServiceMock } from "../__mocks__/shipping-option" import { ShippingProfileServiceMock } from "../__mocks__/shipping-profile" import { CartModelMock, carts } from "../../models/__mocks__/cart" @@ -497,6 +498,7 @@ describe("CartService", () => { const cartService = new CartService({ cartModel: CartModelMock, eventBusService: EventBusServiceMock, + customerService: CustomerServiceMock, }) beforeEach(() => { @@ -509,7 +511,11 @@ describe("CartService", () => { "test@testdom.com" ) - expect(EventBusServiceMock.emit).toHaveBeenCalledTimes(1) + expect(EventBusServiceMock.emit).toHaveBeenCalledTimes(2) + expect(EventBusServiceMock.emit).toHaveBeenCalledWith( + "cart.customer_updated", + expect.any(Object) + ) expect(EventBusServiceMock.emit).toHaveBeenCalledWith( "cart.updated", expect.any(Object) @@ -521,7 +527,10 @@ describe("CartService", () => { _id: IdMap.getId("emptyCart"), }, { - $set: { email: "test@testdom.com" }, + $set: { + email: "test@testdom.com", + customer_id: IdMap.getId("testdom"), + }, } ) }) @@ -556,6 +565,7 @@ describe("CartService", () => { country_code: "US", province: "CA", postal_code: "93011", + phone: "+1 (222) 333 4444", } await cartService.updateBillingAddress(IdMap.getId("emptyCart"), address) @@ -593,7 +603,7 @@ describe("CartService", () => { address ) } catch (err) { - expect(err.message).toEqual("The address is not valid") + expect(err.message).toEqual(`"first_name" is required`) } expect(CartModelMock.updateOne).toHaveBeenCalledTimes(0) @@ -620,6 +630,7 @@ describe("CartService", () => { country_code: "US", province: "CA", postal_code: "93011", + phone: "+1 (222) 333 4444", } await cartService.updateShippingAddress(IdMap.getId("emptyCart"), address) @@ -650,6 +661,7 @@ describe("CartService", () => { country_code: "ru", province: "CA", postal_code: "93011", + phone: "+1 (222) 333 4444", } await expect( @@ -672,7 +684,7 @@ describe("CartService", () => { await expect( cartService.updateShippingAddress(IdMap.getId("emptyCart"), address) - ).rejects.toThrow("The address is not valid") + ).rejects.toThrow(`"first_name" is required`) expect(CartModelMock.updateOne).toHaveBeenCalledTimes(0) }) @@ -779,19 +791,12 @@ describe("CartService", () => { $set: { region_id: IdMap.getId("region-us"), shipping_methods: [], + payment_sessions: [], payment_method: undefined, shipping_address: { first_name: "hi", last_name: "you", - country_code: "", - city: "of lights", - address_1: "You bet street", - postal_code: "4242", - }, - billing_address: { - first_name: "hi", - last_name: "you", - country_code: "", + country_code: "US", city: "of lights", address_1: "You bet street", postal_code: "4242", @@ -858,17 +863,6 @@ describe("CartService", () => { IdMap.getId("testRegion") ) - expect(PaymentProviderServiceMock.retrieveProvider).toHaveBeenCalledTimes( - 1 - ) - expect(PaymentProviderServiceMock.retrieveProvider).toHaveBeenCalledWith( - "default_provider" - ) - expect(DefaultProviderMock.getStatus).toHaveBeenCalledTimes(1) - expect(DefaultProviderMock.getStatus).toHaveBeenCalledWith({ - money_id: "success", - }) - expect(CartModelMock.updateOne).toHaveBeenCalledTimes(1) expect(CartModelMock.updateOne).toHaveBeenCalledWith( { @@ -904,71 +898,6 @@ describe("CartService", () => { ) } }) - - it("fails if the payment provider is not registered", async () => { - const paymentMethod = { - provider_id: "unregistered", - data: { - money_id: "success", - }, - } - - try { - await cartService.setPaymentMethod( - IdMap.getId("cartWithLine"), - paymentMethod - ) - } catch (err) { - expect(RegionServiceMock.retrieve).toHaveBeenCalledTimes(1) - expect(RegionServiceMock.retrieve).toHaveBeenCalledWith( - IdMap.getId("testRegion") - ) - - expect( - PaymentProviderServiceMock.retrieveProvider - ).toHaveBeenCalledTimes(1) - expect( - PaymentProviderServiceMock.retrieveProvider - ).toHaveBeenCalledWith("unregistered") - - expect(err.message).toEqual(`Provider Not Found`) - } - }) - - it("fails if the payment is not authorized", async () => { - const paymentMethod = { - provider_id: "default_provider", - data: { - money_id: "fail", - }, - } - - try { - await cartService.setPaymentMethod( - IdMap.getId("cartWithLine"), - paymentMethod - ) - } catch (err) { - expect(RegionServiceMock.retrieve).toHaveBeenCalledTimes(1) - expect(RegionServiceMock.retrieve).toHaveBeenCalledWith( - IdMap.getId("testRegion") - ) - - expect( - PaymentProviderServiceMock.retrieveProvider - ).toHaveBeenCalledTimes(1) - expect( - PaymentProviderServiceMock.retrieveProvider - ).toHaveBeenCalledWith("default_provider") - - expect(DefaultProviderMock.getStatus).toHaveBeenCalledTimes(1) - expect(DefaultProviderMock.getStatus).toHaveBeenCalledWith({ - money_id: "fail", - }) - - expect(err.message).toEqual(`The payment method was not authorized`) - } - }) }) describe("setPaymentSessions", () => { @@ -1259,7 +1188,7 @@ describe("CartService", () => { _id: IdMap.getId("freeShipping"), price: 0, provider_id: "default_provider", - profile_id: "default_profile", + profile_id: IdMap.getId("default_profile"), data, }, ], @@ -1297,7 +1226,7 @@ describe("CartService", () => { _id: IdMap.getId("freeShipping"), price: 0, provider_id: "default_provider", - profile_id: "default_profile", + profile_id: IdMap.getId("default_profile"), data: { id: "testshipperid", }, @@ -1335,12 +1264,12 @@ describe("CartService", () => { shipping_methods: [ { _id: IdMap.getId("freeShipping"), - profile_id: "default_profile", + profile_id: IdMap.getId("default_profile"), }, { _id: IdMap.getId("additional"), price: 0, - profile_id: "additional_profile", + profile_id: IdMap.getId("additional_profile"), provider_id: "default_provider", data, }, diff --git a/packages/medusa/src/services/__tests__/customer.js b/packages/medusa/src/services/__tests__/customer.js index ccdd9bc444..db0246556b 100644 --- a/packages/medusa/src/services/__tests__/customer.js +++ b/packages/medusa/src/services/__tests__/customer.js @@ -107,7 +107,7 @@ describe("CustomerService", () => { it("calls model layer create", async () => { await customerService.create({ - email: "oliver@medusa.com", + email: "new@medusa.com", first_name: "Oliver", last_name: "Juhl", password: "secretsauce", @@ -115,7 +115,7 @@ describe("CustomerService", () => { expect(CustomerModelMock.create).toBeCalledTimes(1) expect(CustomerModelMock.create).toBeCalledWith({ - email: "oliver@medusa.com", + email: "new@medusa.com", first_name: "Oliver", last_name: "Juhl", has_account: true, @@ -200,6 +200,7 @@ describe("CustomerService", () => { city: "Copenhagen", country_code: "DK", postal_code: "2100", + phone: "+1 (222) 333 4444", }, }) @@ -217,6 +218,7 @@ describe("CustomerService", () => { city: "Copenhagen", country_code: "DK", postal_code: "2100", + phone: "+1 (222) 333 4444", }, }, }, diff --git a/packages/medusa/src/services/__tests__/order.js b/packages/medusa/src/services/__tests__/order.js index 8bee6106ab..8ee3ac0fcd 100644 --- a/packages/medusa/src/services/__tests__/order.js +++ b/packages/medusa/src/services/__tests__/order.js @@ -6,6 +6,7 @@ import { PaymentProviderServiceMock } from "../__mocks__/payment-provider" import { FulfillmentProviderServiceMock } from "../__mocks__/fulfillment-provider" import { ShippingProfileServiceMock } from "../__mocks__/shipping-profile" import { TotalsServiceMock } from "../__mocks__/totals" +import { RegionServiceMock } from "../__mocks__/region" import { EventBusServiceMock } from "../__mocks__/event-bus" describe("OrderService", () => { @@ -34,6 +35,8 @@ describe("OrderService", () => { describe("createFromCart", () => { const orderService = new OrderService({ orderModel: OrderModelMock, + paymentProviderService: PaymentProviderServiceMock, + regionService: RegionServiceMock, eventBusService: EventBusServiceMock, }) @@ -44,10 +47,17 @@ describe("OrderService", () => { it("calls order model functions", async () => { await orderService.createFromCart(carts.completeCart) - expect(OrderModelMock.create).toHaveBeenCalledTimes(1) - expect(OrderModelMock.create).toHaveBeenCalledWith({ + const order = { ...carts.completeCart, - metadata: { cart_id: carts.completeCart._id }, + currency_code: "eur", + cart_id: carts.completeCart._id, + } + delete order._id + delete order.payment_sessions + + expect(OrderModelMock.create).toHaveBeenCalledTimes(1) + expect(OrderModelMock.create).toHaveBeenCalledWith([order], { + session: expect.anything(), }) }) }) @@ -89,7 +99,7 @@ describe("OrderService", () => { it("calls order model functions", async () => { expect(OrderModelMock.findOne).toHaveBeenCalledTimes(1) expect(OrderModelMock.findOne).toHaveBeenCalledWith({ - metadata: { cart_id: IdMap.getId("test-cart") }, + cart_id: IdMap.getId("test-cart"), }) }) diff --git a/packages/medusa/src/services/__tests__/product.js b/packages/medusa/src/services/__tests__/product.js index a421db6867..355714552f 100644 --- a/packages/medusa/src/services/__tests__/product.js +++ b/packages/medusa/src/services/__tests__/product.js @@ -281,17 +281,6 @@ describe("ProductService", () => { expect(err.message).toEqual("Use setMetadata to update metadata fields") } }) - - it("throws error when trying to update variants", async () => { - const id = mongoose.Types.ObjectId() - try { - await productService.update(`${id}`, { variants: ["1", "2"] }) - } catch (err) { - expect(err.message).toEqual( - "Use addVariant, reorderVariants, removeVariant to update Product Variants" - ) - } - }) }) describe("delete", () => { diff --git a/packages/medusa/src/services/__tests__/user.js b/packages/medusa/src/services/__tests__/user.js index c68991639d..4cecb0f4d6 100644 --- a/packages/medusa/src/services/__tests__/user.js +++ b/packages/medusa/src/services/__tests__/user.js @@ -3,6 +3,7 @@ import jwt from "jsonwebtoken" import { IdMap } from "medusa-test-utils" import UserService from "../user" import { UserModelMock, users } from "../../models/__mocks__/user" +import { EventBusServiceMock } from "../__mocks__/event-bus" describe("UserService", () => { describe("retrieve", () => { @@ -144,6 +145,7 @@ describe("UserService", () => { describe("generateResetPasswordToken", () => { const userService = new UserService({ + eventBusService: EventBusServiceMock, userModel: UserModelMock, }) diff --git a/packages/medusa/src/services/cart.js b/packages/medusa/src/services/cart.js index 61b91ab65f..398965ba50 100644 --- a/packages/medusa/src/services/cart.js +++ b/packages/medusa/src/services/cart.js @@ -237,7 +237,7 @@ class CartService extends BaseService { * @return {Cart} return the decorated cart. */ async decorate(cart, fields, expandFields = []) { - const c = cart.toObject() + const c = cart c.shipping_total = await this.totalsService_.getShippingTotal(cart) c.discount_total = await this.totalsService_.getDiscountTotal(cart) c.tax_total = await this.totalsService_.getTaxTotal(cart) @@ -1054,11 +1054,14 @@ class CartService extends BaseService { // Payment methods are region specific so the user needs to find a // new payment method - if (!_.isEmpty(cart.payment_method) || cart.payment_sessions.length) { - update.payment_sessions = [] + if (!_.isEmpty(cart.payment_method)) { update.payment_method = undefined } + if (cart.payment_sessions && cart.payment_sessions.length) { + update.payment_sessions = [] + } + return this.cartModel_ .updateOne({ _id: cart._id }, { $set: update }) .then(result => { diff --git a/packages/medusa/src/services/order.js b/packages/medusa/src/services/order.js index 34a133a3a9..ca94926ac1 100644 --- a/packages/medusa/src/services/order.js +++ b/packages/medusa/src/services/order.js @@ -264,9 +264,16 @@ class OrderService extends BaseService { ) } - const { payment_method } = cart + const { payment_method, payment_sessions } = cart - let paymentSession = cart.payment_sessions.find( + if (!payment_sessions || !payment_sessions.length) { + throw new MedusaError( + MedusaError.Types.INVALID_ARGUMENT, + "cart must have payment sessions" + ) + } + + let paymentSession = payment_sessions.find( ps => ps.provider_id === payment_method.provider_id ) @@ -301,6 +308,7 @@ class OrderService extends BaseService { provider_id: paymentSession.provider_id, data: paymentData, }, + discounts: cart.discounts, shipping_methods: cart.shipping_methods, items: cart.items, shipping_address: cart.shipping_address, @@ -651,7 +659,7 @@ class OrderService extends BaseService { * @return {Order} return the decorated order. */ async decorate(order, fields, expandFields = []) { - const o = order.toObject() + const o = order o.shipping_total = await this.totalsService_.getShippingTotal(order) o.discount_total = await this.totalsService_.getDiscountTotal(order) o.tax_total = await this.totalsService_.getTaxTotal(order) diff --git a/packages/medusa/src/services/shipping-option.js b/packages/medusa/src/services/shipping-option.js index baea75d432..a1017bcb05 100644 --- a/packages/medusa/src/services/shipping-option.js +++ b/packages/medusa/src/services/shipping-option.js @@ -136,8 +136,7 @@ class ShippingOptionService extends BaseService { * @return {ShippingOption} the validated shipping option */ async validateCartOption(optionId, cart) { - const optionDoc = await this.retrieve(optionId) - let option = optionDoc.toObject() + const option = await this.retrieve(optionId) if (cart.region_id !== option.region_id) { throw new MedusaError(