Skip to content

Commit

Permalink
feat(email-plugin): Improve error logging
Browse files Browse the repository at this point in the history
Closes #574
  • Loading branch information
michaelbromley committed Dec 11, 2020
1 parent c4bed2d commit 70cb932
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 17 deletions.
32 changes: 21 additions & 11 deletions packages/email-plugin/src/email-processor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { InternalServerError } from '@vendure/core';
import { InternalServerError, Logger } from '@vendure/core';
import fs from 'fs-extra';

import { isDevModeOptions } from './common';
import { loggerCtx } from './constants';
import { EmailSender } from './email-sender';
import { HandlebarsMjmlGenerator } from './handlebars-mjml-generator';
import { TemplateLoader } from './template-loader';
Expand Down Expand Up @@ -50,15 +51,24 @@ export class EmailProcessor {
}

async process(data: IntermediateEmailDetails) {
const bodySource = await this.templateLoader.loadTemplate(data.type, data.templateFile);
const generated = await this.generator.generate(
data.from,
data.subject,
bodySource,
data.templateVars,
);
const emailDetails = { ...generated, recipient: data.recipient };
await this.emailSender.send(emailDetails, this.transport);
return true;
try {
const bodySource = await this.templateLoader.loadTemplate(data.type, data.templateFile);
const generated = await this.generator.generate(
data.from,
data.subject,
bodySource,
data.templateVars,
);
const emailDetails = { ...generated, recipient: data.recipient };
await this.emailSender.send(emailDetails, this.transport);
return true;
} catch (err: unknown) {
if (err instanceof Error) {
Logger.error(err.message, loggerCtx, err.stack);
} else {
Logger.error(String(err), loggerCtx);
}
return false;
}
}
}
20 changes: 15 additions & 5 deletions packages/email-plugin/src/event-handler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { LanguageCode } from '@vendure/common/lib/generated-types';
import { Type } from '@vendure/common/lib/shared-types';
import { Injector } from '@vendure/core';
import { Injector, Logger } from '@vendure/core';

import { loggerCtx } from './constants';
import { EmailEventListener, EmailTemplateConfig, SetTemplateVarsFn } from './event-listener';
import { EventWithAsyncData, EventWithContext, IntermediateEmailDetails, LoadDataFn } from './types';

Expand Down Expand Up @@ -178,10 +179,19 @@ export class EmailEventHandler<T extends string = string, Event extends EventWit
}
}
if (this instanceof EmailEventHandlerWithAsyncData) {
(event as EventWithAsyncData<Event, any>).data = await this._loadDataFn({
event,
injector,
});
try {
(event as EventWithAsyncData<Event, any>).data = await this._loadDataFn({
event,
injector,
});
} catch (err: unknown) {
if (err instanceof Error) {
Logger.error(err.message, loggerCtx, err.stack);
} else {
Logger.error(String(err), loggerCtx);
}
return;
}
}
if (!this.setRecipientFn) {
throw new Error(
Expand Down
72 changes: 72 additions & 0 deletions packages/email-plugin/src/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { DEFAULT_CHANNEL_CODE } from '@vendure/common/lib/shared-constants';
import {
EventBus,
LanguageCode,
Logger,
Order,
OrderStateTransitionEvent,
PluginCommonModule,
ProcessContextModule,
RequestContext,
VendureEvent,
} from '@vendure/core';
import { TestingLogger } from '@vendure/testing';
import path from 'path';

import { orderConfirmationHandler } from './default-email-handlers';
Expand All @@ -25,6 +27,8 @@ describe('EmailPlugin', () => {
let onSend: jest.Mock;
let module: TestingModule;

const testingLogger = new TestingLogger(() => jest.fn());

async function initPluginWithHandlers(
handlers: Array<EmailEventHandler<string, any>>,
options?: Partial<EmailPluginOptions>,
Expand All @@ -51,6 +55,9 @@ describe('EmailPlugin', () => {
providers: [MockService],
}).compile();

Logger.useLogger(testingLogger);
module.useLogger(new Logger());

const plugin = module.get(EmailPlugin);
eventBus = module.get(EventBus);
await plugin.onVendureBootstrap();
Expand Down Expand Up @@ -492,6 +499,71 @@ describe('EmailPlugin', () => {
expect(onSend.mock.calls[0][0].subject).toBe(`Order confirmation for #${order.code}`);
});
});

describe('error handling', () => {
it('Logs an error if the template file is not found', async () => {
const ctx = RequestContext.deserialize({
_channel: { code: DEFAULT_CHANNEL_CODE },
_languageCode: LanguageCode.en,
} as any);
testingLogger.errorSpy.mockClear();

const handler = new EmailEventListener('no-template')
.on(MockEvent)
.setFrom('"test from" <[email protected]>')
.setRecipient(() => '[email protected]')
.setSubject('Hello {{ subjectVar }}');

await initPluginWithHandlers([handler]);

eventBus.publish(new MockEvent(ctx, true));
await pause();
expect(testingLogger.errorSpy.mock.calls[0][0]).toContain(`ENOENT: no such file or directory`);
});

it('Logs a Handlebars error if the template is invalid', async () => {
const ctx = RequestContext.deserialize({
_channel: { code: DEFAULT_CHANNEL_CODE },
_languageCode: LanguageCode.en,
} as any);
testingLogger.errorSpy.mockClear();

const handler = new EmailEventListener('bad-template')
.on(MockEvent)
.setFrom('"test from" <[email protected]>')
.setRecipient(() => '[email protected]')
.setSubject('Hello {{ subjectVar }}');

await initPluginWithHandlers([handler]);

eventBus.publish(new MockEvent(ctx, true));
await pause();
expect(testingLogger.errorSpy.mock.calls[0][0]).toContain(`Parse error on line 3:`);
});

it('Logs an error if the loadData method throws', async () => {
const ctx = RequestContext.deserialize({
_channel: { code: DEFAULT_CHANNEL_CODE },
_languageCode: LanguageCode.en,
} as any);
testingLogger.errorSpy.mockClear();

const handler = new EmailEventListener('bad-template')
.on(MockEvent)
.setFrom('"test from" <[email protected]>')
.setRecipient(() => '[email protected]')
.setSubject('Hello {{ subjectVar }}')
.loadData(context => {
throw new Error('something went horribly wrong!');
});

await initPluginWithHandlers([handler]);

eventBus.publish(new MockEvent(ctx, true));
await pause();
expect(testingLogger.errorSpy.mock.calls[0][0]).toContain(`something went horribly wrong!`);
});
});
});

const pause = () => new Promise(resolve => setTimeout(resolve, 100));
Expand Down
2 changes: 1 addition & 1 deletion packages/email-plugin/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export interface TestingTransportOptions {
export interface EmailGenerator<T extends string = any, E extends VendureEvent = any> {
/**
* @description
* Any neccesary setup can be performed here.
* Any necessary setup can be performed here.
*/
onInit?(options: EmailPluginOptions): void | Promise<void>;

Expand Down
5 changes: 5 additions & 0 deletions packages/email-plugin/test-templates/bad-template/body.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{ this is a bad Handlbars template }}

{{ < designed }}

{{ to produce an error!! }}}

0 comments on commit 70cb932

Please sign in to comment.