fix(medusa-plugin-sendgrid): Use correct SendGrid client (#4524)
* fix(medusa-plugin-sendgrid): Use correct SendGrid instance * Create loud-fans-own.md * Adds tests * Use logger
This commit is contained in:
committed by
GitHub
parent
5affae9583
commit
fe6586e560
5
.changeset/loud-fans-own.md
Normal file
5
.changeset/loud-fans-own.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"medusa-plugin-sendgrid": patch
|
||||
---
|
||||
|
||||
fix(medusa-plugin-sendgrid): Use correct SendGrid client
|
||||
@@ -0,0 +1,196 @@
|
||||
import SendGridService from "../sendgrid"
|
||||
import SendGrid from "@sendgrid/mail"
|
||||
|
||||
jest.genMockFromModule("@sendgrid/mail")
|
||||
jest.mock("@sendgrid/mail")
|
||||
|
||||
const mockedSendGrid = SendGrid
|
||||
mockedSendGrid.setApiKey.mockResolvedValue(mockedSendGrid)
|
||||
mockedSendGrid.send.mockResolvedValue(Promise.resolve())
|
||||
|
||||
describe("SendGridService", () => {
|
||||
let sendGridService
|
||||
|
||||
const totalsService = {
|
||||
withTransaction: function () {
|
||||
return this
|
||||
},
|
||||
getCalculationContext: jest.fn().mockImplementation((order, lineItems) => {
|
||||
return Promise.resolve({})
|
||||
}),
|
||||
getLineItemTotals: jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({})
|
||||
}),
|
||||
getLineItemRefund: () => {},
|
||||
getTotal: (o) => {
|
||||
return o.total || 0
|
||||
},
|
||||
getGiftCardableAmount: (o) => {
|
||||
return o.subtotal || 0
|
||||
},
|
||||
getRefundedTotal: (o) => {
|
||||
return o.refunded_total || 0
|
||||
},
|
||||
getShippingTotal: (o) => {
|
||||
return o.shipping_total || 0
|
||||
},
|
||||
getGiftCardTotal: (o) => {
|
||||
return o.gift_card_total || 0
|
||||
},
|
||||
getDiscountTotal: (o) => {
|
||||
return o.discount_total || 0
|
||||
},
|
||||
getTaxTotal: (o) => {
|
||||
return o.tax_total || 0
|
||||
},
|
||||
getSubtotal: (o) => {
|
||||
return o.subtotal || 0
|
||||
},
|
||||
getPaidTotal: (o) => {
|
||||
return o.paid_total || 0
|
||||
},
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("should call SendGrid.send when template is configured and correct data is passed", async () => {
|
||||
const orderServiceMock = {
|
||||
retrieve: jest.fn().mockImplementation((data) => {
|
||||
return Promise.resolve({
|
||||
email: "test@test.com",
|
||||
currency_code: "usd",
|
||||
items: [],
|
||||
discounts: [],
|
||||
gift_cards: [],
|
||||
created_at: new Date(),
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
sendGridService = new SendGridService(
|
||||
{ orderService: orderServiceMock, totalsService },
|
||||
{
|
||||
api_key: "SG.test",
|
||||
order_placed_template: "lol",
|
||||
}
|
||||
)
|
||||
|
||||
await sendGridService.sendNotification("order.placed", { id: "test" })
|
||||
expect(mockedSendGrid.send).toBeCalled()
|
||||
})
|
||||
|
||||
it("should failed to send an email when event does not exist", async () => {
|
||||
expect.assertions(1)
|
||||
const orderServiceMock = {
|
||||
retrieve: jest.fn().mockImplementation((data) => {
|
||||
return Promise.resolve({
|
||||
email: "test@test.com",
|
||||
currency_code: "usd",
|
||||
items: [],
|
||||
discounts: [],
|
||||
gift_cards: [],
|
||||
created_at: new Date(),
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
sendGridService = new SendGridService(
|
||||
{ orderService: orderServiceMock, totalsService },
|
||||
{
|
||||
api_key: "SG.test",
|
||||
order_placed_template: "lol",
|
||||
}
|
||||
)
|
||||
|
||||
try {
|
||||
await sendGridService.sendNotification("some.non-existing_event", {
|
||||
id: "test",
|
||||
})
|
||||
} catch (error) {
|
||||
expect(error.message).toEqual(
|
||||
"Sendgrid service: No template was set for event: some.non-existing_event"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should failed to send an email when template id is not configured", async () => {
|
||||
expect.assertions(1)
|
||||
const orderServiceMock = {
|
||||
retrieve: jest.fn().mockImplementation((data) => {
|
||||
return Promise.resolve({
|
||||
email: "test@test.com",
|
||||
currency_code: "usd",
|
||||
items: [],
|
||||
discounts: [],
|
||||
gift_cards: [],
|
||||
created_at: new Date(),
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
sendGridService = new SendGridService(
|
||||
{ orderService: orderServiceMock, totalsService },
|
||||
{
|
||||
api_key: "SG.test",
|
||||
}
|
||||
)
|
||||
|
||||
try {
|
||||
await sendGridService.sendNotification("order.placed", {
|
||||
id: "test",
|
||||
})
|
||||
} catch (error) {
|
||||
expect(error.message).toEqual(
|
||||
"Sendgrid service: No template was set for event: order.placed"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should use localized template to send an email", async () => {
|
||||
const cartServiceMock = {
|
||||
retrieve: jest.fn().mockImplementation((data) => {
|
||||
return Promise.resolve({
|
||||
context: {
|
||||
locale: "de-DE",
|
||||
},
|
||||
})
|
||||
}),
|
||||
}
|
||||
const orderServiceMock = {
|
||||
retrieve: jest.fn().mockImplementation((data) => {
|
||||
return Promise.resolve({
|
||||
email: "test@test.com",
|
||||
currency_code: "usd",
|
||||
items: [],
|
||||
discounts: [],
|
||||
gift_cards: [],
|
||||
created_at: new Date(),
|
||||
cart_id: "test-id",
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
sendGridService = new SendGridService(
|
||||
{
|
||||
orderService: orderServiceMock,
|
||||
totalsService,
|
||||
cartService: cartServiceMock,
|
||||
},
|
||||
{
|
||||
api_key: "SG.test",
|
||||
localization: {
|
||||
"de-DE": {
|
||||
order_placed_template: "lol",
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
await sendGridService.sendNotification("order.placed", {
|
||||
id: "test",
|
||||
})
|
||||
expect(mockedSendGrid.send).toBeCalled()
|
||||
})
|
||||
})
|
||||
@@ -34,6 +34,7 @@ class SendGridService extends NotificationService {
|
||||
totalsService,
|
||||
productVariantService,
|
||||
giftCardService,
|
||||
logger,
|
||||
},
|
||||
options
|
||||
) {
|
||||
@@ -53,6 +54,7 @@ class SendGridService extends NotificationService {
|
||||
this.totalsService_ = totalsService
|
||||
this.productVariantService_ = productVariantService
|
||||
this.giftCardService_ = giftCardService
|
||||
this.logger_ = logger
|
||||
|
||||
SendGrid.setApiKey(options.api_key)
|
||||
}
|
||||
@@ -219,16 +221,20 @@ class SendGridService extends NotificationService {
|
||||
}
|
||||
|
||||
async sendNotification(event, eventData, attachmentGenerator) {
|
||||
const data = await this.fetchData(event, eventData, attachmentGenerator)
|
||||
|
||||
let templateId = this.getTemplateId(event)
|
||||
|
||||
if (!templateId) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, `Sendgrid service: No template was set for event: ${event}`)
|
||||
if (data.locale) {
|
||||
templateId = this.getLocalizedTemplateId(event, data.locale) || templateId
|
||||
}
|
||||
|
||||
const data = await this.fetchData(event, eventData, attachmentGenerator)
|
||||
if (!data) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, "Sendgrid service: Invalid event data was received")
|
||||
}
|
||||
if (!templateId) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Sendgrid service: No template was set for event: ${event}`
|
||||
)
|
||||
}
|
||||
|
||||
const attachments = await this.fetchAttachments(
|
||||
event,
|
||||
@@ -236,10 +242,6 @@ class SendGridService extends NotificationService {
|
||||
attachmentGenerator
|
||||
)
|
||||
|
||||
if (data.locale) {
|
||||
templateId = this.getLocalizedTemplateId(event, data.locale) || templateId
|
||||
}
|
||||
|
||||
const sendOptions = {
|
||||
template_id: templateId,
|
||||
from: this.options_.from,
|
||||
@@ -261,10 +263,15 @@ class SendGridService extends NotificationService {
|
||||
})
|
||||
}
|
||||
|
||||
let status
|
||||
await this.transporter_.sendMail(sendOptions)
|
||||
.then(() => { status = "sent" })
|
||||
.catch((error) => { status = "failed"; console.log(error) })
|
||||
let status
|
||||
await SendGrid.send(sendOptions)
|
||||
.then(() => {
|
||||
status = "sent"
|
||||
})
|
||||
.catch((error) => {
|
||||
status = "failed"
|
||||
this.logger_.error(error)
|
||||
})
|
||||
|
||||
// We don't want heavy docs stored in DB
|
||||
delete sendOptions.attachments
|
||||
@@ -303,18 +310,11 @@ class SendGridService extends NotificationService {
|
||||
|
||||
/**
|
||||
* Sends an email using SendGrid.
|
||||
* @param {string} templateId - id of template in SendGrid
|
||||
* @param {string} from - sender of email
|
||||
* @param {string} to - receiver of email
|
||||
* @param {Object} data - data to send in mail (match with template)
|
||||
* @param {Object} options - send options containing to, from, template, and more. Read more here: https://github.com/sendgrid/sendgrid-nodejs/tree/main/packages/mail
|
||||
* @return {Promise} result of the send operation
|
||||
*/
|
||||
async sendEmail(options) {
|
||||
try {
|
||||
return SendGrid.send(options)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
return await SendGrid.send(options)
|
||||
}
|
||||
|
||||
async orderShipmentCreatedData({ id, fulfillment_id }, attachmentGenerator) {
|
||||
|
||||
Reference in New Issue
Block a user