Skip to content

Commit

Permalink
send engage content to single email address to test (erxes#2586)
Browse files Browse the repository at this point in the history
  • Loading branch information
Buyantogtokh authored Jan 13, 2021
1 parent f6b26c4 commit 695c77c
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 45 deletions.
70 changes: 56 additions & 14 deletions api/src/__tests__/engageMessageMutations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -774,20 +774,6 @@ describe('engage message mutation tests', () => {
{ email: '[email protected]' }
);

mock = sinon.stub(api, 'engagesSendTestEmail').callsFake(() => {
return Promise.resolve('true');
});

await check(
`
mutation engageMessageSendTestEmail($from: String!, $to: String!, $content: String!) {
engageMessageSendTestEmail(from: $from, to: $to, content: $content)
}
`,
'engageMessageSendTestEmail',
{ from: '[email protected]', to: '[email protected]', content: 'content' }
);

mock.restore();
});

Expand Down Expand Up @@ -827,4 +813,60 @@ describe('engage message mutation tests', () => {

expect(response.fromIntegration._id).toBe(integration._id);
});

test('Test engageMessageSendTestEmail()', async () => {
const sendRequest = args => {
return graphqlRequest(
`
mutation engageMessageSendTestEmail(
$from: String!,
$to: String!,
$content: String!,
$title: String!
) {
engageMessageSendTestEmail(from: $from, to: $to, content: $content, title: $title)
}
`,
'engageMessageSendTestEmail',
args,
{ dataSources }
);
};

const mock = sinon
.stub(dataSources.EngagesAPI, 'engagesSendTestEmail')
.callsFake(() => {
return Promise.resolve('true');
});

const params = {
from: '[email protected]',
to: '[email protected]',
content: 'content',
title: 'hello'
};

const response = await sendRequest(params);

expect(response).toBe('true');

// check missing title
try {
params.title = '';

await sendRequest(params);
} catch (e) {
expect(e[0].message).toBe(
'Email content, title, from address or to address is missing'
);
}

// check with valid customer
params.to = _customer.primaryEmail;
params.title = 'hello';

await sendRequest(params);

mock.restore();
});
});
39 changes: 35 additions & 4 deletions api/src/data/resolvers/mutations/engages.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
import * as _ from 'underscore';
import { EngageMessages } from '../../../db/models';
import { Customers, EngageMessages, Users } from '../../../db/models';
import { METHODS } from '../../../db/models/definitions/constants';
import { IEngageMessage } from '../../../db/models/definitions/engages';
import { MESSAGE_KINDS, MODULE_NAMES } from '../../constants';
import { putCreateLog, putDeleteLog, putUpdateLog } from '../../logUtils';
import { checkPermission } from '../../permissions/wrappers';
import { IContext } from '../../types';
import { registerOnboardHistory, sendToWebhook } from '../../utils';
import {
registerOnboardHistory,
replaceEditorAttributes,
sendToWebhook
} from '../../utils';
import { send } from './engageUtils';

interface IEngageMessageEdit extends IEngageMessage {
_id: string;
}

interface ITestEmailParams {
from: string;
to: string;
content: string;
title: string;
}

/**
* These fields contain too much data & it's inappropriate
* to save such data in each log row
Expand Down Expand Up @@ -166,12 +177,32 @@ const engageMutations = {

async engageMessageSendTestEmail(
_root,
args,
args: ITestEmailParams,
{ dataSources, user }: IContext
) {
await registerOnboardHistory({ type: 'engageSendTestEmail', user });

return dataSources.EngagesAPI.engagesSendTestEmail(args);
const { content, from, to, title } = args;

if (!(content && from && to && title)) {
throw new Error(
'Email content, title, from address or to address is missing'
);
}

const customer = await Customers.findOne({ primaryEmail: to });
const targetUser = await Users.findOne({ email: to });

const { replacedContent } = await replaceEditorAttributes({
content,
customer,
user: targetUser
});

return dataSources.EngagesAPI.engagesSendTestEmail({
...args,
content: replacedContent
});
}
};

Expand Down
2 changes: 1 addition & 1 deletion api/src/data/schema/engage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,5 @@ export const mutations = `
engagesUpdateConfigs(configsMap: JSON!): JSON
engageMessageVerifyEmail(email: String!): String
engageMessageRemoveVerifiedEmail(email: String!): String
engageMessageSendTestEmail(from: String!, to: String!, content: String!): String
engageMessageSendTestEmail(from: String!, to: String!, content: String!, title: String!): String
`;
18 changes: 6 additions & 12 deletions api/src/data/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,8 @@ import * as path from 'path';
import * as puppeteer from 'puppeteer';
import * as strip from 'strip';
import * as xlsxPopulate from 'xlsx-populate';
import * as models from '../db/models'
import {
Customers,
OnboardingHistories,
Users,
Webhooks
} from '../db/models';
import * as models from '../db/models';
import { Customers, OnboardingHistories, Users, Webhooks } from '../db/models';
import { IBrandDocument } from '../db/models/definitions/brands';
import { WEBHOOK_STATUS } from '../db/models/definitions/constants';
import { ICustomer } from '../db/models/definitions/customers';
Expand Down Expand Up @@ -479,7 +474,7 @@ export const readFile = utils.readFile;
* Create default or ses transporter
*/
export const createTransporter = async ({ ses }) => {
return utils.createTransporter(models, memoryStorage, { ses })
return utils.createTransporter(models, memoryStorage, { ses });
};

export type IEmailParams = IEmailParamsC;
Expand All @@ -493,8 +488,8 @@ interface IReplacer {
*/
export const replaceEditorAttributes = async (args: {
content: string;
customer?: ICustomer;
user?: IUser;
customer?: ICustomer | null;
user?: IUser | null;
customerFields?: string[];
brand?: IBrandDocument;
}): Promise<{
Expand Down Expand Up @@ -695,8 +690,7 @@ export const sendMobileNotification = async ({
body,
customerId,
conversationId

})
});
};

export const paginate = utils.paginate;
Expand Down
4 changes: 2 additions & 2 deletions engages-email-sender/src/api/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,15 @@ router.post('/remove-verified-email', async (req, res, next) => {
router.post('/send-test-email', async (req, res, next) => {
debugRequest(debugEngages, req);

const { from, to, content } = req.body;
const { from, to, content, title } = req.body;

const transporter = await createTransporter();

try {
const response = await transporter.sendMail({
from,
to,
subject: content,
subject: title,
html: content
});

Expand Down
7 changes: 6 additions & 1 deletion ui/src/__tests__/engage/components/EmailForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ describe('EmailForm component', () => {
dateTime: 'string'
};

const sendTestEmail = () => {
console.log('test email');
};

const defaultProps = {
onChange: (
name: 'email' | 'content' | 'fromUserId' | 'scheduleDate',
Expand All @@ -58,7 +62,8 @@ describe('EmailForm component', () => {
fromUserId: 'string',
content: 'string',
scheduleDate: testIEngageScheduleDate,
verifiedEmails: []
verifiedEmails: [],
sendTestEmail
};

test('renders successfully', () => {
Expand Down
69 changes: 67 additions & 2 deletions ui/src/modules/engage/components/EmailForm.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { IUser } from 'modules/auth/types';
import Button from 'modules/common/components/Button';
import ErrorMsg from 'modules/common/components/ErrorMsg';
import FormControl from 'modules/common/components/form/Control';
import FormGroup from 'modules/common/components/form/Group';
Expand All @@ -12,6 +14,7 @@ import { ISelectedOption } from 'modules/common/types';
import { __ } from 'modules/common/utils';
import {
EditorContainer,
TestEmailWrapper,
VerifyCancel,
VerifyCheck,
VerifyStatus
Expand All @@ -22,13 +25,31 @@ import { IEmailFormProps, IEngageEmail, IEngageScheduleDate } from '../types';
import { generateEmailTemplateParams } from '../utils';
import Scheduler from './Scheduler';

type Props = IEmailFormProps & { verifiedEmails: string[]; error?: string };
type EmailParams = {
content: string;
from: string;
to: string;
title: string;
};

type Props = IEmailFormProps & {
verifiedEmails: string[];
error?: string;
sendTestEmail: (params: EmailParams) => void;
};

type State = {
fromUserId: string;
content: string;
email: IEngageEmail;
scheduleDate?: IEngageScheduleDate;
testEmail?: string;
};

const getEmail = (users: IUser[], fromUserId: string): string => {
const user = users.find(u => u._id === fromUserId);

return user && user.email ? user.email : '';
};

class EmailForm extends React.Component<Props, State> {
Expand All @@ -39,7 +60,8 @@ class EmailForm extends React.Component<Props, State> {
fromUserId: props.fromUserId,
content: props.content,
email: props.email,
scheduleDate: props.scheduleDate
scheduleDate: props.scheduleDate,
testEmail: getEmail(props.users, props.fromUserId)
};
}

Expand Down Expand Up @@ -153,6 +175,48 @@ class EmailForm extends React.Component<Props, State> {
);
}

renderTestEmailSection() {
const { email, sendTestEmail, users } = this.props;
const { fromUserId, testEmail, content } = this.state;

const onChange = e => {
const value = (e.target as HTMLInputElement).value;

this.setState({ testEmail: value });
};

const sendAsTest = () => {
sendTestEmail({
from: getEmail(users, fromUserId),
to: testEmail || '',
content,
title: email && email.subject ? email.subject : ''
});
};

return (
<TestEmailWrapper>
<FormGroup>
<ControlLabel>Send to the following email as test:</ControlLabel>
<HelpPopover>Only one email address must be typed</HelpPopover>
<FormControl
type="text"
onChange={onChange}
defaultValue={testEmail}
/>
<Button
disabled={testEmail ? false : true}
btnStyle="primary"
icon="send"
onClick={sendAsTest}
>
Send
</Button>
</FormGroup>
</TestEmailWrapper>
);
}

render() {
const { attachments } = this.state.email;

Expand Down Expand Up @@ -247,6 +311,7 @@ class EmailForm extends React.Component<Props, State> {
</FormGroup>

{this.renderScheduler()}
{this.renderTestEmailSection()}
</FlexPad>

<FlexItem overflow="auto" count="2">
Expand Down
Loading

0 comments on commit 695c77c

Please sign in to comment.