-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add remove coupon from cart mutation
Signed-off-by: vanpho93 <vanpho02@gmail.com>
- Loading branch information
Showing
8 changed files
with
265 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
import applyCouponToCart from "./applyCouponToCart.js"; | ||
import createStandardCoupon from "./createStandardCoupon.js"; | ||
import removeCouponFromCart from "./removeCouponFromCart.js"; | ||
|
||
export default { | ||
applyCouponToCart, | ||
createStandardCoupon | ||
createStandardCoupon, | ||
removeCouponFromCart | ||
}; |
62 changes: 62 additions & 0 deletions
62
packages/api-plugin-promotions-coupons/src/mutations/removeCouponFromCart.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import SimpleSchema from "simpl-schema"; | ||
import ReactionError from "@reactioncommerce/reaction-error"; | ||
import Logger from "@reactioncommerce/logger"; | ||
import hashToken from "@reactioncommerce/api-utils/hashToken.js"; | ||
import _ from "lodash"; | ||
|
||
const inputSchema = new SimpleSchema({ | ||
shopId: String, | ||
cartId: String, | ||
promotionId: String, | ||
cartToken: { | ||
type: String, | ||
optional: true | ||
} | ||
}); | ||
|
||
/** | ||
* @summary Remove a coupon from a cart | ||
* @param {Object} context - The application context | ||
* @param {Object} input - The input | ||
* @returns {Promise<Object>} - The updated cart | ||
*/ | ||
export default async function removeCouponFromCart(context, input) { | ||
inputSchema.validate(input); | ||
|
||
const { collections: { Cart, Accounts }, userId } = context; | ||
const { shopId, cartId, promotionId, cartToken } = input; | ||
|
||
const selector = { shopId }; | ||
|
||
if (cartId) selector._id = cartId; | ||
|
||
if (cartToken) { | ||
selector.anonymousAccessToken = hashToken(cartToken); | ||
} else { | ||
const account = (userId && (await Accounts.findOne({ userId }))) || null; | ||
|
||
if (!account) { | ||
Logger.error(`Cart not found for user with ID ${userId}`); | ||
throw new ReactionError("invalid-params", "Cart not found"); | ||
} | ||
|
||
selector.accountId = account._id; | ||
} | ||
|
||
const cart = await Cart.findOne(selector); | ||
if (!cart) { | ||
Logger.error(`Cart not found for user with ID ${userId}`); | ||
throw new ReactionError("invalid-params", "Cart not found"); | ||
} | ||
|
||
const newAppliedPromotions = _.filter(cart.appliedPromotions, (appliedPromotion) => appliedPromotion._id !== promotionId); | ||
if (newAppliedPromotions.length === cart.appliedPromotions.length) { | ||
Logger.error(`Promotion ${promotionId} not found on cart ${cartId}`); | ||
throw new ReactionError("invalid-params", "Can't remove coupon because it's not on the cart"); | ||
} | ||
|
||
cart.appliedPromotions = newAppliedPromotions; | ||
|
||
const updatedCart = await context.mutations.saveCart(context, cart); | ||
return updatedCart; | ||
} |
91 changes: 91 additions & 0 deletions
91
packages/api-plugin-promotions-coupons/src/mutations/removeCouponFromCart.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import mockContext from "@reactioncommerce/api-utils/tests/mockContext.js"; | ||
import removeCouponFromCart from "./removeCouponFromCart.js"; | ||
|
||
test("throws if validation check fails", async () => { | ||
const input = { shopId: "123", cartId: "123" }; | ||
|
||
try { | ||
await removeCouponFromCart(mockContext, input); | ||
} catch (error) { | ||
expect(error.error).toEqual("validation-error"); | ||
} | ||
}); | ||
|
||
test("throws error when cart does not exist with userId", async () => { | ||
const input = { shopId: "123", cartId: "123", promotionId: "promotionId" }; | ||
mockContext.collections = { | ||
Accounts: { | ||
findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(null)) | ||
}, | ||
Cart: { | ||
findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(null)) | ||
} | ||
}; | ||
|
||
try { | ||
await removeCouponFromCart(mockContext, input); | ||
} catch (error) { | ||
expect(error.message).toEqual("Cart not found"); | ||
} | ||
}); | ||
|
||
test("throws error when cart does not exist", async () => { | ||
const input = { shopId: "123", cartId: "123", promotionId: "promotionId" }; | ||
const account = { _id: "accountId" }; | ||
mockContext.collections = { | ||
Accounts: { | ||
findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(account)) | ||
}, | ||
Cart: { | ||
findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(null)) | ||
} | ||
}; | ||
|
||
try { | ||
await removeCouponFromCart(mockContext, input); | ||
} catch (error) { | ||
expect(error.error).toEqual("invalid-params"); | ||
expect(error.message).toEqual("Cart not found"); | ||
} | ||
}); | ||
|
||
test("throws error when promotionId is not found on cart", async () => { | ||
const input = { shopId: "123", cartId: "123", promotionId: "promotionId" }; | ||
const account = { _id: "accountId" }; | ||
const cart = { appliedPromotions: [{ _id: "promotionId2" }] }; | ||
mockContext.collections = { | ||
Accounts: { | ||
findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(account)) | ||
}, | ||
Cart: { | ||
findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(cart)) | ||
} | ||
}; | ||
|
||
try { | ||
await removeCouponFromCart(mockContext, input); | ||
} catch (error) { | ||
expect(error.error).toEqual("invalid-params"); | ||
expect(error.message).toEqual("Can't remove coupon because it's not on the cart"); | ||
} | ||
}); | ||
|
||
test("removes coupon from cart", async () => { | ||
const input = { shopId: "123", cartId: "123", promotionId: "promotionId" }; | ||
const account = { _id: "accountId" }; | ||
const cart = { appliedPromotions: [{ _id: "promotionId" }] }; | ||
mockContext.collections = { | ||
Accounts: { | ||
findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(account)) | ||
}, | ||
Cart: { | ||
findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(cart)) | ||
} | ||
}; | ||
mockContext.mutations = { | ||
saveCart: jest.fn().mockName("mutations.saveCart").mockReturnValueOnce(Promise.resolve({})) | ||
}; | ||
|
||
const result = await removeCouponFromCart(mockContext, input); | ||
expect(result).toEqual({}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 3 additions & 1 deletion
4
packages/api-plugin-promotions-coupons/src/resolvers/Mutation/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
import applyCouponToCart from "./applyCouponToCart.js"; | ||
import createStandardCoupon from "./createStandardCoupon.js"; | ||
import removeCouponFromCart from "./removeCouponFromCart.js"; | ||
|
||
export default { | ||
applyCouponToCart, | ||
createStandardCoupon | ||
createStandardCoupon, | ||
removeCouponFromCart | ||
}; |
14 changes: 14 additions & 0 deletions
14
packages/api-plugin-promotions-coupons/src/resolvers/Mutation/removeCouponFromCart.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* @method removeCouponFromCart | ||
* @summary Apply a coupon to the cart | ||
* @param {Object} _ unused | ||
* @param {Object} args.input - The input arguments | ||
* @param {Object} args.input.cartId - The cart ID | ||
* @param {Object} args.input.couponCode - The promotion IDs | ||
* @param {Object} context - The application context | ||
* @returns {Promise<Object>} with updated cart | ||
*/ | ||
export default async function removeCouponFromCart(_, { input }, context) { | ||
const updatedCart = await context.mutations.removeCouponFromCart(context, input); | ||
return { cart: updatedCart }; | ||
} |
15 changes: 15 additions & 0 deletions
15
packages/api-plugin-promotions-coupons/src/resolvers/Mutation/removeCouponFromCart.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import mockContext from "@reactioncommerce/api-utils/tests/mockContext.js"; | ||
import removeCouponFromCart from "./removeCouponFromCart.js"; | ||
|
||
test("calls mutations.removeCouponFromCart and returns the result", async () => { | ||
const input = { cartId: "123", couponCode: "CODE" }; | ||
const result = { _id: "123 " }; | ||
mockContext.mutations = { | ||
removeCouponFromCart: jest.fn().mockName("mutations.removeCouponFromCart").mockReturnValueOnce(Promise.resolve(result)) | ||
}; | ||
|
||
const removedCoupon = await removeCouponFromCart(null, { input }, mockContext); | ||
|
||
expect(removedCoupon).toEqual({ cart: result }); | ||
expect(mockContext.mutations.removeCouponFromCart).toHaveBeenCalledWith(mockContext, input); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters